【腾讯Bugly干货分享】iOS 黑客技术大揭秘(4)

注意一下,如果你不想使用 iResign,在执行 xcrun之前,还需要对微信的二进制文件进行签名:

codesign -f -s "iPhone Developer:xxx” —entitlements Entitlements.plist WeChat.app

经常有人问 Entitlements.plist文件怎么写?照着这个来就行了,把 teamed和 bundle id改成你自己的:

【腾讯Bugly干货分享】iOS 黑客技术大揭秘

签名完成后可以通过ldid命令查看签入的内容:

ldid -e /path/to/WeChat

到这里入侵圆满结束!

二、常用入侵原理和反入侵方法总结

下面我们总结一下用到的几个工具:

dumpdecrypted

insert_dylib

cycript

第一个工具是砸壳用的,代码是开源的,而且相当简单,它并没有破解 appstore的加密算法,而是把自己注入到已经通过系统加载器解密的 mach-o文件,再把解密后的内存数据 dump出来,详细的原理这篇文章写的很清楚:

那他是怎么注入的呢?就是利用了 iOS系统中 DYLD_INSERT_LIBRARIES这个环境变量,如果设置了 DYLD_INSERT_LIBRARIES 环境变量,那么在程序运行时,动态链接器会先加载该环境变量所指定的动态库;也就是说,这个动态库的加载优先于任何其它的库,包括 libc。

由于这个环境变量指定的动态库加载的时机实在是太早了,所以对于 app来说,除了代码混淆外,无良策;

但是我们可以在代码中通过判断环境变量来检测是不是被注入:

charchar *env = getenv("DYLD_INSERT_LIBRARIES");

如果方法返回非空,我们可以做一些上报之类的。

后面两个工具都是用来注入的

insert_dylib通过向 mach-o文件的 loadcommand段插入 LC_LOAD_DYLIB数据来加载第三方库。

对于 insert_dylib,我们可以通过在 Xcode的Build Settings中找到“Other Linker Flags”在其中加上-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null指令来绕过 dylib加载额外的第三方库,具体的原理可参考

但是破解这一招也非常简单,上面的链接也说了,用 0xED打开二进制文件,把__RESTRICT全局替换成其它名字即可。

cycript个人感觉是比较神奇的,它在进程运行时动态注入。

没有细看它的源码,网上资料称,它通过 taskfor_pid函数获取目标进程句柄,然后通过在进程内创建新线程并执行自己的代码。

对于 cycript这种 bt的行为,利用系统的 root权限在进程中创建线程并执行自己的代码,目前还没想到好的对策,如果有老司机有方法,希望能指导一下~

最后再说说 lldb反调试,网上大多都提到 ptrace系列函数,原理我就不多说,这里主要讲如何绕过它,有两种方法,先说第一种,直接通过汇编代码修改 ptrace的第一个参数,这样我们需要先知道在哪里调用了 ptrace。

用backboard服务启动启动目标程序:

debugserver -x backboard *:19999 /path/to/binary

在pc端用lldb连接:

process connect connect://deviceIP:19999

然后在lldb中下符号断点

b ptrace,

在lldb中输入c命令之后看ptrace第一行代码的位置,继续输入命令:

p/x $lr

找到函数返回地址,然后用:

image list -o -f

找到目标程序的基地址,这样就能用上面说的公式计算出偏移量,最后在 hooper中找到调用 ptrace的汇编代码

找到汇编代码的位置后,把 ptrace的第一个参数 1F,替换成 0A即可,下面是我的调试过程:

手机端:

【腾讯Bugly干货分享】iOS 黑客技术大揭秘

pc端:

【腾讯Bugly干货分享】iOS 黑客技术大揭秘

第二种简单又暴力,注入tweak,让 ptrace直接返回0即可,具体的代码非常简单,直接发出来:

//Tweak.xm #import <substrate.h> #import <mach-o/dyld.h> #import <dlfcn.h> static int (*oldptrace)(int request, pid_t pid, caddr_t addr, int data); static int newptrace(int request, pid_t pid, caddr_t addr, int data){ printf("newptrace:%d\n\n",request); return 0; } %ctor { printf("Tweak for SkipPtrace Start!\n\n"); MSHookFunction((void *)MSFindSymbol(NULL,"_ptrace"), (void *)newptrace, (void **)&oldptrace); } 总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/fde9b9a5aea5cff405ec47d471e73efe.html