在应用开发过程中,我们不仅仅需要完成正常的业务逻辑,考虑应用性能、代码健壮相关的问题,我们有时还需要考虑到应用安全的问题。
那么应用安全的问题涉及到很多方面。比如防止静态分析的,代码混淆、逻辑混淆;防止重签名的,应用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源码分析

首先这里分析的DYLD源码版本是519.2.2版本.
我们可以通过检索DYLD_INSERT_LIBRARIES定位到_main函数加载插入动态库的代码如下.

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

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

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

如果判断出进程是restricted!也就是当前进程是限制插入动态库的!就会调用pruneEnvironmentVariables函数移除相关的环境变量.
那么我们的processIsRestricted值什么时候为true呢?
继续分析源码可以发现两个关键函数影响其值.其中 hasRestrictedSegment 函数专门检测RESTRICT段

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

通过注释也能发现.任意进程的__RESTRICT段设置为restricted动态库插入将被限制.
我们进入到processIsRestricted函数内,实现如下.

  1. #if __MAC_OS_X_VERSION_MIN_REQUIRED
  2. static bool hasRestrictedSegment(const macho_header* mh)
  3. {
  4. const uint32_t cmd_count = mh->ncmds;
  5. const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
  6. const struct load_command* cmd = cmds;
  7. for (uint32_t i = 0; i < cmd_count; ++i) {
  8. switch (cmd->cmd) {
  9. case LC_SEGMENT_COMMAND:
  10. {
  11. const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
  12. //dyld::log("seg name: %s\n", seg->segname);
  13. if (strcmp(seg->segname, "__RESTRICT") == 0) {
  14. const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
  15. const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
  16. for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
  17. if (strcmp(sect->sectname, "__restrict") == 0)
  18. return true;
  19. }
  20. }
  21. }
  22. break;
  23. }
  24. cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
  25. }
  26. return false;
  27. }

所以通过添加Other Linker Flags 在MachO中设置RESTRICT段赋值为restricted可以用来防护越狱的代码注入.
但是新版的dyld源码中去掉了__RESTRICT检测.从iOS10开始,这种防护手段已失效

DYLD_INSERT_LIBRARIES 检测

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

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

在没有插入动态库时,env为null.
那么一旦为自己的应用写入插件时,我们就可以看到控制台的输出

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

白名单检测

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

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

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

作者:iOS开发_小迷糊
链接:https://www.jianshu.com/p/4b345acf6f08
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS应用代码注入防护的更多相关文章

  1. dyci——IOS动态代码注入

    有时候用xib,更改了布局需要重新运行才可以看到效果,对于比较复杂的应用尤其浪费时间,下面介绍一个工具dyci-不需要重Run应用,也能看到效果 yci的网址:https://github.com/D ...

  2. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  3. Method Swizzling以及AOP编程:在运行时进行代码注入-备用

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  4. PHP+Mysql注入防护与绕过

    今天给大家分享一个关于php常见的注入防护以及如何bypass的文章,文章内容来源国外某大佬总结,我做了一下整理,文章来源地址不详,下面正文开始.以下的方式也仅仅是针对黑名单的过滤有一定的效果,为了安 ...

  5. Method Swizzling以及AOP编程:在运行时进行代码注入-b

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  6. iOS中的crash防护(二)KVC造成的crash

      接上篇< iOS中的crash防护(一)unrecognized selector sent to instance> 我们攻克了找不到方法实现的crash,这一篇我这里主要分析一下在 ...

  7. HTML5 App的代码注入攻击

    原文链接 摘要 基于HTML5的手机app(译者注:以下简称HTML5 app)越来越流行了, 在大多数情况下它比native应用更容易适配不同的移动操作系统.它开发起来很方便,可以使用标准的web技 ...

  8. HTML5移动应用——小心代码注入风险

    近日在加州举行的移动安全技术大会上,Syracuse大学的研究者的研究报告显示HTML5移动应用可能会给企业带来新的安全风险.开发者的错误可能导致HTML5应用自动执行攻击者通过Wifi蓝牙或短信发送 ...

  9. iPhone手机越狱-逆向砸壳-代码注入

    iPhone手机越狱 逆向砸壳 代码注入 工具下载 操作越狱 安装待逆向应用(app) 使用OpenSSH连接手机 找到应用二进制文件地址 找到应用document沙盒地址 拷贝砸壳工具(dumpde ...

随机推荐

  1. AKKA Inbox收件箱

    起因 得到ActorRef就可以给actor发送消息,但无法接收多回复,也不知道actor是否停止 Inbox收件箱出现就是解决这两个问题 示例 package akka.demo.actor imp ...

  2. 网络基础 ----------- osi 与 一些协议

    1.了解 OSI ISO IOS ISO(全称:International Organization for Standardization) 国际标准化组织, 成立于1947年2月23日,制定全世界 ...

  3. 微信企业微信调试JS神器vConsole

    在js页面上放以下代码 <script src='https://cdn.bootcss.com/vConsole/3.3.2/vconsole.min.js'></script&g ...

  4. VUE控件 VueTreeselect 参数options的数据转换

    VueTreeselect 控件 <Treeselect :options="options" :normalizer="normalizer" plac ...

  5. AngularJS 的全选、反选实现

    目录 AngularJS 的全选.反选实现 一.需求 二.思路 三.实现 AngularJS 的全选.反选实现 一.需求 要使用 AngularJS 实现 checkbox 的全选.反选. 其中所有项 ...

  6. CSP2019: Lost and Found

    再不更就成鸽子了= = Day -INF to Day 0 不记得发生了什么 Day 1 今年HN用网上提交的方式收题?再也不怕因为交代码太晚增加省队名额了 开考看了一眼T1好像是模拟题,特地注意了\ ...

  7. 《MySQL实战45讲》学习笔记1——MySQL的基础架构

    在<极客时间>订阅了<MySQL实战45讲>专栏,总觉得看完和没看一样

  8. Map List Set的区别

    Map List Map的主要区别如下: set List 是实现了Collection接口的子接口:Map本身就是一个接口: list数据存放时有序的,允许有重复元素:set数据存放时无序的,不允许 ...

  9. npm err! Unexpected end of JSON input while parsing near解决办法

    npm install时出现npm err! Unexpected end of JSON input while parsing near错误 输入  npm cache clean --fore ...

  10. CentOS7 安装 浏览器

    firefox(火狐) sudo yum install firefox chrome(谷歌) 添加源:sudo wget http://repo.fdzh.org/chrome/google-chr ...