前段时间在一个群里看到有人在讨论这个app,连一个专职接单的人都被难住了说有反调试过不了,不禁激起了好奇心,这个从来没听过的app有这么牛逼的技术了吗?
看了下下载链接,直接跳到AppStore,那就还好,不会有太变态的混淆,下下来看看吧。
果然,在越狱手机上一启动就退出,且没有crash log,是主动退出的没跑了,既然已经有人踩坑说有反调试策略了,那就先想办法拿到解密后的应用吧。
AppStore上架的应用都是统一的FairPlayDRM 数字版权加密保护,所以现有的各种解密套路也都一样,在程序跑起来以后进行dump。先试试用的比较多的两个工具frida-ios-dump、CrackerXI看看能不能直接dump出来。经过测试,都不行,皆是由于程序退出导致没有完成dump操作,但是在用frida-ios-dump的时候看log显示所有的framework都已经成功的加载,只是dump操作由于程序退出没有完成。
确实没那么简单,但是似乎也不是丝毫没办法嘛,翻翻dyld的源码,看下dyld的加载流程,这里借用 李斌同学 总结的图:
可以看出至少已经能走到加载动态库的地方了,至于是在初始化的地方做的检测还是在进入main函数之后做得检测目前还不得而知,也不重要。由于用lldb拉起程序的时候,断点是断在_dydl_start上,所以我们完全有时机可以dump出程序的,直接memory read手撸出来再做个修复就好。这里为了省事,就直接修改frida-ios-dump 的代码,在砸壳的时候让程序暂停,直接把resume注释掉:
这样就成功把解密后的IPA包拿到了,先把主程序丢尽ida里分析一波,粗略看一下有下面这些检测越狱的API:
使用搜索引擎大致搜了下,发现多是一些sdk提供的检测,那么在越狱屏蔽插件的基础上再针对性做些处理就够了,应该不会有太骚的操作。可以直接写frida脚本或是substrate插件hook
对于懒癌患者来说,哐叽哐叽写那么多代码实非所愿,就想着能不能直接把退出的逻辑处理下,这样只要解决一处即可,谁让它动静那么大。
ida搜下exit,发现确实有好几处调用,大致看了下却都不像是检测到调试或越狱后调用的,经过调试发现确实不是这几处导致程序退出的。那就很奇怪了,还会是怎么退出的呢?
ummm, 直接上MonkeyDev调试一波吧(不得不说MonkeyDev真是一个好东西,把重打包等一系列操作都做了,还集成了一些调试环境,真香),先把MonkeyDev里面反调试相关的注释全部打开,然后就直接跑起来
没想到没想到,给报了个访问异常的错误,想回溯看一下在哪儿崩溃的也不行,直接给堆栈破坏了,这招够坏的呀。
既然是反调试,那么就有办法解决。翻翻看大哥们的博客,发现目前反调试的手段也就那些,MonkeyDev已经使用fishhook帮我们处理了ptrace、dlsym、sysctl和syscall,那么就看看是不是直接整的指令级系统调用,且搜搜看:
真乖,要什么来什么,还真就直接俩汇编写的系统调用干起来了,上面的是退出,下面的是反调试。常规操作是直接暴力 svc patch with nop,但是这里不行。注意下面那段汇编:
这是直接将函数开始保存的“现场”给破坏了,所以不能直接nop,看了下这俩函数都没做什么其它操作,那就直接在函数开头ret或nop完再将堆栈给恢复即可,对于有返回值的记得修改返回值。这些操作都可以借助keypatch轻松完成,具体就不赘述了。
patch 完macho文件后重新打包安装运行,就可以正常使用了,再次觉得MonkeyDev真香~
防护手段:
思考:
任何带特征的检测都是不安全的 & 隐而不发(@Ouroboros)
Thanks to JKSun. 感谢JKSun 大哥的指点。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)