前篇博客中,使用 杨君的小黑屋 提供的工具恢复二进制文件的符号表,只恢复了函数的符号表,本篇讲述如何恢复block符号表,杨君的博客中使用IDA分析二进制文件,本篇则使用MacOS系统上体验也不错的Hopper来作分析。
使用工具:
block的类型有3种:
- _NSConcreteGlobalBlock(全局)
- _NSConcreteStackBlock(栈)
- _NSConcreteMallocBlock(堆)--> 不会出现在二进制文件中
block编译后在二进制文件中的布局,查看 Block_private.h 文件
struct Block_layout {
/* 指向所属类型 __NSConcreteGlobalBlock,__NSConcreteStackBlock */ void *isa;
int flags; int reserved;
/* 函数指针,指向block的实现地址 */ void (*invoke)(void *, ...); struct Block_descriptor *descriptor; /* Imported variables. */ };
使用Hopper查看二进制文件(CrashTest)
-
__NSConcreteGlobalBlock 存在于全局静态区 Segment __DATA 的 Section __const , 使用Hopper查看GlobalBlock如图:
__NSConcreteGlobalBlock位置即为 isa指针地址0x10000c2f0,后跟2个int型的值,接着是函数指针地址0x10000c300, 它指向地址 0x1000081b0 即为block的实现函数地址。
-
_NSConcreteStackBlock则与代码指令在一起,如图
恢复Block符号表
根据以上特性,以及Hopper提供的脚本接口,写一段python脚本收集block函数地址与名字的对应关系,再将此关系恢复到二进制文件中。
原理:
全局的Block比较容易找到函数入口,isa指针向后偏移固定字节即可找到,栈区Block相对复杂,笔者是通过扩大搜索地址区域到 ±24字节的范围内搜索函数指针
在Hopper中运行脚本,会得到一个block_sym.json文件,此json文件将用于恢复block的符号。使用符号表恢复工具的的 -j 选项
./restore-symbol -o CrashTest-sym -j block_sym.json CrashTest-arm64
得到恢复符号的二进制文件 CrashTest-sym,于是就可以用atos命令解析block中的崩溃了
atos -arch arm64 -o CrashTest-sym -l 0x1000d0000 0x1000d84ac 0x1000d83a4 0x1000d8108
// 输出
-[PersonInfo haveChilren:]_block_invoke (in CrashTest-sym) + 220 -[PersonInfo haveChilren:] (in CrashTest-sym) + 76 -[ViewController printStaff] (in CrashTest-sym) + 56
附件:
参考 & 感谢
杨君的小黑屋 http://blog.imjun.net/posts/restore-symbol-of-iOS-app/