当开始逆向分析一个300M的图像处理软件的一个功能时,才发现之前玩逆向都是小打小闹,一个多月的奋斗,终于搞定了。很希望遇到问题,因为这样才能学到新的东西,事实上确实遇到了不少问题,也学到了很多经验。
之前的逆向都是直接扔到OD就开始调试,而现在知道在虚拟机里运行,因为这么大的软件不是一两个小时就可以搞完的,在虚拟机里直接快照拍摄,就像游戏存档一样,这样可以避免每次运行软件的注册激活,避免重复之前的分析,避免内存地址动态变化等等,好处多多。
分析算法的难点之一是定位核心算法。对于有软件保护的软件就更困难了,我分析的这个软件反调试只有一个IsDebugPresent,OD插件轻松绕过。幸好没有虚拟化保护,要不然结果可能就不一样了。
既然是图片处理功能,有两个思路,一是通过跟踪图片数据找到核心算法,二是通过几个影响算法的参数找到核心算法。我一开始选择跟踪图片数据定位核心算法,在CreateFile、ReadFile上下断点,但是没找到,之后改变方法,通过定位参数来找核心算法,一路跟踪从资源文件中读到的参数,但是经过几次传递,最后却跟丢了,设了各种断点,可是都断不下来。最后又用跟踪图片数据的方法,用软件processmonitor辅助,还是下ReadFile的断点,找到了图片数据,一路跟踪图片数据,发现又跟丢了,只得到一处存储着处理结果的图片数据,找不到原图的数据,在主线程里设各种断点,都断不下来。几乎都要放弃的时候,抱着试试看的态度,在每个子线程中都下了断点,终于是断了下来。
这涉及到多线程的资源共享问题,多线程中每个子线程的栈是私有的,堆是公有的,不过可以有私有堆,寄存器也是私有的!之前对这个问题有误解,就一组寄存器怎么会是私有的呢?原来每个子线程都有自己的一组寄存器副本,每当切换线程时,寄存器都是会发生改变的,而设硬件断点就是在drx寄存器中存入目标的地址,这个drx寄存器应该只是当前线程的寄存器副本,因此这个硬件断点只在当前线程有效,当其它线程访问目标时,该硬件断点是不会触发的,这就是我之前在主线程中设断点怎么都断不下来的原因了。
断下来的这个线程是所有线程中(除主线程)运行时间最长的。但是想找到原始图片数据还是没做到。处理的算法是在子线程中执行的,通过在结果图片数据上设断点,一步一步逆向地向前推,直到分析完所有参与运算的代码。核心算法找到了,分析算法就相对简单的多了,不过涉及很多SSE扩展指令,用到xmm0-xmm7寄存器,而OD并不会显示这些寄存器的内容,分析起来十分痛苦,虽然WINDBG可以显示这些寄存器内容,但是用WINDBG分析起来同样痛苦。还好旁边的大牛帮忙写了一个插件,用着插件感觉好多了,大家有需要可以问我要。