Lazenca | RTL(Return to Libc) – x86

133210·2021년 7월 26일
0

2020 시스템

목록 보기
18/25
post-thumbnail

RTL (Return to Libc)

Return address 영역에 공유 라이브러리 함수의 주소로 변경해, 해당 함수를 호출하는 방식. 해당 기법을 이용해 NX bit(DEP)를 우회할 수 있음

1 Calling Convention

1) Cdecl(C declaration)
∙ 해당 호출 규약(Calling Convention)은 인텔 x86 기반 시스템의 C/C++ 에서 사용되는 경우가 많음
∙ 기본적으로 Linux Kernel에서는 Cdelcl 호출 규약(Calling Convention)을 사용함
∙ 함수의 인자 값을 Stack에 저장하며, 오른쪽부터 왼쪽 순서로 저장함.
∙ 함수의 Return값EAX 레지스터에 저장됨
∙ 사용된 Stack 정리는 해당 함수를 호출한 함수가 정리함

다음 코드는 4개의 인자를 전달 받고, 반환값을 ret 변수에 저장

앞의 코드를 cdecl 형태의 assembly code로 변환한 것
4개의 인자 값을 push 명령어를 이용해 stack에 저장함.
함수 호출 후 반환된 값은 EAX 레지스터에 저장되며, 해당 값을 ret 변수에 저장함

2) Example

example 코드 (test.c)

main() 함수에서 vuln 함수의 인자 값을 push 명령어를 이용해 Stack에 저장

Stack에 저장된 vuln() 함수의 인자 값 확인

vuln() 함수는 main() 함수에서 전달된 인자 값 사용
main() 함수에서 사용하던 호출 프레임을 Stack에 저장 (“push ebp”)
이전 함수에서 사용하던 호출 프레임은 ebp 레지스터에는 저장되어 있음
vuln() 함수에서 사용할 새 호출 프레임이 ebp 레지스터에 초기화 됨(“mov ebp, esp”). ebp 레지스터를 활용하여 Main() 함수로부터 전달된 인자 값을 활용할 수 있음

DWORD PTR [ebp+*] 영역에서 4번째 인자 값을 확인할 수 있음
DWORD PTR [ebp+0x8]부터 DWORD PTR [ebp+0x10]까지 vuln() 함수에 전달된 인자 값
DWORD PTR [ebp+0x4] 영역에는 해당 함수 호출 후 돌아갈 Return Address가 저장되어 있음
DWORD PTR [ebp] 영역에는 이전 호출 프레임이 저장되어 있음

ret2libc 기법 사용시 인자 값을 전달하기 위해서는 Return Address의 4byte 뒤에 인자 값을 전달해야 함

2 Proof of concept

ret2libc.c 코드
main() 함수는 vuln() 함수 호출
vuln() 함수는 read 함수를 이용해 사용자로부터 100개의 문자열을 입력받음. 여기서 buf 변수의 크기는 50byte이기 때문에 Stack Overflow 발생.
libc의 Base address를 얻기 위해 libc 영역에서 printf() 함수의 주소 출력

Build

0x0804851b: vuln() 함수의 첫번째 명령어
0x08048586: read() 함수 호출
0x08048595: vuln() 함수의 RET 명령어

ESP 레지스터가 가리키고 있는 최상위 Stack의 주소는 0xffffd06c
0xffffd06c 영역에 Return address(0x080485ac)가 저장되어 있음

buf 변수의 주소 확인 가능
buf 변수의 위치는 0xffffd02a이며, Return address와 66byte 떨어져 있음

Return address 값이 변경되어 0xffffd06c 영역에 0x52525151(“QQRR”)이 저장된 것을 확인 가능

시스템 함수의 형태
인자 값으로 실행할 command의 경로를 문자열로 전달 받음.
RTL 기법을 사용해 Shell을 실행하기 위해 “/bin/sh” 문자열을 전달해야 함.

0xf7e48670(printf function address in libc) – 0xf7dff000(libc Start Address) = 0x49670(libc Base Address offset)
0xf7e39da0(system function address in libc) – 0xf7dff000(libc Start Address) = 0x3a940(system function address offset)

“/bin/sh” 문자열 찾기

0xf7f5902b(“/bin/sh” string address in libc) – 0xf7dff000(libc Start Address) = 0x15ba0b(“bin/sh” string Address offset)

3 Exploit

프로그램 종료 시 Error 발생
system() 함수 호출 후에 0x42424242(BBBB) 영역으로 이동하려고 했기 때문
0x42424242 영역에 system() 함수 호출 후 이동 할 영역의 주소를 저장하면 Error가 발생하지 않음. 대부분 exit() 함수의 주소를 저장함

0개의 댓글