博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS应用代码注入防护
阅读量:6934 次
发布时间:2019-06-27

本文共 3909 字,大约阅读时间需要 13 分钟。

在应用开发过程中,我们不仅仅需要完成正常的业务逻辑,考虑应用性能、代码健壮相关的问题,我们有时还需要考虑到应用安全的问题。

那么应用安全的问题涉及到很多方面。比如防止静态分析的,代码混淆、逻辑混淆;防止重签名的,应用ID检测、甚至是代码的HASH检测等等。那么这篇文章我想聊聊关于代码的注入检测,因为发现随着iOS系统的更新,我们防护的手段发生了一些变化。

代码注入的方式

代码注入的方式大致分为两种

  • 越狱注入:通过修改DYLD_INSERT_LIBRARIES 环境变量的值,来插入动态库并执行
  • 非越狱注入:

    • 直接将自定义的Framwork或者dylib库打包进入APP并重签名。
    • 利用yololib修改MachO文件,添加库路径.在应用启动时,dyld会加载并执行.

早期防护方式

在工程的Build Settings中找到Other Linker Flages 并添加字段

-Wl,-sectcreate,__RESTRICT,__raestrict,/dev/null
此操作的作用是在可执行文件中添加一个Section.我们使用MachOView分析如下:
MachOView

当MachO文件中拥有这个字段,那么我们通过越狱环境插入动态库的方式就会失效.起到防护的作用.其原理在DYLD源码中可以分析到.

dyld源码分析

首先这里分析的版本是519.2.2版本.

我们可以通过检索DYLD_INSERT_LIBRARIES定位到_main函数加载插入动态库的代码如下.

// load any inserted libraries        if  ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {            for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib)                 loadInsertedDylib(*lib);        }

但是早在这个环境变量判断之前,dyld已经做了一个判断

if ( gLinkContext.processIsRestricted ) {        pruneEnvironmentVariables(envp, &apple);        // set again because envp and apple may have changed or moved        setContext(mainExecutableMH, argc, argv, envp, apple);    }

如果判断出进程是restricted!也就是当前进程是限制插入动态库的!就会调用pruneEnvironmentVariables函数移除相关的环境变量.

那么我们的processIsRestricted值什么时候为true呢?
继续分析源码可以发现两个关键函数影响其值.其中 hasRestrictedSegment 函数专门检测RESTRICT段

// any processes with setuid or setgid bit set or with __RESTRICT segment is restricted    if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {        gLinkContext.processIsRestricted = true;    }

通过注释也能发现.任意进程的__RESTRICT段设置为restricted动态库插入将被限制.

我们进入到processIsRestricted函数内,实现如下.

#if __MAC_OS_X_VERSION_MIN_REQUIREDstatic bool hasRestrictedSegment(const macho_header* mh){    const uint32_t cmd_count = mh->ncmds;    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));    const struct load_command* cmd = cmds;    for (uint32_t i = 0; i < cmd_count; ++i) {        switch (cmd->cmd) {            case LC_SEGMENT_COMMAND:            {                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;                //dyld::log("seg name: %s\n", seg->segname);                if (strcmp(seg->segname, "__RESTRICT") == 0) {                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {                        if (strcmp(sect->sectname, "__restrict") == 0)                             return true;                    }                }            }            break;        }        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);    }    return false;}

所以通过添加Other Linker Flags 在MachO中设置RESTRICT段赋值为restricted可以用来防护越狱的代码注入.

但是新版的dyld源码中去掉了__RESTRICT检测.从iOS10开始,这种防护手段已失效

DYLD_INSERT_LIBRARIES 检测

那么既然dyld加载过程不再检测__RESTRICT段了我们就手动的检测DYLD_INSERT_LIBRARIES环境变量.通过函数可查看当前进程环境变量的值.

char *env = getenv("DYLD_INSERT_LIBRARIES");  NSLog(@"%s",env);

在没有插入动态库时,env为null.

那么一旦为自己的应用写入插件时,我们就可以看到控制台的输出

2019-01-03 19:20:37.285 antiInject[7482:630392] /Library/MobileSubstrate/MobileSubstrate.dylib

白名单检测

那么上面的检测只可以检测越狱环境中的代码注入,在非越狱环境中,逆向工程师可以利用yololib工具注入动态库.所以我们可以检索一下自己的应用程序所加载的动态库是否是我们源程序所有

bool HKCheckWhitelist(){    int count = _dyld_image_count();    for (int i = 0; i < count; i++) {        //遍历拿到库名称!       const char * imageName = _dyld_get_image_name(i);        //判断是否在白名单内,应用本身的路径是不确定的,所以要除外.        if (!strstr(libraries, imageName)&&!strstr(imageName, "/var/mobile/Containers/Bundle/Application")) {            printf("该库非白名单之内!!\n%s",imageName);            return NO;        }    }    return YES;}

其中libraries变量是<q style="box-sizing: border-box;">白名单</q>.

小编给大家推荐一个iOS技术交流群:551346706!群内提供数据结构与算法、底层进阶、swift、逆向、底层面试题整合文档等免费资料!让我们来相互学习,为了今年的跳槽加分吧!

转载地址:http://pnwnl.baihongyu.com/

你可能感兴趣的文章
转://SIHA环境修改主机名实施步骤
查看>>
转://点评Oracle11g新特性之动态变量窥视
查看>>
三安光电圈钱凶猛 两年三轮再融资逾百亿
查看>>
【转】Apache配置中ProxyPassReverse指令的含义
查看>>
ASPxGridView之PreviewRow
查看>>
vsftd搭建
查看>>
洛谷P2057 【SHOI2007】善意的投票
查看>>
一篇关于java变量定义的文章
查看>>
jQuery获取json数据
查看>>
超出父控件怎么才能点击
查看>>
2011最新个人所得税计算器---起点3500元
查看>>
PHP随手记1--内置函数date
查看>>
【转】【RDS教程】专业DBA速成 - CPU优化篇
查看>>
UVa 11624,两次BFS
查看>>
关于输入流与输出流
查看>>
MVC分页控件
查看>>
“==”和equals方法的区别
查看>>
原生socket穿透HTTP代理服务器
查看>>
2019/5/12 查漏补缺
查看>>
超酷图片压缩工具,就是不支持批量
查看>>