iOS DEP研究(2)——获取vmaddr与ASLR

创建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位下会有所不同。

屏幕快照 2015-04-20 下午12.37.22

在MachOView中验证的确是拿到了正确的数据。

屏幕快照 2015-04-20 下午12.42.11

 


  •  获取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

来验证我们所取得的地址的正确性。如下图

屏幕快照 2015-04-20 下午12.54.56

Leave a Reply

Your email address will not be published. Required fields are marked *

4 × 2 =