CrackProof iOS版分析(二)补充
- 内容介绍
- 文章标签
- 相关推荐
0x0
最近又研究了一下,仅作简单的补充
0x1 dyld
iOS加载Mach-O的时候会由dyld调用目标Mach-O全部的mod_init_func来完成初始化,和安卓的.init_proc段是一个作用
hook一下全局的pthread再配合trace日志,可以知道mod_init_func_0调用了pthread来创建线程进行越狱检测,触发pthread的调用点为0xa03050c,创建的函数为0xa07ce90
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10b8e0e90!0xa07ce90 0x10b8e0e90 !0xa07ce90 (0xa07ce90)
arg: 0x10ccf5118
pthread_t*: 0x16fb10650 -> 0x16fffb000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10bab1668!0xa24d668 0x10bab1668 !0xa24d668 (0xa24d668)
#3 dyld:0x10059842c!0x2842c 0x10059842c dyld!invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const
#4 dyld:0x1005c76ec!0x576ec 0x1005c76ec dyld!invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const
#5 dyld:0x1005752d0!0x52d0 0x1005752d0 dyld!invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const
#6 dyld:0x100574788!0x4788 0x100574788 dyld!dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const
#7 dyld:0x100573d78!0x3d78 0x100573d78 dyld!dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const
#8 dyld:0x1005c1160!0x51160 0x1005c1160 dyld!dyld3::MachOFile::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, bool&) block_pointer) const
#9 dyld:0x10057ed94!0xed94 0x10057ed94 dyld!dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const
#10 dyld:0x10057b97c!0xb97c 0x10057b97c dyld!dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const
#11 dyld:0x100578444!0x8444 0x100578444 dyld!dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const
#12 dyld:0x1005984b4!0x284b4 0x1005984b4 dyld!dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_1::operator()() const
#13 dyld:0x10057d4d4!0xd4d4 0x10057d4d4 dyld!dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const
#14 dyld:0x100577c1c!0x7c1c 0x100577c1c dyld!dyld4::APIs::dlopen_from(char const*, int, void*)
#15 CoreFoundation:0x1a2166f58!0x122f58 0x1a2166f58 CoreFoundation!_CFBundleDlfcnLoadFramework
然后0xa07ce90又会继续创建两个线程进行越狱检测
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10b938704!0xa0d4704 0x10b938704 !0xa0d4704 (0xa0d4704)
arg: 0x16fffae58
pthread_t*: 0x16fffa5c0 -> 0x170087000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10b9ea704!0xa186704 0x10b9ea704 !0xa186704 (0xa186704)
#3 UnityFramework:0x10b8af47c!0xa04b47c 0x10b8af47c !0xa04b47c (0xa04b47c)
#4 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#5 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#6 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#7 UnityFramework:0x10b8f6c80!0xa092c80 0x10b8f6c80 !0xa092c80 (0xa092c80)
#8 UnityFramework:0x10b9ca288!0xa166288 0x10b9ca288 !0xa166288 (0xa166288)
#9 UnityFramework:0x10b8e1134!0xa07d134 0x10b8e1134 !0xa07d134 (0xa07d134)
#10 libsystem_pthread.dylib:0x1ecdf40ec!0x30ec 0x1ecdf40ec libsystem_pthread.dylib!_pthread_start
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10ba2f23c!0xa1cb23c 0x10ba2f23c !0xa1cb23c (0xa1cb23c)
arg: 0x170086f10
pthread_t*: 0x16fff9310 -> 0x170113000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10b9d929c!0xa17529c 0x10b9d929c !0xa17529c (0xa17529c)
#3 UnityFramework:0x10b8af47c!0xa04b47c 0x10b8af47c !0xa04b47c (0xa04b47c)
#4 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#5 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#6 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#7 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#8 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#9 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#10 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#11 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#12 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#13 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#14 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#15 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
0x2 魔改ollvm
入口点长这样
PixPin_2026-03-29_11-06-341825×1300 267 KB
初始化分发器
PixPin_2026-03-29_11-07-321597×763 151 KB
分发器核心,整体如下
PixPin_2026-03-29_11-08-051920×1044 139 KB
分发器最具特色的应该就是这个opcode生成了
PixPin_2026-03-29_11-09-061920×1044 325 KB
通过一系列计算来获取初步的opcode
PixPin_2026-03-29_11-09-521492×327 67.4 KB
然后会进入如下两个switch case,二次解密opcode以后再选择函数执行
PixPin_2026-03-29_11-11-541006×934 134 KB
PixPin_2026-03-29_11-13-361193×1855 473 KB
每个case对应的函数又是一个分发器,分发器里面还有crackproof::state_compute0,反正塞了致死量的魔改ollvm
不过通过trace可以得知,整个trace.log前面全是垃圾计算,目的是掩盖真实的调用函数,这下就很容易找到检测函数了
PixPin_2026-03-29_11-17-371385×2077 421 KB
这里发现了一个上次没分析出来的检测,这玩意会检测__objd段是否有修改,有任何修改也会通过OS_dispatch_queue_main压入exit(0)杀掉进程(这玩意还会sleep几秒,阴完了)
环境检测倒是和上次的分析一致,下面是字符串的解密算法:
- 先把立即数拷到缓冲区里面,直到遇到0为止
s[i] = (~ROL8(s[i], 3) - (i & 3)) & 0xff;字节左转3位,然后取反,再减掉i&3
0xF
得从VMProtect里面学学垃圾代码生成了,然后又可以出CTF题目折磨逆向的了
网友解答:--【壹】--:
这个保护器全平台都是高强度防御的(
只不过windows能通过ring0直接注入dll来改内存,安卓和iOS这边就不好搞了(
--【贰】--:
为啥一个iOS上的游戏会塞这么多检查
感觉macOS上很少见到这么强的保护
--【叁】--:
佬友太强了
0x0
最近又研究了一下,仅作简单的补充
0x1 dyld
iOS加载Mach-O的时候会由dyld调用目标Mach-O全部的mod_init_func来完成初始化,和安卓的.init_proc段是一个作用
hook一下全局的pthread再配合trace日志,可以知道mod_init_func_0调用了pthread来创建线程进行越狱检测,触发pthread的调用点为0xa03050c,创建的函数为0xa07ce90
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10b8e0e90!0xa07ce90 0x10b8e0e90 !0xa07ce90 (0xa07ce90)
arg: 0x10ccf5118
pthread_t*: 0x16fb10650 -> 0x16fffb000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10bab1668!0xa24d668 0x10bab1668 !0xa24d668 (0xa24d668)
#3 dyld:0x10059842c!0x2842c 0x10059842c dyld!invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const
#4 dyld:0x1005c76ec!0x576ec 0x1005c76ec dyld!invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const
#5 dyld:0x1005752d0!0x52d0 0x1005752d0 dyld!invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const
#6 dyld:0x100574788!0x4788 0x100574788 dyld!dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const
#7 dyld:0x100573d78!0x3d78 0x100573d78 dyld!dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const
#8 dyld:0x1005c1160!0x51160 0x1005c1160 dyld!dyld3::MachOFile::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, bool&) block_pointer) const
#9 dyld:0x10057ed94!0xed94 0x10057ed94 dyld!dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const
#10 dyld:0x10057b97c!0xb97c 0x10057b97c dyld!dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const
#11 dyld:0x100578444!0x8444 0x100578444 dyld!dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const
#12 dyld:0x1005984b4!0x284b4 0x1005984b4 dyld!dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_1::operator()() const
#13 dyld:0x10057d4d4!0xd4d4 0x10057d4d4 dyld!dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const
#14 dyld:0x100577c1c!0x7c1c 0x100577c1c dyld!dyld4::APIs::dlopen_from(char const*, int, void*)
#15 CoreFoundation:0x1a2166f58!0x122f58 0x1a2166f58 CoreFoundation!_CFBundleDlfcnLoadFramework
然后0xa07ce90又会继续创建两个线程进行越狱检测
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10b938704!0xa0d4704 0x10b938704 !0xa0d4704 (0xa0d4704)
arg: 0x16fffae58
pthread_t*: 0x16fffa5c0 -> 0x170087000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10b9ea704!0xa186704 0x10b9ea704 !0xa186704 (0xa186704)
#3 UnityFramework:0x10b8af47c!0xa04b47c 0x10b8af47c !0xa04b47c (0xa04b47c)
#4 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#5 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#6 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#7 UnityFramework:0x10b8f6c80!0xa092c80 0x10b8f6c80 !0xa092c80 (0xa092c80)
#8 UnityFramework:0x10b9ca288!0xa166288 0x10b9ca288 !0xa166288 (0xa166288)
#9 UnityFramework:0x10b8e1134!0xa07d134 0x10b8e1134 !0xa07d134 (0xa07d134)
#10 libsystem_pthread.dylib:0x1ecdf40ec!0x30ec 0x1ecdf40ec libsystem_pthread.dylib!_pthread_start
creator: UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
start_routine: UnityFramework:0x10ba2f23c!0xa1cb23c 0x10ba2f23c !0xa1cb23c (0xa1cb23c)
arg: 0x170086f10
pthread_t*: 0x16fff9310 -> 0x170113000
attr: default
backtrace:
#0 UnityFramework:0x10b89450c!0xa03050c 0x10b89450c !0xa03050c (0xa03050c)
#1 UnityFramework:0x10b896cbc!0xa032cbc 0x10b896cbc !0xa032cbc (0xa032cbc)
#2 UnityFramework:0x10b9d929c!0xa17529c 0x10b9d929c !0xa17529c (0xa17529c)
#3 UnityFramework:0x10b8af47c!0xa04b47c 0x10b8af47c !0xa04b47c (0xa04b47c)
#4 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#5 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#6 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#7 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#8 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#9 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#10 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#11 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#12 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#13 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#14 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
#15 UnityFramework:0x10b8afb18!0xa04bb18 0x10b8afb18 !0xa04bb18 (0xa04bb18)
0x2 魔改ollvm
入口点长这样
PixPin_2026-03-29_11-06-341825×1300 267 KB
初始化分发器
PixPin_2026-03-29_11-07-321597×763 151 KB
分发器核心,整体如下
PixPin_2026-03-29_11-08-051920×1044 139 KB
分发器最具特色的应该就是这个opcode生成了
PixPin_2026-03-29_11-09-061920×1044 325 KB
通过一系列计算来获取初步的opcode
PixPin_2026-03-29_11-09-521492×327 67.4 KB
然后会进入如下两个switch case,二次解密opcode以后再选择函数执行
PixPin_2026-03-29_11-11-541006×934 134 KB
PixPin_2026-03-29_11-13-361193×1855 473 KB
每个case对应的函数又是一个分发器,分发器里面还有crackproof::state_compute0,反正塞了致死量的魔改ollvm
不过通过trace可以得知,整个trace.log前面全是垃圾计算,目的是掩盖真实的调用函数,这下就很容易找到检测函数了
PixPin_2026-03-29_11-17-371385×2077 421 KB
这里发现了一个上次没分析出来的检测,这玩意会检测__objd段是否有修改,有任何修改也会通过OS_dispatch_queue_main压入exit(0)杀掉进程(这玩意还会sleep几秒,阴完了)
环境检测倒是和上次的分析一致,下面是字符串的解密算法:
- 先把立即数拷到缓冲区里面,直到遇到0为止
s[i] = (~ROL8(s[i], 3) - (i & 3)) & 0xff;字节左转3位,然后取反,再减掉i&3
0xF
得从VMProtect里面学学垃圾代码生成了,然后又可以出CTF题目折磨逆向的了
网友解答:--【壹】--:
这个保护器全平台都是高强度防御的(
只不过windows能通过ring0直接注入dll来改内存,安卓和iOS这边就不好搞了(
--【贰】--:
为啥一个iOS上的游戏会塞这么多检查
感觉macOS上很少见到这么强的保护
--【叁】--:
佬友太强了

