ciscn_2019_es_2 栈迁移
栈迁移相关知识
栈迁移是通过leave_ret这样的gadget去实现的
leave相当于mov esp,ebp; pop ebp;
ret相当于pop eip;
具体实现看图,假设有个栈溢出的漏洞,将栈填充成如下图,此时的bss段或data段还没用内容,等等我们调用read函数读入内容

当函数call调用一般都有leave和retn的操作

首先调用mov esp, ebp; pop ebp; 记得pop ebp之后esp要向下减一个单位

然后调用retn也就是pop eip,也就是调用read函数,往fake_ebp1中写入内容,主要是要往fake_ebp1中写入fake_ebp2,还有你需要调用的函数地址啥的

然后继续调用一遍leave,也就是mov esp, ebp; pop ebp;

然后执行retn,也就是pop eip,这样就会调用我们写好的函数了,下面我们通过一道例题来深化理解一下。
ciscn_2019_es_2
程序里有个vul()函数,第一个read读入0x30个字节数据,正好溢出0x8个字节,那么就只能覆盖原ebp和retn地址

还有个hack()函数,这里调用了system函数,但是不能直接获取flag,但是给我们提供了system函数的地址,之后我们就可以通过栈迁移的手段,调用system(‘/bin/sh’);

首先这里有两个read函数,没办法像上面提到的将栈迁移到我们的设想的地方,read函数的参数还是s,那么就迁移到s中,这里第一个read可以先泄露出ebp的地址,然后解出变量s的地址
1 | |

原ebp地址距离s的偏移就为0x38,也就是s的地址泄露的ebp地址-0x38,知道了s的地址就可以开始栈迁移了

1 | |