본문 바로가기
프로그래밍/해킹

PLT / GOT / libc database

by 만디기 2024. 8. 15.

1) PLT (Procedure Linkage Table) :

외부 프로시저를 연결해주는 테이블이다. PLT를 통해 다른 라이브러리에 있는 프로시저를 호출해 사용할 수 있다.

 

2) GOT (Global Offset Table) :

PLT가 참조하는 테이블이다. 프로시저들의 주소가 들어 있다.

- 함수를 호출하면(PLT를 호출하면) GOT로 점프하는데 GOT에는 함수의 실제 주소가 쓰여있다.
- 첫 번째 호출이라면 GOT는 함수의 주소를 가지고 있지 않고 ‘어떤 과정’을 거쳐 주소를 알아낸다.
- 두 번째 호출부터는 첫 번째 호출 때 알아낸 주소로 바로 점프한다. 

 

3) libc database 활용 :

https://dreamhack.io/wargame/challenges/354 에 있는 rop 파일을 이용하였다.

 

(1) rop.c

(2) rop.c 컴파일 : gcc -o rop rop.c -fno-PIE -no-pie => rop 파일 생성

// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie

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

int main() {
  char buf[0x30];

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

  // Leak canary
  puts("[1] Leak Canary");
  write(1, "Buf: ", 5);
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  // Do ROP
  puts("[2] Input ROP payload");
  write(1, "Buf: ", 5);
  read(0, buf, 0x100);

  return 0;
}

 

 

(3) readelf -d rop 결과 : 파일의 동적 섹션에 대한 내용을 출력한다.

- readelf 명령어 : http://korea.gnu.org/manual/release/binutils/binutils_15.html

 

 

(4) ldd rop 결과 : 지정한 프로그램 또는 파일의 라이브러리 의존성을 살펴볼 때 사용하는 명령어

 

 

(5) nm rop 결과 : 오브젝트 파일, 실행 파일 및 오브젝트 파일 라이브러리에 있는 기호에 대한 정보를 표시한다.

 

(6) 위의 readelf와 ldd 결과를 보고, rop에서는 libc.so.6 라이브러리를 사용한다고 생각하여 다음과 같이 readelf 명령어로 해당 라이브러리 파일에서 printf와 puts 함수를 찾았다.

puts의 주소 마지막 12비트는 e50이며, printf의 경우는 6f0이다. 마지막 12비트를 보는 이유는, libc_base(libc의 시작주소)의 하위 12비트가 0이기 때문이다.

이를 이용하여 실행 중인 특정 함수의 주소 마지막 12비트를 보면, 어떤 라이브러리를 사용하고 있는지 추측할 수 있는데 이 때 libc database를 활용할 수 있다.

 

- readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "puts"

 

- readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "printf"

 

(7) 두 가지 방법으로 바이너리가 어떤 라이브러리를 사용하는지 알 수 있다.

- 일단 gdb 실행 후 바이너리에서 사용하는 puts/printf 함수의 주소가 어디인지 조사한다. 위에서 언급했듯 첫 번째 호출이라면 GOT는 함수의 주소를 가지고 있지 않고 ‘어떤 과정’을 거쳐 주소를 알아내기 때문에 두 번째 호출에서 함수의 주소를 알아낼 수 있다.

gdb rop => start / c 명령으로 프로그램을 일단 한 번 실행한 후 주소를 조사하자. 

이후 puts/printf 함수의 주소 맨 끝 12비트를 비교하면 (6)에서와 동일함을 알 수 있다.

첫 번째 호출 시. 해당 주소는 바이너리 내의 plt 코드의 주소이다.

 

두 번째 호출 시. GOT에 실제 함수의 주소가 담겨 있다.

 

- 첫 번째 방법https://libc.rip/ 이용

해당 사이트에서 함수 이름과 함수 주소 맨 끝 12비트를 입력하면 이에 맞는 libc 라이브러리를 찾아 준다.

단 없는 버전도 있는 것 같으니 주의.

 

 

두 번째 방법 : libc-database를 다운로드 받아 검색하기

https://github.com/niklasb/libc-database 에서 다운로드 후 설정하고 검색

(1) - (6)까지 보았듯이 실제 사용 라이브러리는 libc.so.6인데... 이 쪽이 좀 더 정확한가? 싶다.

$ ./find puts e50
ubuntu-glibc (libc6_2.35-0ubuntu3.8_amd64)
/usr/lib/x86_64-linux-gnu/libc.so.6 (local-b99cddb548877d514655da7ecac1348dd45e6eee)

$ ./find printf 6f0
rpm (libc-2.36-52.mga9.x86_64_2)
rpm (libc-2.36-53.mga9.x86_64_2)
rpm (libc-2.36-54.mga9.x86_64_2)
ubuntu-glibc (libc6_2.35-0ubuntu3.8_amd64)
ubuntu-old-glibc (libc6_2.3.6-0ubuntu20_i386_2)
ubuntu-old-glibc (libc6-amd64_2.19-10ubuntu2.3_i386)
ubuntu-old-eglibc (libc6-i386_2.12.1-0ubuntu10.4_amd64)
ubuntu-glibc (libc6-i386_2.38-1ubuntu6.3_amd64)
ubuntu-glibc (libc6-i386_2.38-1ubuntu6_amd64)
/usr/lib/x86_64-linux-gnu/libc.so.6 (local-b99cddb548877d514655da7ecac1348dd45e6eee)

 

 

