System/System Hacking

PLT, GOT

PLT, GOT

Procedure Linkage Table(PLT)

= 외부 라이브러리 함수를 사용할 수 있도록 주소를 연결해주는 역할을 하는 테이블

PLT의 주소는 고정되어 있기 때문에 서버에 ASLR 보호기법이 적용되어 있어도 PLT로 점프하면 RTL과 비슷하게 공격할 수 있다,

Global Offset Table(GOT)

= PLT에서 호출하는 resolve 함수를 통해 구한 라이브러리 함수의 절대 주소가 저장되어 있는 테이블

▷ 초기에는 라이브러리 함수의 주소를 구하는 바이너리 코드 영역의 주소가 저장되어 있다가, 함수가 처음 호출되면서 라이브러리 함수의 실제 주소가 저장된다.

 

ASLR이 적용되어 있는 환경에서, 동적으로 라이브러리를 링크해 실행되는 바이너리(Dynamically Linked Binary)는 바이너리가 실행될 때마다 라이브러리가 매핑되는 메모리의 주소가 변한다.

 Dynamically linked binary는 실행되기 전까지 라이브러리 함수의 주소를 알 수 없기 때문에 PLT와 GOT 영역이 존재하게 된다.

▶ 라이브러리가 메모리에 매핑된 후 라이브러리 함수가 호출되면, 정적 주소를 통해 해당 함수의 PLT와 GOT 영역에 접근해 함수의 주소를 찾는다.


//gcc -o ex2 ex2.c -fno-stack-protector -mpreferred-stack-boundary=2 -m32
#include <stdio.h>
int main(void){
  char buf[32] = {};
  puts("Hello World!");
  puts("Hello ASLR!");
  scanf("%s", buf);
  return 0;
}

 

실행

위와 같이 Hello World! Hello ASLR!이 출력되고 사용자로부터 문자열을 입력받는다.

 

puts 함수의 PLT
puts 함수의 GOT

main 함수에서 함수를 호출할 때는 plt 주소의 값을 호출한다. 그 후에 plt 주소에서 함수의 got 주소를 호출해 연결된다.

 

puts 함수를 호출하는 부분에 breakpoint를 설정하고 실행한다.

EIP 레지스터에는 그 다음에 실행될 0x8048485 (puts 함수 호출)이 저장된다.

eip에 저장되어 있던 puts 함수 호출 명령을 실행하는데 이 때 함수를 호출했기 때문에 호출한 함수의 내부로 들어가 puts@plt+0에서 멈추게된다.

EIP 레지스터에는 puts@plt의 주소값(0x8048320)이 저장된다.

- puts@plt+0 (0x8048320): 0x804a00c 메모리를 참조해 0x804a00c에 저장되어 있는 값(=puts@plt+6)으로 점프한다.

- puts@plt+6 (0x8048326): 스택에 0을 push한 후, puts@plt+11로 넘어가

- puts@plt+11 (0x804832b): 0x8048310 함수로 점프한다.

- 0x8048310: 0x804a008 주소에 저장되어 있는 0xf7ee000 함수로 점프한다.

링커 라이브러리인 ld-linux.so.2 메모리에 있는 resolve 함수(0xf7fee000)가 리턴하는 시점에 브레이크 포인트를 설정한다.

0xf7fee000 (resolve)함수가 리턴한 후 puts 함수(함수의 실제주소)로 점프한다.

즉, 0xf7fee000함수가 호출된 라이브러리 함수의 실제 주소를 알아내는 함수라는 것을 알 수 있다.

puts함수의 plt를 호출했을 때 puts@plt+11에서 점프하는 주소에서 0xf7fee00의 함수를 호출하는 결과를 만들고, 최종적으로 puts 함수의 실제 주소로 점프하여 puts함수가 실행되도록 한다.

 

=> 특정 함수의 PLT를 호출하면 함수의 실제 주소를 호출하는 것과 같은 효과를 나타낸다. PLT 주소는 고정적이기 때문에 ASLR 보호기법이 적용된 서버에서도 PLT로 점프하게 되면 RTL과 비슷한 공격이 가능해진다.

 

Abusing ASLR

1) ex2의 코드 중 스택 버퍼 오버플로우 취약점(scanf)을 이용해 리턴주소를 puts@plt+6(0x8048326)으로 바꾸고 puts 함수의 첫번째 인자를 "ASLR!" 문자열의 주소(0x8048553)로 바꾼다.

 

[buf+SFP] "A"*36 | [RET] \x26\x83\x04\x08 (puts@plt+6의 주소) | [puts함수 실행 후 리턴할 주소] "BBBB" (\x42424242) | [puts의 인자] \x53\x85\x04\x08

→ puts 함수 실행 후 리턴할 주소가 0x42424242이기 대문에 Segmentation fault가 발생하여 프로그램이 비정상 종료된다.

→ 함수를 호출할 때 GOT에 저장된 주소로 점프하기 때문에 GOT에 저장된 값을 바꾸면 원하는 주소로 점프할 수 있다.

 

2) ex2 바이너리의 main 함수에 bp를 걸고 실행한 후 puts 함수의 GOT(0x804a00c) 메모리의 값을 0xdeadbeef로 바꾼다.

GOT 메모리의 값 변경

GOT 메모리의 값을 바꾸고 프로그램을 이어서 실행하면 puts가 호출되면서 puts@got에 저장된 값으로 점프해 0xdeadbeef가 EIP 레지스터에 저장된다.

 

[참고사이트]

dreamhack.io/learn/3#7

 

로그인 | Dreamhack

 

dreamhack.io

 

SMALL

'System > System Hacking' 카테고리의 다른 글

[Protection Tech.] Canaries(카나리), SSP  (0) 2021.01.27
[Protection Tech.] ASLR  (0) 2021.01.15
[Protection Tech.] NX bit  (2) 2021.01.03
[Heap] Memory Leak  (0) 2020.11.16
[Heap] House of Force  (0) 2020.11.03