GDB/LLDB 动态调试iOS应用
LLDB官方文档:https://lldb.llvm.org/tutorial.html
GDB文档:https://www.cs.cmu.edu/~gilpin/tutorial/
准备工作
1.越狱iPhone一台
2.安装OpenSSH, 在Cydia里搜索并安装,目的是:从MacOS连接到iPhone
3.安装adv-cmds, 在Cydia里搜索并安装,目的是:SSH连接上iphone后,可以执行一些命令,如:进程状态显示
4.安装GDB Debugger, 在网站 http://cydia.radare.org/debs/ 找到gdb,并下载,然后通过MacOS版的软件iTools或者iFunBox拖拽到iPhone目录:/var/root/Media/Cydia/AutoInstall 下,最后重新开机
调试步骤
1.ssh连接上iPhone 如果密码忘记了,就使用iFunBox去手机的目录/etc/master.passwd文件里查看,root开头的,一般等于密码等于abc123
2.查询系统中的进程号相关信息
>ps -ax
3.查找需要动态调试的进程信息,如:WeChat(微信),微信一定要打开
>ps aux -c|grep WeChat
会输出信息如:
>mobile 239 0.0 5.1 766104 52556 ?? Ss 7:33PM 0:02.50 WeChat
那么我们就得到了进程ID:239
4.将进程附加到GDB
>gdb -p 239
然后,会输出一堆信息
5.给已知函数名打断点,比如函数名:-[WTLoginApi loginWithPasswd:andPasswd:andSigBitmap:andLoginFlag:retData:]:
>(gdb) b -[WTLoginApi loginWithPasswd:andPasswd:andSigBitmap:andLoginFlag:retData:]:
单步跳过
>(gdb) ni
单步步入
>(gdb) si
继续运行
>(gdb) continue
运行一个app
>(gdb) run
结束当前函数
>(gdb) finish
如何防止你的应用被GDB附加进程?
1.ptrace 介绍
https://en.wikipedia.org/wiki/Ptrace
2.阻止GDB附加 (来自念茜的博客)
http://blog.csdn.net/yiyaaixuexi/article/details/18222339
3.实际代码
#import <UIKit/UIKit.h>
#import <dlfcn.h>
#import "AppDelegate.h"
//定义一个函数指针用来接收动态加载出来的函数ptrace
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif
void DenyAppAttach() {
//动态加载并链接指定的库
//第一个参数path为0时, 它会自动查找 $LD_LIBRARY_PATH,$DYLD_LIBRARY_PATH, $DYLD_FALLBACK_LIBRARY_PATH 和 当前工作目录中的动态链接库.
void * handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
//动态加载ptrace函数,ptrace函数的参数个数和类型,及返回类型跟ptrace_ptr_t函数指针定义的是一样的
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
//执行ptrace_ptr相当于执行ptrace函数
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
//关闭动态库,并且卸载
dlclose(handle);
}
int main(int argc, char * argv[]) {
#ifndef DEBUG
DenyAppAttach();
#endif
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
如果你在Xcode调试环境下,去掉#ifndef DEBUG #endif这句话,你会发现,Xcode无法调试该应用;因为动态的加载了ptrace,然后给传输的宏是PT_DENY_ATTACH 拒绝附加进程
到此为止,就到达目的了