实战栈溢出剖析
菜鸡一枚,大佬勿喷

首先我们先了解一下什么是栈溢出,栈溢出是在内存地址空间分配指定的字节数,push到内存的数据称之为压栈,pop出来的数据称之为出栈,向栈区写入一定的数据后在ret指令eip的值会改变到其他地方,这就出现了程序崩溃,而call指令则是压栈到栈区eip下一条指令的值,当再压入数据并且超过范围覆盖下一次出栈eip的值就可以指定我们要执行的指令地址。
我们可以实战分析一下下面的C语言代码中一共分配了12个数组到内存中的地址,也可被称之为栈。
#include "stdafx.h"
#include <string.h>
void success() { puts("hacker pwn!!!!"); }
void vulnerable() {
char s[12];
gets(s);
puts(s);
return;
}
int main(int argc, char **argv) {
vulnerable();
return 0;
}
我们编译后使用OD进行动态调试看一下汇编代码,call ascasc 那么就是执行vulnerable(),这个函数,我们单步步入到里面看看。

我们可以看到里面明显有两个函数,那么一定是vulnerable函数中的puts和gets,如果跟进是没有任何意义的,这些都不重要,重要的是lea指令关键点,lea eax,dword ptr ss:[ebp-0xC],开辟了14字节的空间,lea是四则混合运算,相当于把栈空间开辟了14字节,开辟十四字节后 add esp 又增加4字节???那么只会18的后位内存地址空间就是ret的call返回地址。

我们已经了解完程序运行机制,那么经过计算的 payload 就是 0x14 * 'C'+EEEEEE+9999,后面的9999换算16进制就是39393939,那么就是一个可控的返回地址了。

既然是可控地址,我们也可以控到success这个函数中,由于我windows没有安装python pwn tools,只能在Ubuntu系统里面搞了,编译完成后,丢入ida查看,我们可以看到填充14个字符偏移10正好是ret的返回地址。

之后success的地址是08048456

payload 代码非常简单18-12正好是6,其中后4位就是ret起返地址。

运行成功执行了该success函数。


浙公网安备 33010602011771号