上一篇文章: "专注实践:解析lldb砸壳实战技巧"
在iOS逆向工程中,动态库注入是一项关键技术,允许开发者在运行时向目标应用程序注入自定义的动态链接库(Dylib),从而实现各种定制化的功能扩展和修改。
通过动态库注入,可以实现诸如破解应用程序、修改游戏内存数据、实现插件化功能等任务。本文将探讨动态库注入的原理、方法和实践技巧,帮助读者深入理解并掌握这一强大的逆向工程技术。
我们利用以下工具进行注入。
1.yololib
我们将以LLDB创建的项目作为案例。
下面是编译后的Mach-O文件,用MachOView进行打开,即下图.
我们另外创建一个项目,创建动态库LKDylib
+(void)load {
NSLog(@"~~success~~");
}
通过编译拿到动态库LKDylib
- 使用yololib命令
yololib binary dylib file
yololib LLDBTest LKDylib.framework
2024-04-12 15:12:01.570 yololib[21869:278509] dylib path @executable_path/LKDylib.framework
2024-04-12 15:12:01.570 yololib[21869:278509] dylib path @executable_path/LKDylib.framework
Reading binary: LLDBTest
2024-04-12 15:12:01.570 yololib[21869:278509] Thin 64bit binary!
2024-04-12 15:12:01.570 yololib[21869:278509] dylib size wow 64
2024-04-12 15:12:01.570 yololib[21869:278509] mach.ncmds 22
2024-04-12 15:12:01.570 yololib[21869:278509] mach.ncmds 23
2024-04-12 15:12:01.570 yololib[21869:278509] Patching mach_header..
2024-04-12 15:12:01.571 yololib[21869:278509] Attaching dylib..
2024-04-12 15:12:01.571 yololib[21869:278509] size 58
2024-04-12 15:12:01.571 yololib[21869:278509] complete!
我们再打开MachOView
我们所创建的动态库注入成功
2.optool
Yololib通常用于在iOS应用中实现动态库注入,通过修改应用的可执行文件,使其能够加载外部动态库,实现定制化的功能扩展。
optool主要用于操作Mach-O文件中的加载命令(Load Commands),例如添加、删除、替换加载命令等。
optool不仅可以添加动态库,还可以把已添加的动态库删除.
git clone https://github.com/alexzielenski/optool.git
cd optool
git submodule update --init --recursive
optool install -c load -p /Dylib/optool2/LKDylib.framework -t /Dylib/optool2/LLDBTest
Found thin header...
Inserting a LC_LOAD_DYLIB command for architecture: arm64
Successfully inserted a LC_LOAD_DYLIB command for arm64
Writing executable to /Dylib/optool2/LLDBTest...
动态库注入成功了
optool uninstall -p /Dylib/optool2/LKDylib.framework -t /Dylib/optool2/LLDBTest
Found thin header...
removing payload from LC_LOAD_UPWARD_DYLIB...
Successfully removed all entries for /Dylib/optool2/LKDylib.framework
Writing executable to /Dylib/optool2/LLDBTest...
注入动态库删除了
尽管成功进行了动态库注入,但是在尝试安装应用时可能会遇到签名问题,此时需要进行重签名才能顺利安装。
动态库注入原理
在Mach-O文件中,加载命令(Load Command)描述了文件在内存中的加载情况,其中与动态库相关的加载命令主要包括以下几种类型:
LC_LOAD_DYLIB:用于指定要加载的动态库文件的路径和名称。每个LC_LOAD_DYLIB命令描述了一个要加载的动态库,可以在运行时动态链接到目标进程中。
LC_ID_DYLIB:用于指定动态库的名称和版本信息,以及动态库的兼容性版本号等。LC_ID_DYLIB命令通常用于标识动态库本身的信息。
LC_REEXPORT_DYLIB:用于重新导出其他动态库的符号,使得当前动态库可以提供对其他动态库中符号的访问。
LC_LOAD_WEAK_DYLIB:类似于LC_LOAD_DYLIB,用于指定要加载的动态库文件的路径和名称,但是在加载过程中如果找不到指定的动态库,则不会引发错误。
LC_LAZY_LOAD_DYLIB:用于指定要延迟加载的动态库,即在需要使用时再进行加载,而不是在程序启动时立即加载。
LC_PREBOUND_DYLIB:用于指定已经预绑定的动态库,即动态库已经在编译时进行了地址绑定,可以加快程序的启动速度。
- 检测动态库注入成功:
遍历Load Command段,将找到的动态库加载命令与已加载的动态库路径进行比对,以确认注入是否成功。
空白区域在Load Command段末尾:
在Mach-O文件的Load Command段末尾留有空白区域,以满足段的页对齐要求,避免改变可执行文件的大小,因为Mach-O文件是基于偏移量进行计算的。新建动态库替换空白区域:
注入动态库时,新建的动态库文件会取代Load Command段末尾的空白区域,确保注入的动态库不改变可执行文件的大小和结构。修改Mach-O Header内容:
在注入过程中可能会修改Mach-O文件的Header内容,以确保动态库能够正确加载并与目标进程进行链接。重签名应用并安装到手机:
在注入完成后,需要对应用进行重新签名以确保合法性,并将其安装到手机上。通过dyld加载应用时,动态库将被动态链接到目标进程中。
总结
动态库注入是一项强大而灵活的技术,通过将自定义的动态链接库加载到目标进程的内存空间中,并执行其中的代码,可以实现对目标进程的修改和控制。