9oat's LAB
Libc-Database를 이용한 함수 주소 구하기 본문
로컬 익스플로잇 시엔 gdb에서 제공하는 print 명령어로 손쉽게 원하는 함수의 주소를 찾을 수 있지만, CTF 등 원격 익스플로잇의 경우 라이브러리가 다르니 함수의 주소를 찾기가 어렵다.
이 때 함수 주소를 찾기 쉽도록 해주는 도구가 바로 Libc-Database.
[사진 1] ASLR이 적용된 후 Library Base 변화
Libc-Database를 설명하기 전에 원리 겸 라이브러리에 대해 설명하자면 함수 주소는 Library Base + offset 이다. ASLR이 적용되어 있다 하더라도 Library Base가 랜덤으로 설정될 뿐 함수의 offset은 변하지 않는다. 이 offset은 Libc 버전 별로 달라지며, Libc 버전 별 offset을 DB화 시킨 것이 Libc-Database다. 물론 모든 Libc의 정보를 갖고있는 것은 아니라는 점을 유의하고, 사용자가 Libc를 추가하여 사용할 수도 있다.
Libc-Database는 offset들의 끝 12bit를 저장하고 있는데, 이는 Library Base의 끝 12bit가 0으로 설정되기 때문인 걸로 보인다.(즉 ASLR이 동작한다 하더라도 함수 주소의 끝 12bit는 바뀌지 않고, 이 값은 offset이다)그래서 함수 주소의 끝 3자리(12bit)를 이용해 검색하면, 사용하고 있는 Libc의 버전을 알려주는 식이다. 그럼 offset을 알 수 있으니 이를 이용하여 Library Base를 구하고, 필요한 함수의 offset을 이용해 함수 주소를 계산하여 사용할 수 있게 되는 것.
https://github.com/niklasb/libc-database 에서 내려받을 수 있다.
[사진 2] libc-database
libc-database는 [사진 2]와 같이 구성되어 있다.
add, dump, find, get, identify는 명령어들이고, README.md는 명령어의 사용법이 적혀있다. 그리고 db에 libc 관련한 파일들이 저장되는 듯. 사용자가 libc를 추가할 때도 이 디렉토리를 이용하면 될 것 같다.
다음은 각 명령어들의 사용법이다.
[사진 3] get
get
현재 로컬에서 사용 중인 libc를 자동으로 DB에 추가하는 명령어.. 라고 하는데 잘 안되는 거 같다.
로컬에 있는 Libc를 추가할 일이 있다면 peda의 vmmap과 같은 명령어를 이용해 libc파일의 경로를 알아낸 뒤 libc-database의 add명령어로 해당 libc를 추가하여 쓰는게 정확한 듯 하다.
[사진 4] add
add [libc 파일]
사용자가 임의로 libc를 DB에 추가하는 명령어.
[사진 5] find
find [함수명] [주소 끝 3글자(12bit)]
함수명과 12bit를 이용해 DB에서 libc 버전을 검색하는 명령어.
여러개의 함수들을 한 번에 입력하여 검색할 수도 있다.
[사진 6] dump
dump [id]
find 명령어로 얻은 id를 이용해 exploit에 쓰이는 주요 함수/문자열의 offset을 출력하는 명령어.
모든 함수의 offset을 출력하는 게 아니기 때문에 사실상 [사진 6]에 보이는 함수들의 주소를 알아야만 제대로 Libc-database를 사용할 수 있다.
왜냐면 Library Base주소를 알아내야 하는데 Library Base주소는 함수 주소 - offset 으로 알아내야 하고, 알 수 있는 offset은 사진에 보이는 게 전부기 때문. 그렇기에 사용할 수 있는 함수 역시도 [사진 6]속의 함수가 전부다.
그래도 보통 [사진 6]에 있는 함수 주소를 구할 수 있는 경우가 대부분이기 때문에 크게 무리는 없는 듯.
[사진 7] identify
identify [libc 파일]
해당 libc의 정보가 이미 DB에 존재하는 지 검사하는 명령어
명령어의 사용법을 알았으니 실제로 어떻게 쓰면 되는지 보자.
read 함수의 주소를 알고있다고 가정하고(0xf7edaaf0), system 함수와 문자열 "/bin/sh" 를 찾는 과정이다.
[사진 8] libc를 알아내자
read 함수의 주소 끝 12bit(af0)를 이용해 libc 버전과 id를 알아낸다.
만약 검색했을 때 libc가 두 개 이상 출력된다면 알고 있는 함수 주소를 하나 더 입력하여 검색하면 된다. 하지만 하나밖에 모른다면 음.. 찍어야겠지..
[사진 9] offset 알아내기
id를 이용해 offset을 구했으니 Library Base를 구해보자.
read 함수의 주소가 0xf7edaaf0이고, offset이 0xd5af0 이므로
Library Base = 0xf7edaaf0 - 0xd5af0 = 0xf7e05000
system 함수의 offset은 0x3ada0이고, 문자열 "/bin/sh"의 offset은 0x15b9ab다. 이를 Library Base와 더하여 주소를 알아낸다.
system() = 0xf7e05000 + 0x3ada0 = 0xf7e3fda0
&/bin/sh = 0xf7e05000 + 0x15b9ab = 0xf7f609ab
[사진 10] 짠
뭐 당연한 거지만 Libc-Database는 특정한 함수 중 하나라도 그 주소를 알고 있어야만 사용할 수 있다. 문제에서 대놓고 함수의 주소를 주는 경우는 드물기 때문에 함수의 주소를 알려면 Memory Leak이 필수다.
그래서 다음 게시물은 Memory Leak인 걸로..
참고한 글 : http://kaspyx.tistory.com/86 [잘지내나요, 내청춘]
Ubuntu 16.04 / gcc 5.4.0
'Study > System' 카테고리의 다른 글
Pwnable.kr input 풀다가 궁금한 거 (0) | 2017.07.16 |
---|---|
Memory Leak 관련한 삽질(Feat. Buffering) (0) | 2017.07.02 |
Memory Leak 기법 (0) | 2017.06.30 |
Dynamic Link 시 함수 호출 과정 (0) | 2017.06.26 |
함수 주소에 대한 궁금증 (0) | 2017.05.20 |