DASCTF七月月赛PWN
qiandao
简单的栈溢出,但是在leave
指令后,利用lea
指令给esp
赋值别的地址,导致我们覆盖到返回地址的地址不能被跳转。
分析
首先需要明白在函数返回时leave
和ret
两条指令的本质:
leave
指令相当于mov esp,ebp; pop ebp;
即恢复上一个函数的栈结构ret
指令则相当于pop esp;
也就是在ebp出栈之后,esp其实是指向返回地址的,就会将当前栈顶内容弹出到eip
中进行执行
而lea
和mov
指令呢?
lea
是load effective address
的缩写,简单的说,lea指令可以用来将一个内存地址直接赋给目的操作数,例如:lea eax,[ebx+8]
就是将ebx+8这个值直接赋给eax,而不是把ebx+8处的内存地址里的数据赋给eax。而
mov
指令则恰恰相反,例如:mov eax,[ebx+8]
则是把内存地址为ebx+8处的数据赋给eax。
再看一下这道题目中函数调用结束的指令:
在leave
和ret
之间执行了lea esp,[ecx-4]
也就是将esp指向了ecx-4
这个地址,这个地址在哪?
我们看到前面的mov ecx,[ebp+var_4]
得知了ecx存放的是ebp+var_4
地址上的内容,而var_4
是栈上比ebp低四字节的位置:
也就是说esp=[ebp-4]-4
同时程序又存在格式化字符出纳漏洞,那整个思路就很明显了:
- 1、格式化字符串泄露栈地址
- 2、修改ebp-4处的值为可控地址
- 3、在可控地址-4的位置存放backdoor的地址
我们先看一下能不能通过输入格式化字符串输出ebp地址:%p%p%p%p%p%p%p%p%p
从图中的结果可以看到,第二个参数输出的内容正是栈底地址。
注意:指出个容易混淆的地方
在用代码attach的时候,发现ebp中是有三个地址(下图),第三个才是真正的main函数的栈底地址,刚开始很困惑为什么ebp不是输出的值?思考半天才想起来main函数中调用了多次的puts和gets函数,attach的时候是在调用函数栈中的。
由此构造下payload:
stack_addr = int(p.recv(8),16) - 0x24 |
构造exp如下:
exp
from pwn import * |
- Post Title: DASCTF七月月赛PWN
- Post Author: ggb0n
- Post Link: http://ggb0n.cool/2020/07/26/DASCTF七月月赛PWN/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
1.CybricsCTF
2.TCTF2020部分题解
3.DASCTF六月月赛
4.De1CTF2020部分题解
5.安恒月赛DASCTF
6.高校战"疫"部分题解
7.V&N公开赛
8.安恒-抗疫月赛
1.TCTF2020部分题解
2.第五空间pwn题练习
3.堆溢出-Tcache_Attack
4.堆溢出-Housese_Of_XXX
5.堆溢出基础
6.入坑二进制