(8) 이를 통해 libc_base를 구해 보자.

puts 함수를 예로 들면, (6)의 libc.so.6 라이브러리에서 puts 함수의 오프셋은 0x80e50이며, rop에서의 주소는 (7)에서 보면 0x7ffff7e0be50이다. rop에서의 함수 주소에 라이브러리에서의 오프셋을 빼면 rop 바이너리의 libc_base를 알 수 있다.

libc_base의 마지막 12비트는 000이므로 맞게 구했음을 알 수 있다.

0x7ffff7e0be50 - 0x80e50 = 0x7ffff7D8B000 (rop 바이너리에서의 libc_base 값)

 

 

(9) libc_base 값을 이용하여 libc 내 다른 함수들을 rop 바이너리에서 어떤 주소로 호출하는지 알 수 있다.

이를 이용하면, 원하는 libc 함수를 rop 바이너리에서 실행할 수도 있게 된다.

 

(ex) rop 바이너리에서 호출하는 read 함수 주소 구하기

(1) readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "read" 명령어를 실행하면, read 함수의 오프셋이 0x1147d0임을 알 수 있다. 이를 아까 구한 libc_base와 더하면 rop 바이너리에서 호출하는 read 함수 주소가 나온다.

0x7ffff7D8B000 (rop 바이너리에서의 libc_base 값) + 0x1147d0 = 0x7ffff7e9f7d0

 

(2) 실제로 gdb rop을 하여 확인해보면 read 함수의 주소가 맞음을 확인할 수 있다.

 

 

 

 

참조

https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

 

PLT와 GOT 자세히 알기 1

Dynamic Linking 과정을 추적해 PLT와 GOT를 이해해보자 :) 시스템 해킹을 공부하시는 분들이라면 PLT와 GOT에 대해 알고 있을 것입니다. 이제 막 시스템 해킹 공부를 시작한 분들도 한 번 쯤 들어보셨을

bpsecblog.wordpress.com

 

https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/

 

PLT와 GOT 자세히 알기 2 (with ‘yocto’)

이번 편에서는 Codegate 2015 본선 문제 였던 pwnable 분야의 ‘yocto’ 를 통해 PLT 와 GOT에 대해 자세히 알아보겠습니다. 과정이 조금 복잡하기 때문에, 보시면서 따라 해 보는 것이 이해 하는 데 조금

bpsecblog.wordpress.com

 

https://dreamhack.io/forum/qna/4937#answer-5269

 

개인적으로 궁금한 점 질문 드립니다(라이브러리 주소 관련)

rop.c 파일을 컴파일한 후 libc 종류를 직접 찾아내는 걸 한 번 해 보고 싶었는데... 뭔가 잘 안 돼서 질문 드립니다. 환경 Ubuntu: 22.04.4 LTS gcc…

dreamhack.io

 

https://wyv3rn.tistory.com/61

 

문제에서 제공된 libc 파일 사용.

offset을 찾는 것은 아래 링크 참조. https://wyv3rn.tistory.com/64 libc에서 offset 찾기. pwnable 문제를 풀다보면 libc 파일을 제공해주는 경우가 다수 있다. 하지만 offset을 구할때 자꾸 헷갈리는 부분이 있어

wyv3rn.tistory.com

 

https://kaspyx.tistory.com/86?category=939328

 

libc-database 사용법

/* written by kaspy (kaspyx@gmail.com)*/ 1. libc-database 서론 libc-databse 라는게 무엇이냐하면, 주로 해킹대회에서 포너블(pwnable) 문제를 풀때 사용하는 유틸리티 프로그램인데, glibc 라이브러리버전별로 우리

kaspyx.tistory.com

 

https://s1m0hya.tistory.com/20

 

libc-database 사용해보기

github에 들어가서 libc-database라고 검색해보자. 자세한 설명은 이곳에 나와있습니다. https://github.com/niklasb/libc-database niklasb/libc-database Build a database of libc offsets to simplify exploitation - niklasb/libc-database g

s1m0hya.tistory.com

 

https://hannahsecurity.tistory.com/entry/gdb-%EB%A1%9C%EC%BB%AC%EC%84%9C%EB%B2%84%EC%9D%98-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%8B%A4%EB%A5%B8-%EA%B2%BD%EC%9A%B0

 

[gdb] 로컬/서버의 라이브러리 다른 경우

서버의 라이브러리 정보 찾는 방법 서버에서 어떻게든 주소 하나 leak해서 뒤에 3자리(16진수) 입력해주면 됨 (왜냐하면 aslr나 pie 적용되어있어도 뒤에 12bit는 똑같음 페이지 기법 때문에) https://lib

hannahsecurity.tistory.com

'프로그래밍 > 해킹' 카테고리의 다른 글

웹 해킹 퀴즈 모음  (0) 2024.08.30
Format String Bug  (0) 2024.08.18
Ghidra 사용법  (0) 2024.08.03
IDA 사용법  (0) 2024.08.03
XSS Filtering Bypass 실습 문제  (0) 2024.07.22