Тема: VBScript & LangMF: исследование Win32 PE файлов
Данное предварительное решение предназначено для отображения в память Win32 PE файлов и получения некоторых характерных для них параметров. В качестве надежды на возможность глубокого изучения Win32 операционных систем, с использованием скриптовых интерфейсов программирования.
Используется библиотека dynwrap.dll, а также библиотека LangMf.dll или установленный LangMF 7.7.
Проверялось на Win98/Millenium/XP.
'---------------------------------------------------------------
'Данный предварительный скрипт предназначен для исследования
'Win32 PE файлов и получения некоторых специфических параметров
'характерных для этих файлов.
'---------------------------------------------------------------
'Language: VBScript
'Используется библиотека dynwrap.dll
'Используется библиотека LangMf.dll
'или установленный LangMF 7.7
'OS Win98/Millenium
'---------------------------------------------------------------
'Дополнительно:
' http://www.wasm.ru/print.php?article=1001013
' Справка "Win32 Api Первые Шаги"-WinApi-шаг 23-27
' Возможно потребуется Hiew
'---------------------------------------------------------------
Set RtlMoveMemoryC =CreateObject("DynamicWrapper")
RtlMoveMemoryC.Register _
"KERNEL32.DLL","RtlMoveMemory","f=s","i=lll","r=l"
'---------------------------------------------------------------
'Константы CreateFileMapping/
Const PAGE_READONLY =2
Const PAGE_READWRITE =4
Const PAGE_WRITECOPY =8
Const PAGE_EXECUTE =16
Const PAGE_EXECUTE_READ =32
Const SEC_IMAGE =&H1000000
'Константы MapViewOfFile/
Const FILE_MAP_ALL_ACCESS =&HF0000
Const FILE_MAP_READ =4
'---------------------------------------------------------------
LMFCode= _
"<#Module=filecr> \" & _
";/Константы CreateFile/ \" & _
"Const GENERIC_READ =&H80000000 \" & _
"Const GENERIC_WRITE =&H40000000 \" & _
"Const FILE_SHARE_READ =1 \" & _
"Const FILE_SHARE_WRITE =2 \" & _
"Const CREATE_NEW =1 \" & _
"Const CREATE_ALWAYS =2 \" & _
"Const OPEN_EXISTING =3 \" & _
"Const OPEN_ALWAYS =4 \" & _
"Const FILE_ATTRIBUTE_NORMAL =&H80 \" & _
"Const FILE_ATTRIBUTE_READONLY =&H1 \" & _
";--------------------------------------------------------------\" & _
"Sub Load(cmdstr) \" & _
"End Sub \" & _
";--------------------------------------------------------------\" & _
";Диалог открытие файла \" & _
"Function OpenFileDlg() \" & _
"OpenFileDlg=sys.cdlg.showopen( 'Выбор PE файла', _ \" & _
"'Dll files (*.dll)|*.dll|All files (*.*)|*.*', _ \" & _
" Sys.WinInfo('system'), _ \" & _
" '.dll') \" & _
"End Function \" & _
";--------------------------------------------------------------\" & _
"Function OpenPEFile(FilePE) \" & _
";Открытие файла \" & _
"OpenPEFile=Sys.DynApi.CallFunction( _ \" & _
" 'KERNEL32.DLL','CreateFileA', _ \" & _
" FilePE, _ \" & _
" GENERIC_READ, _ \" & _
" FILE_SHARE_READ, _ \" & _
" 0, _ \" & _
" OPEN_EXISTING, _ \" & _
" FILE_ATTRIBUTE_READONLY, _ \" & _
" 0) \" & _
"End Function \" & _
";--------------------------------------------------------------\" & _
"Function GetVarPtr(cVar) \" & _
" GetVarPtr=VarPtr(cVar) \" & _
"End Function \" & _
"<#Module>"
'---------------------------------------------------------------
Set LMActiveX=CreateObject("Atomix.LangMF")
LMFCode=Replace(LMFCode,Chr(39),Chr(34))
LMFCode=Replace(LMFCode,"\",vbCRLF)
LMFCode=Replace(LMFCode,";","'")
LMActiveX.Command LMFCode
'---------------------------------------------------------------
'Диалог открытие файла
FileName=LMActiveX.FuncRun("OpenFileDlg",1)
If FileName=vbNullString Then
LMActiveX.Reset
WScript.Quit
End If
FileName1=FileName
'После пропуска через OpenPEFile значение FileName
'теряет читабельность,поэтому заранее сохранено
'в переменной FileName1
'-------------------------------------------------------
'Открытие файла
hFile=LMActiveX.FuncRun("OpenPEFile",1,FileName)
If hFile=-1 Or hFile=0 Then
Msgbox "Невозможно открыть указанный файл," & _
"имя задано неверно,либо не задано вовсе.", _
vbExclamation,"Open File Error"
LMActiveX.Reset
WScript.Quit
End If
'---------------------------------------------------------------
'Отображение файла в память.В отображенном виде PE файл
'представляет из себя развернутую структуру с базовым адресом hMap,
'содержащую байт-код.Мэппированный файл подобен просмотру в Hiew,
'в режиме дизассемблера.
Set CreateFileMappingAC=CreateObject("DynamicWrapper")
CreateFileMappingAC.Register _
"KERNEL32.DLL","CreateFileMappingA","i=hlllls","f=s","r=l"
hMap=CreateFileMappingAC.CreateFileMappingA( _
hFile, _
0, _
PAGE_READONLY, _
0, _
0, _
"")
'---------------------------------------------------------------
Set MapViewOfFileC=CreateObject("DynamicWrapper")
MapViewOfFileC.Register _
"KERNEL32.DLL","MapViewOfFile","i=hllll","f=s","r=l"
hView=MapViewOfFileC.MapViewOfFile( _
hMap, _
FILE_MAP_READ, _
0, _
0, _
0)
'Дескриптор hView соответствует адресу заголовка IMAGE_DOS_HEADER
'в выделенной области памяти и является базовым адресом
'структуры отображенного файла
'---------------------------------------------------------------
'Получение сигнатуры заголовка IMAGE_DOS_HEADER
DOS_SIGN=GetDataDWORD(hView,2,0)
'---------------------------------------------------------------
'Получение адреса структуры заголовка IMAGE_NT_HEADERS
'Этот последний параметр структуры IMAGE_DOS_HEADER соответствует
'смещению 60=0x3C
IMAGE_NT_HEADERS_ADDR=GetDataDWORD(hView,4,60)
'---------------------------------------------------------------
'Получение сигнатуры заголовка IMAGE_NT_HEADERS
NT_SIGN=GetDataDWORD(hView,4,IMAGE_NT_HEADERS_ADDR)
NT_SIGN=InvertDataDWORD(NT_SIGN)
If NT_SIGN<>"50450000" Then
Msgbox "Указанный файл не является исполняемым PE файлом для Win32", _
vbExclamation,"Open File Error"
ReleaseMapping()
LMActiveX.Reset
WScript.Quit()
End If
'---------------------------------------------------------------
'Получение количества секций PE файла из структуры
'IMAGE_FILE_HEADER.Основная тонкость-правильно подобрать
'смещение и количество перемещаемых байт.
SNUM=GetDataDWORD(hView,2,IMAGE_NT_HEADERS_ADDR+6)
'---------------------------------------------------------------
WScript.Echo _
"[Имя открываемого файла]" & vbCR & FileName1 & vbCR & _
"[Дескриптор файла]" & vbCR & Hex(hFile) & vbCR & _
"[Базовый адрес отображения]" & vbCR & Hex(hMap) & vbCR & _
"[Сигнатура DOS]" & vbCR & Hex(DOS_SIGN) & vbCR & _
"[Адрес структуры заголовка IMAGE_NT_HEADERS]" _
& vbCR & Hex(IMAGE_NT_HEADERS_ADDR) & vbCR & _
"[Сигнатура NT]" & vbCR & NT_SIGN & vbCR & _
"[Количество секций файла]" & vbCR & SNUM
'---------------------------------------------------------------
'Можно использовать Hiew,чтобы проверить правильнось значения
'NumberOfSections [количество секций в файле].Откройте заданный
'файл в Hiew и переведите редактор в режим дизассемблера.Нажав
'кнопку F8 можно усмотреть NumberOfSections и сравнить со значением
'получаемым через скрипт.
ReleaseMapping()
'************ Вспомогательные функции **************************
'[Обьязательное освобождение ресурсов отображения]
'[Закрытие дескрипторов]
'---------------------------------------------------------------
Function ReleaseMapping()
'Внимание!Перед завершением работы скрипта все дескрипторы
'должны быть обьязательно закрыты.В противном случае
'экземпляр мэппированного файла сохранится в памяти
'что приведет к невозможности повторного исполнения
'отображения файла в память.
Set UnmapViewOfFileC=CreateObject("DynamicWrapper")
UnmapViewOfFileC.Register _
"KERNEL32.DLL","UnmapViewOfFile","i=h","f=s"
UnmapViewOfFileC.UnmapViewOfFile hView
'---------------------------------------------------------------
Set CloseHandleC=CreateObject("DynamicWrapper")
CloseHandleC.Register _
"KERNEL32.DLL","CloseHandle","i=h","f=s"
CloseHandleC.CloseHandle hView
CloseHandleC.CloseHandle hMap
CloseHandleC.CloseHandle hFile
Set UnmapViewOfFileC =Nothing
Set RtlMoveMemoryC =Nothing
LMActiveX.Reset
End Function
'[Инвертирование числа DWORD]
'---------------------------------------------------------------
Function InvertDataDWORD(data)
data=CStr(Hex(data))
data=String(8-Len(data),"0") & data
B1=Mid(data,1,2)
B2=Mid(data,3,2)
B3=Mid(data,5,2)
B4=Mid(data,7,2)
InvertDataDWORD=B4 & B3 & B2 & B1
End Function
'[Извлечение DWORD данных из отображенного файла]
'---------------------------------------------------------------
Function GetDataDWORD(lpData,iSize,iOffset)
Dim pDest,tdOffset
GetDataDWORD=CLng(0)
pDest=LMActiveX.FuncRun("GetVarPtr",1,GetDataDWORD)
GetDataDWORD=CLng(0)
RtlMoveMemoryC.RtlMovememory pDest+8,lpData+iOffset,iSize
End Function
'---------------------------------------------------------------
'Poltergeyst
Пример результата работы скрипта:
[Имя открываемого файла]
C:\WINDOWS\notepad.exe
[Дескриптор файла]
580
[Базовый адрес отображения]
5C4
[Сигнатура DOS]
5A4D
[Адрес структуры заголовка IMAGE_NT_HEADERS]
E0
[Сигнатура NT]
50450000
[Количество секций файла]
3
Скрипт должен показывать такое сообщение для DLL и EXE файлов. Если файл не является PE, например текстовый, то будет показано соответствующее оповещение.
Автор скрипта - Poltergeyst.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.