-
[02-08 공부정리(RTL정리)]공부정리 2018. 2. 8. 03:32
오늘은 RTL에 대해서 공부했으니, 실습한 부분은 정리하겠다.
[RTL이란?]
Return To Library로 프로그램 ret(리턴 값)에 공격자가 원하는 라이브러리 함수 주소를 로드 시켜
해당 라이브러리 함수를 실행하는 공격기법이다. 예를들면 System함수를 호출한다거나 또, System함수를 호출한다거나...
맞다. 우린 쉘을 따면 된다.
또, RTL공격은 메모리 보호 기법중 NX Bit와 DEP를 우회한다.
NX bit(Never Execute bit) : ELF 보호기법. NX특성으로 모든 메모리영역을 데이터 저장용도로만 사용한다.
따라서 쉘코드 실행을 방지한다.
DEP(Data Execution Prevention) : PE 보호기법. 데이터 실행 방지로 스택이나 힙에서 쉘코드 실행을 방지한다.
간단하게 말하면, 쉘코드 실행을 방지하는 보호기법이다.
자 이제 그럼 RTL공격으로 System("/bin/sh")를 실행해보자!
[Test.c SourceCode]
123456789#include <stdio.h>#include <string.h>int main(int agrc,char **argv){char buf[64];strcpy(buf,argv[1]);printf(buf);return 0;}cs 인자값을 strcpy로 길이값을 체크하지 않고 buf에 저장하면서 BOF가 발생하는 소스코드이다.
[checksec test]
RTL을 처음 실습하는 것이기 때문에 실습편의를 위해 보호기법은 다 꺼두었다.
우선 공격 시나리오는 이러하다.
1. 파일에 적용된 메모리 보호기법을 확인한다. -> All off
2. Memory leak. 리턴주소를 알아낸다.
3. RTL. 시스템함수 주소를 리턴주소로 바꾼다.
[SFP Crash]
스택 구조를 보면
===Top===
buf[64]
SFP
RET
===Bottom===
이렇게 되어 있다.
따라서 A를 68바이트 줬으니 SFP공간이 41로 차있으니 Segmentation Error가 뜬 것이다.
그럼 RET부분을 BBBB로 채우고 core덤프를 확인해보자
[Core dump]
A를 68바이트 만큼 주고 RET부분에 BBBB를 줬더니
0x42424242주소로 RET되는걸 확인할 수 있다.
따라서 저 부분에 시스템 함수 라이브러리주소를 주면된다.
그럴려면 시스템 함수 주소를 알아야한다.
[System address]
자 시스템 함수의 주소를 찾았다.
이제 인자값으로 넘겨줄 /bin/sh를 찾아야한다.
나는 환경변수 설정으로 /bin/sh를 넘겨줬다.
스택이 고정되어 있는 0x8048000에서 아스키코드값이 될 만한 값을 찾아서
그 아스키코드이름의 실행파일을 /bin/sh로 만들어서 쉘이 실행되도록 했다.
말로 설명하는 것보다 직접 보는게 이해가 더 빠를 것이다.
[0x8048000 Stack]
여기서 보면 0x8048038에 아스키코드로 "4"인 값이 들어가있다.
난 이 값을 /bin/sh로 등록해서 4가 넘어가면 /bin/sh가 실행되도록 설정했다.
[환경변수 등록]
./4에 쉘을 복사해서 4가 실행되면 쉘이 실행되도록 만들고
환경변수 PATH에 현재 위치를 등록해서 4만 실행해도 쉘이 실행되도록 설정해준다.
이렇게 설정하면 system("/bin/sh") == system("4") 처럼 인자값으로 4를 넘겨도 같은 의미가 된다.
이제 필요한 정보들은 다 얻었으니 RTL공격을 시도해보자
[RTL 성공]
보는바와 같이 쉘을 성공적으로 따내고 ls, whoami 명령어를 입력한 모습이다.
여기서 인자값 부분이 생각했던것과 다른점을 눈치챌 수 있을 것이다.
첫번째 값 : System함수 주소값
두번째 값 : 더미값
세번째 값 : 4의 주소값
예상대로라면 "시스템함수 주소값"+"4의 주소값"을 보내야 하는데 중간에 더미값이 하나 끼어있다.
이 더미값의 정체는 시스템함수의 RET값이다.
정상적인 주소값을 넣어주면 시스템함수가 끝나고 넣어줬던 주소값으로 복귀할 것이다.
하지만 우린 쉘만 따내면 그 후론 상관이 없으니 그냥 AAAA라는 더미값을 넣어준 것이다.
스택을 직접 확인해보자
[System( ) 호출 전 스택]
스택에 저렇게 저장이 되어있고 System( )가 호출되면
[System( ) 호출 후 스택]
보는 바와 같이 AAAA가 RET으로 넘어가고 0x08048038이 인자값으로 넘어갔음을 확인할 수 있다.
[System( ) 복귀]
그리고 계속 진행해서 쉘이 실행되고 쉘을 종료해서 System( )가 종료되면
우리가 넣어준대로 0x41414141로 복귀하는 것을 확인할 수 있다.
이것으로 RTL에 대한 실습은 끝났다.
다음에는 ROP에 대해서 알아보도록 하겠다.
'공부정리' 카테고리의 다른 글
[02-14 공부정리(FSB 정리)] (0) 2018.02.15 [02-11 공부정리(Chaining RTL 정리)] (0) 2018.02.11 [02-10 공부정리] (0) 2018.02.10 [02-07 공부정리] (2) 2018.02.07 [02-06 공부정리] (1) 2018.02.06 댓글