首页
社区
课程
招聘
[讨论]通过修改Mach-O中Load Commands进行全局进程劫持
2014-3-3 16:00 9234

[讨论]通过修改Mach-O中Load Commands进行全局进程劫持

2014-3-3 16:00
9234
Mach-O格式, 是Mach object文件格式的缩写,是一种可执行文件、目标代码、共享程序库、动态加载代码和核心DUMP(摘自度娘),类似于Win环境的PE、Linux环境的ELF。

Load Commands数据位于Mach Header数据之后,顾名思义为加载器命令。

    Structure overview
|--------------------------------
|          Mach Header     
|--------------------------------
|        Load Command 1
|        Load Command 2
|        Load Command n
|--------------------------------
|               Data            
|--------------------------------

Load Command定义有诸多,比如LC_SEGMENT、LC_SYMTAB、LC_SYMSEG等等,更多的LC定义可在<mach-o/loader.h>头文件中找到。利用otool -l命令可以查看一个mach-o文件的Load Commands。

利用Load Commands进行进程劫持的大致思路如下:
1.找一个任意进程启动都会加载的dylib;
2.为dylib写入自定义shellcode;
3.修改/添加此dylib的LC_ROUTINES命令,指向shellcode;
4.替换原dylib。

每步骤原理:
1.找到一个任意进程都会加载的dylib,比如/usr/lib/dyld,这样就达到了全局范围的效果。
2.写入shellcode,比如执行一段dlopen的代码,打开指定动态库,或是什么。
3.当链接器加入-init选项时,LC_ROUTINES就会被加入到Load Commands中,描述该dylib的入口。如此我们将原入口替换为shellcode的地址,在shellcode执行完再跳回原入口来运行自定义代码。
4.替换后开启任意进程看效果

以上是本人的假设,还没经过实践。欢迎大家讨论~

注意:任意进程都会加载的dylib一般都是进程严重依赖的系统库,无十足把握,切莫随意操作,否则后果自负。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞0
打赏
分享
最新回复 (5)
雪    币: 14
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
snakeninny 2014-3-4 23:24
2
0
我对MachO的头部不是很熟悉,这种深度的hack也不大会,但最近开始了这方面知识的学习,楼主的思路我觉得理论上是可行的,但在实际情况中,dylib的ctor并不一定在LC_ROUTINES段(当然楼主也说“当链接器加入-init选项时”才会有这个段),也可能在__mod_init_func段(拿我自己的dylib测试了一下,也可以参考http://blogs.embarcadero.com/eboling/2010/01/29/5639/),所以在替换前两个段都替换一下效果可能会更理想(具体用什么函数我也不是太清楚,但OSX/iOS好像有一系列函数是专门处理MachO头部的)
雪    币: 174
活跃值: (205)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
rainyx 1 2014-3-5 09:21
3
0
__mod_init_func这个学习了,按照博文原文
So, how do C++ static constructors get called?  Looking around a bit (see otool -lv), I see sections like __mod_init_func, with the S_MOD_INIT_FUNC_POINTERS flag set.
看得出应该是C++独有的。

在此严谨一下术语:
LC_ROUTINES为Load Commands的一种;
__mod_init_func是LC_SEGMENT_COMMAND中segment的一个section;
S_MOD_INIT_FUNC_POINTERS为section type,这种type的section数据只放了入口地址。

目前还没有深究Loader的内部原理,不过目测LC_ROUTINES和S_MOD_INIT_FUNC_POINTERS是可以并存的。在Load Commands后面往往有一大片空白,如果LC_ROUTINES不存在则手动构造一个便是

或者修改它依赖的DYLIBS估计也是可行的,实现起来似乎也更容易一些。
雪    币: 14
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
snakeninny 2014-3-5 13:53
4
0
MachO的头部格式我还不熟,不过手动加一个LC_ROUTINES应该是可以的。但是,如果LC_ROUTINES和S_MOD_INIT_FUNC_POINTERS如果并存的话,是不是必须两者定义的入口地址也要相同呢?如果不同,哪一个入口地址才是对的呢?
我也觉得加一个依赖dylib更好,不需要更改原来的头部,就保险一些
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tcp重置 2014-3-6 11:26
5
0
__mod_init_func 不是C++ 独有的。 每个dylib可以定义多个constructor, 这些constructor会被放入 __mod_init_func中,在dylib 装载完毕后执行。

https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html

1. 用clang -dynamiclib mylib.c -o mylib.dylib 编译下边的代码
2. 用otool -l 查看__mod_init_func的地址
3. 用xxd 读出地址里的值 (little endian)
4. 用otool -tV 反汇编 mylib.dylib, 发现定义的constructor地址正是3中读出来的值

#include <stdlib.h>                                                               
#include <stdio.h>                                                                 
                                                                                   
                                                                                   
__attribute__((constructor))                                                      
static void initializer()                                                         
{                                                                                 
    printf("%s\n", __FUNCTION__);                                                  
}                                                                                 
                                                                                   
                                                                                   
void func1()                                                                       
{                                                                                 
    printf("%s\n", __FUNCTION__);                                                  
}   

另外,严格意义上讲, dyld 不是dylib。 dyld 中也不应该存在 __mod_init_func
雪    币: 14
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
snakeninny 2014-3-6 22:54
6
0
唉,一开始就是搞的iOS,没搞过OSX,忘记参考OSX上的文档啦!感谢提醒
游客
登录 | 注册 方可回帖
返回