/ POSTS

windows-0x09

0x09 DEP(3)

이번 시간에는 DEP의 마지막 주제인 ROP에 대해서 알아보도록 하겠습니다.

ROP (Return Oriented Programming)

ROP는 Gadget으로 Chain을 구성하여 API를 호출하는 방식의 공격 기법입니다.

주로 VirtualProtect()나 SetProcessDEPPolicy() 등 메모리와 관련된 함수들을 호출하며,

Shellcode를 실행할 수 있도록 실행 권한을 추가하는 방향으로 진행됩니다.

이번 연재에서는 가장 흔하고 쉬운 방식인 VirtualProtect() API를 호출해서 DEP를 우회하도록 하겠습니다.

VirtualProtect 함수

VirtualProtect는 4개의 인자를 가지며, 특정 메모리 영역의 실행 권한을 변경해주는 함수입니다.

BOOL WINAPI VirtualProtect (
		_In_ LPVOID lpAddress, 		 # 권한을 변경할 메모리 영역의 시작 주소
		_In_ SIZE_T dwSize,	   		 # 변경할 크기
		_In_ flNewProtect,     		 # 변경할 속성 값
		_Out_ PDWORD lpflOldProtect, # 이전 값 저장 (쓰기 가능한 영역)
	);

VirtualProtect 함수는 변경을 원하는 메모리 영역의 시작 주소를 기준으로 원하는 크기만큼 실행 권한을 변경해줍니다.

그럼 ShellCode를 넣어둔 뒤, 그 크기만큼 실행 권한을 주면 되겠네요.

이 내용을 STACK으로 구성하면 다음과 같습니다.

[그림 1-1]

그림처럼 STACK을 구성할 경우, VirtualProtect()가 호출되어 ShellCode가 들어있는 메모리 주소에 실행 권한이 생길 것이고,

다음 RET에서 JMP ESP가 호출되어 ShellCode가 실행될 것 입니다.

그리고 이 모양의 STACK을 구성하기 위해 PUSHAD 명령어를 이용할 것 입니다. STACK 구성이 좀 더 쉽겠죠?

PAYLOAD 구성

Mona.py를 이용해서 ROP Chain 구성에 사용할 Gadget들을 찾아 보겠습니다. ( !mona modules )

[그림 1-2]

Gadget은 위의 Module들 중에 ASLR이 적용되어 있지 않은 example.dll에서 가져다 쓰면 되겠네요.

이제 여기서 Gadget을 구해서 값들을 맞춰주기만 하면 되는데,,, 일일이 하나씩 찾아서 넣으면 엄청나게 많은 시간이 소요되겠죠??

하나하나 다 찾아다닐 시간은 없으니까 mona.py에서 제공하는 기능을 활용하겠습니다.

!mona rop -m example

이 명령어를 사용하면 mona.py에서 자동으로 rop 공격에 필요한 Gadget들을 example.dll에서 찾아 파일로 생성해줍니다.

[그림 1-3]

여러 언어에 맞게 추천을 해주는데 여러분 환경에 맞는 값을 사용하시면 됩니다.

이제 필요한 Gadget들을 아주 손쉽게 찾아왔는데 한 가지 생각해야 할 점이 있습니다.

바로 VirtualProtect의 함수 주소입니다.

ASLR이 적용되어 있으면 Window API 함수들의 주소도 계속해서 변할텐데 어떻게 주소를 가지고 올 수 있는 걸까요?

Gadget 파일을 잘 보시면 VirtualProtect에 IAT라고 적혀있는 것을 보실 수 있을 겁니다.

IAT(Import Address Table)는 프로그램에서 사용되는 라이브러리에서 어떤 함수들을 사용하고 있는지, 그 함수들의 정보를 기술한 테이블입니다.

아래와 같이 example.dll의 IAT를 살펴보면 우리가 사용하고자 하는 VirtualProtect() 함수의 정보가 들어있는 것을 확인하실 수 있습니다.

[그림 1-4]

이렇게 VirtualProtect() 정보가 들어 있는 경우에는 IAT 값에서 시작 주소를 가져다가 쓰면 되는 것이죠.

없다면? 동적으로 찾아오도록 Gadget을 구성하면 됩니다.

Null Byte 제거

공격을 성공적으로 하기 위해 Payload에 존재하는 Null Byte들을 제거해줘야겠죠?

mona가 만들어 준 값들엔 Null Byte가 존재해서 Payload 전달이 완전하게 이루어지지 않는답니다.

그래서 다음과 같이 수정을 했습니다.

[그림 1-5]

먼저, 0x201, 0x40 같은 값을 넣어줘야 하는데 Null이 존재하므로 0xfffffdff, 0xffffffc0를 넣고 neg를 사용해서 값을 생성해줬습니다.

그리고 Gadget 주소 중에 Null이 존재하는 것은 다른 Gadget 찾아서 교체해준 내용입니다.

mona만 믿고 Payload를 구성하시면 안됩니다. 잘 살펴보고 Null은 반드시 제거해주셔야 합니다.

이어서 DBG로 살펴보면 다음과 같습니다.

[그림 1-6]

strcpy가 실행되고 나서의 모습입니다. 각 Gadget들이 연속해서 실행된 뒤, VirtualProtect() 함수가 실행될 것이고,

마지막에 JMP ESP가 실행되면서 ShellCode가 실행되겠네요.

[그림 1-7]

잘 실행되네요^^

지금까지 DEP에 대해서 알아봤습니다.

다음 연재부터는 Heap Exploit으로 찾아뵙도록 하겠습니다.