从MachO、DYLD到安全防护

1、MachO

其实MachO是一种文件格式,它包含了可执行文件、动态库、静态库、目标文件、dyld等。
对于我们编写的应用程序,在编译后的app右键显示包内容,就能看到与包名一样的可执行文件,可以通过file 可执行文件指令查看该文件的具体信息。

file指令.png

上图可执行文件是arm64架构的,而有的应用可执行文件是胖二进制文件(也叫通用二进制文件格式的),会包含多种架构,比如arm64、armv7。我们也可以通过lipo命令实现拆分架构(通过-thin指令)和合并架构(通过-create指令),一般在拆分和合并静态库的时候用到。

MachO结构

  • Header 用于快速确认文件,比如cpu类型、文件类型
  • LoadCommands 用于指示加载器如何加载二进制文件
  • Data 用于存放数据,比如代码、字符串常量、类、方法等
2、DYLD

dyld,动态链接器,用来加载所有的库和可执行文件。
dyld源码是苹果开放出来的,感兴趣的小伙伴可以下载源码查看分析下。

dyld加载流程

  • 程序执行从_dyld_start 开始
  • 进入dyld:main函数(这里做了很多工作)
    • 配置环境变量
    • 加载共享缓存库(一开始就判断是否是禁用,iOS无法被禁用)
    • 实例化主程序
    • 加载动态库
      • 最先加载插入的动态库,通过判断环境变量DYLD_INSERT_LIBRARIES是否为空。
      • 然后加载系统的动态库
      • 再加载weak动态库
    • 初始化主程序
    • 初始化方法(这里是最关键的地方)
      • 经过一系列初始化,调用notifySingle函数,该函数会执行一个回调。通过断点调试可以发现,这个回调是_objc_init 初始化的时候赋值的一个函数load_images,在load_images里面会执行call_load_methods函数,而call_load_methods函数内部会循环调用各个类的load方法。
      • doModInitFunctions函数。内部会调用带atrribute((constructor))的c++函数。
      • 返回主程序的入口函数。开始进入主程序的main函数。
3、安全防护

(1)RESTRICT
通过对dyld源码的分析,可以找到一个安全防护的突破口,就是在加载动态库的第一步,通过判断环境变量DYLD_INSERT_LIBRARIES是否为NULL,来决定是否加载插入的动态库,通常越狱插件都是在这个时候加载的。那我们只要想办法把环境变量DYLD_INSERT_LIBRARIES移除掉,就可以解决这种类型的进攻。系统也确实给我们提供了一个入口,就是通过RESTRICT段,具体操作如下:
打开自己要做防护的应用程序,选择Target -> Build Settings -> Other Linker Flags -> 添加-Wl,sectcreate,__RESTRICT,__restrict,/dev/null(友情提示:Xcode11中编译会报错,旧版本Xcode可用,跑不通的小伙伴表打我😂)。添加完成后,编译一下,把可执行文件拖到MachOView里面看一下,就会发现神奇的多了一个__RESTRICT段,你再Tweak一下试试😏

RESTRICT防护Tweak.png

(2)反调试Ptrace
ptrace(PT_DENY_ATTCH,0,0,0)拒绝进程被附加

  • 该函数防护的特点:
    • 程序被Xcode安装直接闪退
    • 通过终端附加失败
    • 用户正常启动能运行
  • 破解ptrace
    • 通过fishhook函数勾住ptrace
    • 判断参数1,是否拒绝附加,如果是,就直接返回

(3)反调试sysctl
sysctl这个函数的作用是去检测程序的状态。

  • sysctl(查询信息的数组(放字节码),数组的大小,结构信息的结构体指针,结构体大小,和2一样,和3一样)
    • 在接受信息的结构体中,kp_proc属性 有一个标记 p_flag
    • 查看第12位 是否为 1(1代表着有调试器附加)可通过P_TRACED查询
  • 破解sysctl
    • 通过fishhook函数勾住sysctl
    • 调用原始的函数
    • 取出结构一的标记判断
    • 通过异或 P_TRACED 取反。修改标记,达到破解的效果。

(4)其他方法

  • 提前执行:将检测函数放入Framwork中。
  • 二进制修改:找到相关函数,直接修改汇编。
  • 混淆类名、方法名:通过宏定义,写入PCH文件进行类名、方法名混淆。
  • 字符串加密:所有的字符串常量拆分成字符,然后通过异或运算隐藏字符串常量。
  • 防护fishhook:通过 dlopen()拿到模块句柄 、 通过 dlsym()获得函数地址。
  • syscall:通过syscall 调用系统函数,使用fishhook和lldb符号断点都拿不到。
    • syscall 对应的函数编号在 sys/syscall.h 文件里面
  • 汇编软中断的方式触发系统函数
    • mov w16,#0 中断根据x16里面的值跳转对应编号函数(和syscall编号一样)
    • svc #0x80 这条指令是触发中断
  • getenv 函数:该函数可以查询环境变量。我们可以通过查询DYLD_INSERT_LIBRARIES检测是否越狱状态。

防护的手段千千万,这里只是提供给小伙伴一个做防护的思路,毕竟进攻技术在发展,防护也一样😊

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342