1. 在有symbols 的情况下,断点 objc method , 这个比较方便
b [UIView init];
然后敲 c 运行到 断点处:
objc 的 method 方法的原型,大概是这样:
id __UIView_init(id self, SEL sel, args ...)
所以 $r2 才是第一个参数。。而这里的init 不带参数的
2. 由于 ios的 程序 是arm架构,参数 传递 先按 r0 - r4 传递, 之后的参数 压栈处理, 返回值也在 r0 里面, 所以 在没有 symbols的是有, 想要 查看具体参数的信息, 可以试试:
po $r0
po $r1
po 会发一个objc消息, 然后打印出 objc 对象的 实际内容, 类似 NSLog
3. 在没有 symbols的情况下,想要下断 objc method 或者 private framework 里面的 method 就比较麻烦点:
一种可以通过 class-dump 加参数 -A 导出没有 impl 的 相对地址, 然后用gdb info shared
获取 每个模块的 加载基址, 来算出实际 地址, 下断 , 不过这种方法 我算到现在 还没精确断成功过, = =
还有一种 比较简单有效, 可以通过 objc_getClass 和 class_getInstanceMethod获取 私有类的 实例, 然后通过 method_getImplementation, 获取指定 impl 的 地址, 然后下断:
b *((long)method_getImplementation((long)class_getInstanceMethod((long)objc_getClass((char*)"UIApplication"), @selector(deactivate))))
为了方便使用, 可以定义成命令, 放到 .gdbinit 中, 例如:
define bo
b *((long)method_getImplementation((long)class_getInstanceMethod((long)objc_getClass((char*)"$arg0"), @selector($arg1))))
end
之后只需要:
bo UIApplication deactivate
bo SBIconView touchesBegan:withEvent:
就行了。。
4. trace objc 的 调用过程
由于ios的大部分调用,都在objc_msgSend上, 所以先下断 objc_msgSend, 然后c 到断点处
此时 r0 指向 object , r1 为 selector 名, 可以同通过 object_getClassName 来获取类名
printf "[%s %s]\n", (char*)object_getClassName($r0), (char*)$r1
打印如下:
[__NSCFTimer retain]
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!