Beruflich Dokumente
Kultur Dokumente
Go
Search
Incomplete Codesign is a technique introduced by Comex in the Spirit jailbreak that allows untethered userland code execution. The idea is to plant a crafted Mach-O binary on the filesystem and have it loaded early during the boot process. This technique must be used in conjunction with another exploit to first plant the binary on the filesystem (like the MobileBackup Copy Exploit used in Spirit, or one of the DFU mode exploits Pwnage 2.0/Steaks4uce/Limera1n). Since executable pages must be signed, the crafted binary will have to abuse the loader or the dynamic linker functionalities to transfer execution to a ROP payload that will use existing (signed) code fragments (gadgets). The endgame is to have the userland code trigger and exploit a kernel vulnerability to achieve the jailbroken state. This is fixed as of iOS 4.3.4.
Credit
Comex
if (pid1_magic && g_use_gmalloc) { if (!getenv("DYLD_INSERT_LIBRARIES")) { setenv("DYLD_INSERT_LIBRARIES", "/usr/lib/libgmalloc.dylib", 1); setenv("MALLOC_STRICT_SIZE", "1", 1); execv(argv[0], argv); } else { unsetenv("DYLD_INSERT_LIBRARIES"); //this call is hijacked through interposition unsetenv("MALLOC_STRICT_SIZE"); } }
The crafted libgmalloc.dylib does not contains any executable segments, but instead uses the dyld interposition feature to redirect several exported functions to code fragments in the launchd binary. The interposed functions and their replacement addresses are chosen to force launchd to perform a stack pivot, and have SP pointing to a data segment in the shared library, allowing ROP code execution. The following functions are interposed to allow the stack pivot : _unsetenv, _launch_data_new_errno, _setrlimit, __exit,
_audit_token_to_au32, _launch_data_unpack, _launch_data_dict_iterate
interposed to create some gadgets used by the ROP payload). Once launchd has restarted itself with the crafted libgmalloc.dylib, the unsetenv function call will execute the following "interposition gadgets" :
LDR BL LDR BL R0, =aDyld_insert_li ; "DYLD_INSERT_LIBRARIES" _unsetenv R0, [R0] #R0 = 0x444c5944 = "DLYD" = little endian "DYLD" _launch_data_new_errno
#SP = 0x11130000 (start of ROP stack in __heap section) #ROP starts here
The ROP payloads in Spirit and Star exploit respectively the BPF and IOSurface kernel vulnerabilities in order to patch the kernel, and then restart launchd to continue the normal boot process. In iOS 4.1, dyld does a range check on the interposition targets to make sure that a dylib only redirects symbols to its own code segments, preventing the use of this feature to control code flow (since we cannot have executable code segments without a valid signature).
R12, R4, #0x58 R0, [R4,#0x44] R1, [R4,#0x48] R2, [R4,#0x4C] R3, [R4,#0x50] R12, [SP] R6 ; func(context.argc, context.argv, context.envp,
Since R11 points to the start of the section containing the initializers function pointers ( inits ), comex uses the following uncommon gadget to perform the stack pivot :
0x499ba000 LDMIBMI R11, {SP, PC} #increments R11 by 4, then pops SP and PC
Unlike Spirit's and Star's kernel exploits, the Packet Filter Kernel Exploit is not done in the ROP payload. Instead, the ROP payload is shorter and performs the following calls to run the exploit in an unsigned binary :
int zero = 0; char *params[] = {"/usr/lib/pf2", NULL}; char *env[] = {NULL}; /* these 3 function calls are done as ROP */ sysctlbyname("security.mac.proc_enforce", NULL, 0, &zero, sizeof(zero)); sysctlbyname("security.mac.vnode_enforce", NULL, 0, &zero, sizeof(zero)); execve("/usr/lib/pf2", params, env);
Setting the
security.mac.proc_enforce
and
security.mac.vnode_enforce
). The
vnode_enforce
completes. In iOS 4.3 beta, those variables are now read only.
Starting with iOS 4.2.1, dyld does a range check on the initializers so that the previous trick does not work (look for the "dyld: ignoring out of bounds initializer function %p in %s" string). However, for some unknown reason this check is only made if
ImageLoaderMachO::isDylib()
RC5, a crafted executable with an initializers section was used to replace the launchd binary and kickstart pod2g's HFS Legacy Volume Name Stack Buffer Overflow kernel exploit. The original launchd binary is renamed to punchd and is run as soon as the kernel exploit is done. In iOS 4.2.1 dyld the
inits
__text:2FE0C03C loc_2FE0C03C __text:2FE0C03C __text:2FE0C03E __text:2FE0C040 __text:2FE0C044 __text:2FE0C046 __text:2FE0C048 __text:2FE0C04A __text:2FE0C04C ...
R3, [SP,#4] R0, R6 R4, [R3,R8,LSL#2] ;Initializer func = inits[i]; R3, [R6] R3, [R3,#0x78] R3 ; ImageLoaderMachO::isDylib(void) R0, #0 loc_2FE0C0EE ;bypass range check
__text:2FE0C088 loc_2FE0C088 __text:2FE0C088 ADD.W __text:2FE0C08C LDR __text:2FE0C08E LDR __text:2FE0C090 LDR __text:2FE0C092 LDR __text:2FE0C094 STR.W __text:2FE0C098 BLX context.apple, &context.programVars)
R12, R5, #0x5C R0, [R5,#0x48] R1, [R5,#0x4C] R2, [R5,#0x50] R3, [R5,#0x54] R12, [SP] ; &context.programVars->mh R4 ; func(context.argc, context.argv, context.envp,
Since the first initializer clobbers R6 and shuffles the local variables by incrementing SP by 8, some conditions must be met for dyld to reach the second initializer call without crashing : the second initializer pointer has to be stored at offset 0x1004 (segPreferredLoadAddress(0) + 4) a pointer to a return 0 gadget must be present at offset 0x78 in the Mach-O file (context.programVars>mh[0x78])
ImageLoaderMachOCompressed::eachBind
also contains rebasing information but is not marked as position independent (?). The section calls functions.
__text:2FE0DEEA loc_2FE0DEEA __text:2FE0DEEA __text:2FE0DEEE __text:2FE0DEF2 __text:2FE0DEF4 __text:2FE0DEF6 __text:2FE0DEF8 __text:2FE0DEFA __text:2FE0DEFC __text:2FE0DEFE __text:2FE0DF02 __text:2FE0DF02 loc_2FE0DF02 __text:2FE0DF02 __text:2FE0DF04 __text:2FE0DF06 __text:2FE0DF08 __text:2FE0DF08 loc_2FE0DF08 __text:2FE0DF08 __DATA:__b
dyld::runTerminators doModInitFunctions
ImageLoaderMachO::doTermination ,
R3, [R11,#0x91] R6, [R5,#-4] ;Terminator func = terms[i-1]; R3, loc_2FE0DF02 R3, [SP,#0x28+var_28] R0, =(aDyldCallingTer - 0x2FE0DEFE) R1, R6 R0, PC ; "dyld: calling termination function %p i"... R2, [R3,#4] __ZN4dyld3logEPKcz ; dyld::log(char const*,...)
CMP
R4, #0
Here R5 points directly to the to the array of terminators ( terms ). The binary contains one termination function (in section section
ldm __DATA:__c )
that points to the following gadget which will transfer execution to the ROP payload (in
__DATA:__d ).
r5, {r2, r4, r5, r7, r8, r9, r10, r11, r12, sp, pc}
Saffron kickstart
The Saffron untether binary also uses relocations. Here, the standard format is used ( ARM_RELOC_VANILLA , not compressed
asrs bx LINKEDIT ).
context.apple ,
command. Values for this stack pointer and the ROP payload segment base are chosen epilog.
__text:2FE0C804 SUB.W SP, R7, #0x18 __text:2FE0C808 POP.W {R8,R10,R11} __text:2FE0C80C POP {R4-R7,PC} __text:2FE0C80C ; End of function ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&)
This page was last modified on 9 March 2012, at 22:19. This page has been accessed 56,015 times. Privacy policy About The iPhone Wiki Disclaimers