深入解析VMP3.x_VM-Jcc指令爆破
我们通过一个被VMP3.x_VM保护的CracKme来探索下Vmp3.x_VM的内部,深入了解VM指令(文中有很多VM爆破点)。本文只通过修改JCC指令来达到在VM中爆破的目的,在进行本文之前,我们需要简单了解一下JCC指令。
JCC指令有两个分支,它是通过判断eflag来进行选择走向哪一个分支,同时虚拟机化的(VM),JCC指令最终的走向也是在选择分支。
样本是很简单,一句if语句的、E语言编写的CrackMe,同时关键代码被VMP3.2.0保护。
Compilation Type为 Ultra(Mutation+Virtualization)。
反汇编窗口十六进制搜索 FF55FC5F5E , CC断点位于00418BDD ,运行程序随便输入pass中断。
标准的VM入口
借助xx_vm插件进行分析,(初始化日志,进行分析)看看有没有我们需要的一些信息。停留在这里:
单步F8跟踪,执行到函数尾部:
这个函数应该是在获取我们已经输入的内容,并在累加寄存器 EAX返回
继续单步F8。
再次来到一个VM入口,使用插件继续分析
........................
一段vm代码后,我们到达了一个熟悉的地方,但是比前面相同的地方多了一些有意思的信息:
[sp+4] 是我们当前输入的数值
[sp+8] 看起来貌似是个正确的密码
单步跟踪一下,发现这里是一个字符串比较函数。
字符串比较函数到达函数尾部,发现EAX寄存器的值返回FFFFFFFF,考虑到Strcmp的返回值,我们可以把这里暂定为Strcmp函数。
走出这个函数,又来到一个VM入口:
这里应该是对 Strcmp的返回值进行判断,同时这里的分析成为了我们的重点。
另外根据前面的分析,Strcmp走了两次,获取输入的值的函数也走了两次,我们在这里猜测,第一次是判断输入的数值是否为空,第二次才是真正的判断密码是否正确。(尝试了不输入密码,发现我们的猜测正确)
重新初始化插件日志,这里开始分析。
堆栈窗口,出现了判断我们输入的值是否合法的信息。
这里执行到函数尾部,出现了对话框,判断的整个流程执行完毕。
打开我们的日志信息,(Strcmp之后的分析日志内容),Strcmp返回的值是FFFFFFFF,日志文本内搜索FFFFFFFF,发现在Entry之后的第11个pop中找到了这个值。
这里EAX的值被映射到 index=00000004的寄存器中,这些日志文件指令是不是看起来有种茫然的感觉?
我们先进行一个基础的概念了解。
VM伪代码和真实汇编代码它们不是一 一对应的关系,实际上一组伪代码对应一条真实汇编代码。
了解了基础概念,我们可以将VM伪代码划分为代码块,划分原则-虚拟栈平衡(PUSH,POP除外)。
根据划分原则,我们对日志文件的VM伪代码来进行划分代码块。
原始指令: add ESP,8 也许我们会联想到 _cdecl, call func; add esp,x;
使用常数 00000000 和 EAX的映射寄存器联合计算得到两个eflag, 246和 286。
这里合并了两个eflag,得到一个 eflag=286。
对eflag进行运算,并且最终得到了一个值=0000000。
把值放入[sp+4]=0012f708 = [0019f45c]中。
Strcmp的返回值 FFFFFFFF和 0 最终得到一个值且都放入 [0019f45c]中,我们在日志中进行对 [0019f45c]的操作,第一次找到的因为没有对[0019f45c]的值进行操作,我们再次搜索发现这段代码块使用 [0019f45c] 和 常数 00000000 进行了运算,运算的代码块与上面代码块5一致
最终计算的结果都得到一个值00000000 并且映射到寄存器index=18中,值获取的过程前面代码块已经阐述。
根据分析代码块1和代码块2实际上就是虚拟机JCC的两个代码分支,最终得到的结果是005348ed。
总结:输入了错误的密码,JCC分支最后选择了005348ed这个地址,如果我们把这个分支地址改成00534869,理论上来说会走向验证成功的分支同时会正确输出信息框内容!
在JMP这里CC断点,随便输入密码,点击确认中断后,[EDI]的值=005348ed,修改为00534869。
附件和插件
CrackMe虽然简单,但是有助于我们探索和理解vm-jcc的原理。
CrackMe程序见附件(附件请点“阅读原文”,即可获得)
这里也提供使用到的分析插件:xxdisasm.com
- End -
看雪ID:兴兴
https://bbs.pediy.com/user-674721.htm
本文由看雪论坛 兴兴 原创
转载请注明来自看雪社区
热门技术文章推荐: