网上介绍hopper有逆向伪代码的文章很多,并以为其是万能而且cool B的。但是并没有人去求证hopper的逆向伪代码参考系数(参考价值,大家做过开发都清楚明白,有些功能看起来很花很cool但不实用)有多高,或者说可信度正确率(至少不要误导人,这比自己直接逆向分析反汇编代码有误还要冤狂)。上一篇已经提出了这个问题,本篇就来进一步求证,我只本着高中时代上过的政治思想课里面毛论中的实事求是精神,和一个程序员对代码的热爱,并非挑事端。
从我已经逆向过的函数中挑选三个出来,用hopper进行逆向输出伪代码,对比观察我想考察的点。
1.QuartzCore`CA::Context::client_port 观察hopper是否可以分析出^() Block。
2.QuartzCore`CA::Context::commit_commands 观察hopper是否可以分析出switch。
3.QuartzCore`drawLine(c风格函数)在适配到QuartzCore`-[CATextLayer _drawLine:inContext:atPoint:]时 观察hopper是否正确分析出传参。
首先是QuartzCore`CA::Context::client_port, 结果是hopper没有能分析出^() Block,还意外发现hopper在逆向伪代码时不考虑内存单元的引用在其它函数中的内容修改的情况。
下面是对hopper的逆向伪代码关于没有分析出^()Block的批注
接着是意外发现的另一个问题的相关批注
下面是对反汇编进行批注
然后是我逆向出来的代码:
第二个安排的测试点是函数QuartzCore`CA::Context::commit_commands,结果hopper没有分析出switch结构。
最后一个测试点是函数QuartzCore`drawLine,结果hopper在逆向其最善长的oc函数调用时分析传参失误。将QuartzCore`drawLine(c风格函数)在适配到QuartzCore`-[CATextLayer _drawLine:inContext:atPoint:]。hopper只会照着x64体系的传参约定,数着手指头硬生生地加入一个r8寄存器,粗暴地作为msg_send的第5个参数来对付,而并没有从编译器传参数的约定出发来考虑问题。
这个函数简单短小就一同贴上反汇编代码
QuartzCore`drawLine(objc_object*, void*, CGPoint, __CTLine const*): 0x1041ca4dc <+0>: pushq %rbp 0x1041ca4dd <+1>: movq %rsp, %rbp 0x1041ca4e0 <+4>: movq %rsi, %rax 0x1041ca4e3 <+7>: movq 0x50f2e(%rip), %rsi ; "_drawLine:inContext:atPoint:" 0x1041ca4ea <+14>: movq %rax, %rcx 0x1041ca4ed <+17>: popq %rbp 0x1041ca4ee <+18>: jmpq *0x55d44(%rip) ; (void *)0x000000010357d800: objc_msgSend