iOS内存权限的一些思考

栏目: IOS · 发布时间: 1年前

来源: www.nevermoe.com

内容简介:iOS能否动态生成代码并执行?或者说iOS能否在运行时改变__text段的属性来改变程序代码?iOS的APP的代码段(__text)的权限默认是rx/rx的,也就是说是可读可执行,且max_protection也是可读可执行的。在这种情况下我们无法把代码段改为rw,修改代码,然后再改回rx进行执行。并且iOS限制了w和x权限无法同时出现。那么问题来了,在越狱机器上常用的hooking framework,比如Substitute, Cydia Substrate这样的库是如何做到inline hook的呢?

本文转载自:https://www.nevermoe.com/2019/02/27/ios内存权限的一些思考/,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

0x00 背景

iOS能否动态生成代码并执行?或者说 iOS 能否在运行时改变__text段的属性来改变程序代码?

0x01 详细

iOS的APP的代码段(__text)的权限默认是rx/rx的,也就是说是可读可执行,且max_protection也是可读可执行的。在这种情况下我们无法把代码段改为rw,修改代码,然后再改回rx进行执行。并且iOS限制了w和x权限无法同时出现。

那么问题来了,在越狱机器上常用的hooking framework,比如Substitute, Cydia Substrate这样的库是如何做到inline hook的呢?因为inline hook需要篡改 text段的内容,如果 text段不能被设置为rw,那么怎么实现篡改__text段的内存呢?

参考这篇 defcon的ppt 和Substitute的 源代码 我们可以总结出篡改__text段的方法:

  1. 使用mmap新建一块内存,把这块内存叫做new。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L383-L384
  2. 使用vm_copy把想要篡改的处于__text段内的内存(把这块内存叫target)拷贝到new里。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L394
  3. 使用mmap把target内存给unmap掉。因为这里调用mmap的时候使用了 MAP_FIXED 这个参数,所以mmap会隐式地unmap掉目标内存。(参考: If a mapping already exists for the portion of the processes address space that is to be mapped and the value MAP_FIXED was specified for flags, then the previous mappings for the affected pages are implicitly unmapped)。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L404
  4. 向new里写入想执行的代码。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L411-L416
  5. 调用mprotect把new改为rx。因为mmap出来的内存的max_protection是rwx,所以这里mprotect改权限没问题。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L431-L432
  6. 调用mach_vm_remap把new的内容反映回target里。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L438-L441
  7. 把newをunmap。 https://github.com/comex/substitute/blob/95f2beda374625dd503bfb51a758b6f6ced57887/lib/darwin/execmem.c#L447

0x02 实验

kern_return_t mach_vm_remap(vm_map_t, mach_vm_address_t *, mach_vm_size_t,
                        mach_vm_offset_t, int, vm_map_t, mach_vm_address_t,
                        boolean_t, vm_prot_t *, vm_prot_t *, vm_inherit_t);

int test_mprotect()
{
    unsigned long p = (unsigned long)(test_func) & ~(0x1000-0x1);
    NSLog(@"p: 0x%x", p);

    int err = 0;
    errno=0;

    mach_port_t task_self = mach_task_self();
    NSLog(@"port got: %d", task_self);

    void *new = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
                     MAP_ANON | MAP_SHARED, -1, 0);
    if (new )
        NSLog(@"mmap ok");
    else
        NSLog(@"mmap not ok");
    kern_return_t kr = vm_copy(task_self, p, 0x1000, (vm_address_t) new);
    if (!kr)
        NSLog(@"vm_copy ok");
    else {
        NSLog(@"vm_copy not ok:%d ", kr);
        NSLog(@"kr: %d, errno: %d", kr, errno);
    }

    int ret = mprotect(new, 0x1000, PROT_READ | PROT_EXEC);
    NSLog(@"ret: %d, errno: %d, addr: 0x%x", ret, errno, new);

    vm_prot_t c, m;
    vm_inherit_t inherit;
    mach_vm_address_t target = p;
    kr = mach_vm_remap(mach_task_self(), &target, 0x1000, 0,
                              VM_FLAGS_OVERWRITE, task_self,
                              (mach_vm_address_t) new, TRUE,
                              &c, &m, inherit);

    return err;
}
(0)                    0x8eca6081 000000010061c000-0000000100620000 [  16K]r-x/r-x COW /private/var/containers/Bundle/Application/F9E997B1-5FE5-4105-9988-8FD75FAE1850/iOSSample.app/iOSSample
(0)                    0x8e9eee81 0000000100620000-0000000100621000 [   4K]r-x/rwx COW 
(0)                    0x8eca6081 0000000100621000-0000000100628000 [  28K]r-x/r-x COW /private/var/containers/Bundle/Application/F9E997B1-5FE5-4105-9988-8FD75FAE1850/iOSSample.app/iOSSample
(0)                    0x8eca6081 0000000100628000-000000010062c000 [  16K]rw-/rw- COW /private/var/containers/Bundle/Application/F9E997B1-5FE5-4105-9988-8FD75FAE1850/iOSSample.app/iOSSample
(0)                    0x8eca6081 000000010062c000-0000000100638000 [  48K]r--/r-- COW /private/var/containers/Bundle/Application/F9E997B1-5FE5-4105-9988-8FD75FAE1850/iOSSample.app/iOSSample

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

关注码农网公众号

关注我们,获取更多IT资讯^_^


为你推荐:

相关软件推荐:

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

思考的技术

思考的技术

[日]大前研一 / 刘锦秀、谢育容 / 中信出版社 / 2010-11 / 32.00元

思路决定出路,没有了思路,也就没有了出路。 在充满危机与冒险的当下,我们缺乏的不是技巧而是揭发事务本质的动力和好奇心,缺少怀疑一切的心态和对固有模式的怠惰。 大前研一凭借他30多年的管理咨询经验,为我们提供了一种全新的可借鉴的思考方式。 企业和个人惟有改变既有的思考模式,放弃对过去成功经验的迷恋,学习有创意的思考方法,方能找到正确的经营思路。一起来看看 《思考的技术》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具