反-反汇编patch学习(四)

2019-05-16 约 1144 字 预计阅读 3 分钟

声明:本文 【反-反汇编patch学习(四)】 由作者 ret2nullptr 于 2019-05-16 10:02:00 首发 先知社区 曾经 浏览数 173 次

感谢 ret2nullptr 的辛苦付出!

本文是反-反汇编系列的第四篇文章,继续介绍一些最近学习到的花指令和patch技巧

源码、编译

代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int agr, char** argv) {
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    system("pause");
    return 0;
}
//gcc -m32 main.c -o test

x86-1

IDA视角

用IDA打开,和之前几篇类似的汇编代码

因为没开优化,对esp的加加减减没有合并

0x0804844F处的puts("nop me");全部nop掉,也就是4条汇编指令,分别是参数压栈、调用函数、"平栈2次"

patch

接着,0x0804844F处改成call $+6,也就是call 0x08048455,这条指令长度为5

最后把0x08048455的指令改成pop eax,效果如下:

运行时没有什么问题

F5也可以看出大致逻辑,IDA把sub_8048455看成了子函数

点进这个子函数,F5就会失败,因为堆栈不平衡

实际上call func == push 下一条指令地址 + jmp func

这里通过一个pop eax消除call对栈的影响,效果其实就是无条件jmp,但是IDA显示非常混乱

修复

让IDA正确识别也很简单,只要nop掉那一块代码就行了

如果代码中有防止patch的措施,比如取代码段上某一块的数据,patchnop以后就会改变原有的结果;也可能是代码段的校验之类,这样就会比较难以处理

补充-x64

这个技巧在x64架构下实现也一样简单,只补一个图

x86-2

失败的尝试

主要关于push retn的组合使用

尝试patch成这样,运行到0x8048440时压入一个代码段地址,然后直接retn

因为retn == pop eip,就会直接跳转到0x8048449

由于IDA一般会把retn看作函数结束的标志,所以一般分析到retn就结束了

重新打开,尴尬的是IDA并没有被我们骗到

可能是IDA对紧邻的push + retn有一定的识别吧

改进

作为改进方法,我们将栈弄得更复杂一些

目标地址0x804843D刚被push压栈,这时esp指向它

紧接着就通过add dword ptr [esp],0x2把存的代码段地址增加2

可以看到即将ret 0x804843f也就是原程序流程

重新打开后发现识别效果很差,原先的很多代码段已经是红色了,这表明分析是有问题的

不过虽然看到sp-analysis failed,但却不影响F5,不知道为什么

F5之后,后半部分的代码逻辑直接没了...效果不错

小总结

在实际上手时,一开始第一个例程用的32位exe,但是patch之后直接运行失败,调试也直接crash,暂时没找到结果,于是用gcc编译成elf代替

另外,消除对栈的影响也可以单纯的通过add/sub esp,xxx来完成,都差不多所以只举了pop reg的例子

关键词:[‘安全技术’, ‘二进制安全’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now