설명

NX-bit를 우회하는 RTL (Return-To-Libc) 공격 기법 (32-bit)

sewoo-jjang 2026. 1. 18. 17:59

BOF(Buffer Overflow) 기초를 배우고 나면 보통 쉘코드(Shellcode)를 스택에 올리고 실행하는 공격을 배운다.

하지만 현대의 시스템에는 이러한 공격을 막기 위한 보호 기법들이 존재하는데, 그중 NX-bit를 우회하기 위한 핵심 기법이 바로 RTL이다.

이번 글에서는 32-bit 아키텍처를 기준으로 RTL의 원리와 공격 방법에 대해 알아보도록 하겠다.

1. 왜 RTL이 필요한가?

NX-bit (No-eXecution) 보호 기법

  • 과거에는 스택(Stack) 영역에 쉘코드를 주입하고, Return Address를 쉘코드의 주소로 덮어씌워 실행시킬 수 있었다. 하지만 NX-bit가 도입되면서 스택 영역에 실행 권한(Execute permission)이 제거되었다.. 
  • 즉, 스택에 쉘코드를 아무리 예쁘게 올려놓아도, CPU가 "어? 여기는 실행 권한이 없네?" 하고 프로그램을 강제 종료(Segmentation Fault)시켜 버리는 것. 

RTL (Return-To-Libc)의 등장

  • 해커들은 "내가 코드를 직접 넣을 수 없다면, 프로그램 안에 이미 존재하는 코드를 빌려다 쓰자!"라는 생각을 하게 된다.
  • 리눅스 프로그램은 실행될 때 표준 C 라이브러리인 libc 공유 라이브러리를 메모리에 로딩한다. 이 libc 안에는 system(), execve(), printf() 같은 유용한 함수들이 잔뜩 들어있다.

   ▶ RTL은 프로그램의 실행 흐름(RET)을 스택의 쉘코드가 아닌, 메모리에 이미 적재된 공유 라이브러리(libc)의 함수로 돌리는 기법

2. PLT와 GOT, 그리고 함수 호출 규약

RTL을 이해하려면 3가지를 알아야 한다. 

(1) 동적 링킹과 PLT/GOT

프로그램이 printf 같은 함수를 호출할 때, 실제 라이브러리 주소를 바로 찾아가는 것이 아니라 PLT(Procedure Linkage Table)GOT(Global Offset Table)를 거쳐서 간다. 

  • PLT: 외부 함수를 호출하기 위한 중간 다리 (Trampoline)
  • GOT: 실제 함수의 주소가 저장되는 테이블

우리는 공격할 때 함수의 실제 주소를 알아내거나, 바이너리 내에 존재하는 PLT 주소를 이용하여 해당 함수를 호출할 수 있다.

(2) 32-bit 함수 호출 규약

  • 32-bit 환경에서는 함수 인자를 스택(Stack)을 통해 전달한다. 이때 인자는 뒤에서부터(오른쪽에서 왼쪽으로) push 된다.
  • 예를 들어 system("/bin/sh")를 호출한다고 가정하면 스택은 다음과 같은 모양이 되어야 함수가 정상적으로 인자를 가져가 실행된다.
[   ESP   ]  ->  Ret (Return Address)
[ ESP + 4 ]  ->  Argument 1
[ ESP + 8 ]  ->  Argument 2
...

3. RTL 공격 시나리오 (32-bit)

목표는 취약한 프로그램에서 BOF를 일으켜 system("/bin/sh")를 실행하는 것.

스택 프레임 구조 (Payload 구성)

일반적인 BOF 공격에서는 RET에 쉘코드 주소를 넣었지만, RTL에서는 스택을 다음과 같이 구성해야 함.

  • 32-bit 호출규약을 확인해보면 system 함수 주소 블럭 이후 왜 저런 블럭이 쌓이는지 알 수 있다.

4. 실습 예제 및 익스플로잇 코드

rtl_32
0.01MB

 

  • 이 파일에는 소스코드가 존재하지 않음으로 IDA나 다른 디컴파일러로 소스코드를 확인하길 바란다.
  • 풀이

https://dreamhack.io/wargame/challenges/4

 

로그인 | Dreamhack

 

dreamhack.io

 

[시스템 해킹] basic_exploitation_002 write up

https://dreamhack.io/wargame/challenges/4 로그인 | Dreamhack페르소나 굿즈 이벤트 기간 한정 구독 혜택 지금 가입하면 연간 플랜을 최대 75% 할인 된 가격으로!dreamhack.io0. 보안 기법 확인Arch: i386-32-littleRELRO: P

seowoo-j.tistory.com

요약

  1. 스택에 실행 권한이 없으므로(NX), 쉘코드 대신 라이브러리 함수(system)를 쓴다.
  2. 32-bit는 인자를 스택으로 전달한다.
  3. Payload 구조: [Dummy] + [SFP] + [system_addr] + [Dummy_Ret] + [Arg1_addr]