在创建Section之后,我们需要获取该Section的vmaddr和这个外壳程序运行时的ASLR,然后才能正确跳转。
- 获取vmaddr
#import <mach-o/getsect.h> #import <mach-o/loader.h> #import <unistd.h> #import <stdio.h> #import <iostream> #if __arm64__ || __x86_64__ #define SEGMENT_COMMAND segment_command_64 #define SECTION section_64 #else #define SEGMENT_COMMAND segment_command #define SECTION section #endif int main() { @autoreleasepool { const struct SEGMENT_COMMAND * myseg = getsegbyname("__[data deleted]"); if (myseg) { printf("Segment __[data deleted] Init Prot: %d\n",myseg->initprot); printf("Segment __[data deleted] Max Prot: %d\n",myseg->maxprot); printf("Segment __[data deleted] vmaddr: 0x%llX\n",(unsigned long long)myseg->vmaddr); const struct SECTION * mysect = getsectbyname("__[data deleted]", "__code"); if (mysect) { printf("Section __code flags: %X\n",mysect->flags); std::cout<<"Section __code size: "<<mysect->size<<std::endl; printf("Section __code addr: 0x%llX\n",(unsigned long long)mysect->addr); } } } }
iPod touch 5下的运行结果,64位下会有所不同。
在MachOView中验证的确是拿到了正确的数据。
- 获取ASLR
那么接下来是获取ASLR。
先引入头文件
#import <dlfcn.h>
然后同样的,针对32位和64位处理一下。
#if __arm64__ || __x86_64__ #define FILE_BASE_ADDR 0x100000000 #else #define FILE_BASE_ADDR 0x4000 #endif
最后在适当的地方加上:
Dl_info info; if (dladdr((const void *)main, &info)){ int * fbase = (int*)info.dli_fbase; printf("ASLR: 0x%lX\n", reinterpret_cast<unsigned long>(fbase) - FILE_BASE_ADDR); }
我们可以通过在lldb里执行:
image list -o -f
来验证我们所取得的地址的正确性。如下图