Выполнение скриптов JScript и VBScript из памяти
Выполнение скриптов JScript и VBScript из памяти
Windows Script Host - стандартный компонент операционной системы Windows - сервер выполнения скриптов на языках VBScript и JScript, а также на других, если их обработчики установлены в системе. Сценарии на WSH способны взаимодействовать с программами, имеющими объектный скриптовый интерфейс путем доступа к их объектам и свойствам. За счет этого сценарии могут выполнять операции с файлами и каталогами, системным реестром, базами данных, производить сложные расчеты, манипуляции со строками и т.п. Было бы большим упущением не задействовать подобную мощь в своих программах.
Материал большой, писанины будет много. Перед тем, как использовать какой-то инструмент, надо удостовериться, что он нам доступен. Поэтому начнем с разбора способа получения списка установленных в системе скриптовых движков. Но перед этим традиционная пачка данных, необходимых для работы с нужными нам COM-объектами.
Code (Assembler) : Убрать нумерацию
- CLSCTX_INPROC_SERVER = 0x01
- CLSCTX_INPROC_HANDLER = 0x02
- CLSCTX_LOCAL_SERVER = 0x04
- CLSCTX_REMOTE_SERVER = 0x10
- CLSCTX_SERVER = CLSCTX_INPROC_SERVER + CLSCTX_LOCAL_SERVER\
- + CLSCTX_REMOTE_SERVER
- CLSCTX_ALL = CLSCTX_INPROC_HANDLER + CLSCTX_SERVER
- S_OK = 0
- ; GUID {0002E005-0000-0000-C000-000000000046}
- CLSID_StdComponentCategoriesMgr \
- dd 00002E005h
- dw 00000h
- dw 00000h
- db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
- ; IEnumGUID Interface
- struct IEnumGUID
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IEnumGUID
- Next dd ? ; 00Ch
- Skip dd ? ; 010h
- Reset dd ? ; 014h
- Clone dd ? ; 018h
- ends
- ; GUID {0002E013-0000-0000-C000-000000000046}
- IID_ICatInformation \
- dd 00002E013h
- dw 00000h
- dw 00000h
- db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
- ; IID_ICatInformation Interface
- struct ICatInformation
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; ICatInformation
- EnumCategories dd ? ; 00Ch
- GetCategoryDesc dd ? ; 010h
- EnumClassesOfCategories dd ? ; 014h
- IsClassOfCategories dd ? ; 018h
- EnumImplCategoriesOfClass dd ? ; 01Ch
- EnumReqCategoriesOfClass dd ? ; 020h
- ends
- ; GUID {F0B7A1A2-9847-11CF-8F20-00805F2CD064}
- CATID_ActiveScriptParse \
- dd 0F0B7A1A2h
- dw 09847h
- dw 011CFh
- db 08Fh, 020h, 000h, 080h, 05Fh, 02Ch, 0D0h, 064h
Code (Assembler) : Убрать нумерацию
- ; Инициализировать COM-объект
- invoke CoInitialize,NULL
- ; Создать объект
- invoke CoCreateInstance,CLSID_StdComponentCategoriesMgr,\
- NULL,\
- CLSCTX_ALL,IID_ICatInformation,pCatInformation
- cmp eax,S_OK
- jne wmclose
- ; Получить список скриптовых движков
- mov eax,[pCatInformation]
- mov eax,[eax]
- stdcall dword [eax+ICatInformation.EnumClassesOfCategories],\
- [pCatInformation],\
- 1,CATID_ActiveScriptParse,0,0,pEnumClasses
- loc_loop:
- ; Получить следующий объект списка движков
- mov eax,[pEnumClasses]
- mov eax,[eax]
- stdcall dword [eax+IEnumGUID.Next],[pEnumClasses],\
- 1,clsid,0
- cmp eax,S_OK
- jne loc_done
- ; Получить название движка
- invoke ProgIDFromCLSID,clsid,ProgramID
- ; Получить строку CLSID
- invoke StringFromCLSID,clsid,ClsidStr
- ; Сформировать строку вида "CLSID\{CLSID}"
- invoke wsprintf,buff,mask1,[ClsidStr]
- add esp,12
- mov [len],MAX_PATH
- ; Получить описание движка из реестра
- invoke RegGetValue,HKEY_CLASSES_ROOT,buff,\
- NULL,RRF_RT_REG_SZ,NULL,desc,len
- ; [ProgramID] -> строка идентификатора движка
- ; [ClsidStr] -> строка CLSID движка
- ; desc -> строка описания скриптового движка
- ; Освободить память
- invoke CoTaskMemFree,[ProgramID]
- invoke CoTaskMemFree,[ClsidStr]
- ; Следующий объект
- jmp loc_loop
- loc_done:
- ; Прибраться за собой
- mov eax,[pEnumClasses]
- mov eax,[eax]
- stdcall dword [eax+IEnumGUID.Release],[pEnumClasses]
- mov eax,[pCatInformation]
- mov eax,[eax]
- stdcall dword [eax+ICatInformation.Release],[pCatInformation]
- ; Удалить объект
- invoke CoUninitialize
Итак, мы удостоверились, что нужный нам обработчик скриптов в системе присутствует, значит будем запускать скрипты. Перед кодом следует очередная пачка необходимых для работы данных.
Code (Assembler) : Убрать нумерацию
- ; GUID {00000000-0000-0000-C000-000000000046}
- IID_IUnknown \
- dd 000000000h
- dw 00000h
- dw 00000h
- db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
- ; GUID {BB1A2AE1-A4F9-11CF-8F20-00805F2CD064}
- IID_IActiveScript \
- dd 0BB1A2AE1h
- dw 0A4F9h
- dw 011CFh
- db 08Fh, 020h, 000h, 080h, 05Fh, 02Ch, 0D0h, 064h
- ; IID_IActiveScript Interface
- struct IActiveScript
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IActiveScript
- SetScriptSite dd ? ; 00Ch
- GetScriptSite dd ? ; 010h
- SetScriptState dd ? ; 014h
- GetScriptState dd ? ; 018h
- Close dd ? ; 01Ch
- AddNamedItem dd ? ; 020h
- AddTypeLib dd ? ; 024h
- GetScriptDispatch dd ? ; 028h
- GetCurrentScriptThreadID dd ? ; 02Ch
- GetScriptThreadID dd ? ; 030h
- GetScriptThreadState dd ? ; 034h
- InterruptScriptThread dd ? ; 038h
- Clone dd ? ; 03Ch
- ends
- ; GUID {BB1A2AE2-A4F9-11CF-8F20-00805F2CD064}
- IID_IActiveScriptParse \
- dd 0BB1A2AE2h
- dw 0A4F9h
- dw 011CFh
- db 08Fh, 020h, 000h, 080h, 05Fh, 02Ch, 0D0h, 064h
- ; IActiveScriptParse Interface
- struct IActiveScriptParse
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IActiveScriptParse
- InitNew dd ? ; 00Ch
- AddScriptlet dd ? ; 010h
- ParseScriptText dd ? ; 014h
- ends
- ; GUID {DB01A1E3-A42B-11CF-8F20-00805F2CD064}
- IID_IActiveScriptSite \
- dd 0DB01A1E3h
- dw 0A42Bh
- dw 011CFh
- db 08Fh, 020h, 000h, 080h, 05Fh, 02Ch, 0D0h, 064h
- ; IActiveScriptSite Interface
- struct IActiveScriptSite
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IActiveScriptSite
- GetLCID dd ? ; 00Ch
- GetItemInfo dd ? ; 010h
- GetDocVersionString dd ? ; 014h
- OnScriptTerminate dd ? ; 018h
- OnStateChange dd ? ; 01Ch
- OnScriptError dd ? ; 020h
- OnEnterScript dd ? ; 024h
- OnLeaveScript dd ? ; 028h
- refcount dd ?
- ends
- ; IActiveScriptError Interface
- struct IActiveScriptError
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IActiveScriptError
- GetExceptionInfo dd ? ; 00Ch
- GetSourcePosition dd ? ; 010h
- GetSourceLineText dd ? ; 014h
- ends
- SCRIPTSTATE_CONNECTED = 2
- COINIT_MULTITHREADED = 0
Code (Assembler) : Убрать нумерацию
- ; Инициализировать COM-объект
- invoke CoInitializeEx,NULL,COINIT_MULTITHREADED
- ; Получить CLSID из названия движка
- invoke CLSIDFromProgID,szLang,langID
- ; Создать объект
- invoke CoCreateInstance,langID,\
- NULL,\
- CLSCTX_ALL,IID_IActiveScript,ActiveScriptEngine
- cmp eax,S_OK
- jne loc_exit
- ; Получить интерфейс IActiveScriptParse
- mov eax,[ActiveScriptEngine]
- mov eax,[eax]
- stdcall dword [eax+IActiveScript.QueryInterface],[ActiveScriptEngine],\
- IID_IActiveScriptParse,ActiveScriptParser
- ; Инициализировать парсер
- mov eax,[ActiveScriptParser]
- mov eax,[eax]
- stdcall dword [eax+IActiveScriptParse.InitNew],[ActiveScriptParser]
- ; Настроить собственные обработчики методов
- mov [ActiveScriptSite.QueryInterface],My_QueryInterface
- mov [ActiveScriptSite.AddRef],My_AddRef
- mov [ActiveScriptSite.Release],My_Release
- mov [ActiveScriptSite.GetLCID],My_GetLCID
- mov [ActiveScriptSite.GetItemInfo],My_GetItemInfo
- mov [ActiveScriptSite.GetDocVersionString],My_GetDocVersionString
- mov [ActiveScriptSite.OnScriptTerminate],My_OnScriptTerminate
- mov [ActiveScriptSite.OnStateChange],My_OnStateChange
- mov [ActiveScriptSite.OnScriptError],My_OnScriptError
- mov [ActiveScriptSite.OnEnterScript],My_OnEnterScript
- mov [ActiveScriptSite.OnLeaveScript],My_OnLeaveScript
- ; Заполнить указатель на структуру
- mov [pActiveScriptSite],ActiveScriptSite
- ; Установить точку привязки скрипта
- mov eax,[ActiveScriptEngine]
- mov eax,[eax]
- stdcall dword [eax+IActiveScript.SetScriptSite],[ActiveScriptEngine],\
- pActiveScriptSite
- ; Преобразовать текст скрипта в юникод
- invoke GetProcessHeap
- mov [hHeap],eax
- invoke MultiByteToWideChar,CP_ACP,0,szScript,-1,NULL,0
- mov ebx,eax
- shl eax,1
- invoke HeapAlloc,[hHeap],0,eax
- mov [pMem],eax
- invoke MultiByteToWideChar,CP_ACP,0,szScript,-1,[pMem],ebx
- ; Передать парсеру текст скрипта
- mov eax,[ActiveScriptParser]
- mov eax,[eax]
- stdcall dword [eax+IActiveScriptParse.ParseScriptText],\
- [ActiveScriptParser],\
- [pMem],\
- 0,0,0,0,0,0,0,0
- ; Выполнить скрипт
- mov eax,[ActiveScriptEngine]
- mov eax,[eax]
- stdcall dword [eax+IActiveScript.SetScriptState],\
- [ActiveScriptEngine],\
- SCRIPTSTATE_CONNECTED
- ; Очистить память
- invoke HeapFree,[hHeap],0,[pMem]
- ; Прибраться за собой
- mov eax,[ActiveScriptParser]
- mov eax,[eax]
- stdcall dword [eax+IActiveScriptParse.Release],[ActiveScriptParser]
- mov eax,[ActiveScriptEngine]
- mov eax,[eax]
- stdcall dword [eax+IActiveScript.Close],[ActiveScriptEngine]
- mov eax,[ActiveScriptEngine]
- mov eax,[eax]
- stdcall dword [eax+IActiveScript.Release],[ActiveScriptEngine]
- loc_exit:
- ; Удалить объект
- invoke CoUninitialize
Теперь что касается методов интерфейса IActiveScriptSite. Как можно понять из названий, большинство из них соответствуют определенному этапу выполнения скрипта: запуск, остановка, изменение состояния, возникновение ошибки и т.п. Вы можете добавить в них собственные обработчики событий, но можно просто возвращать ответ-пустышку. А вот методы интерфейса IUnknown обязательны к реализации.
Code (Assembler) : Убрать нумерацию
- ;----------------------------------------------------------------------------
- ; Обработчик метода QueryInterface
- ;----------------------------------------------------------------------------
- proc My_QueryInterface pthis:DWORD, iid:DWORD, ppvObject:DWORD
- pusha
- mov eax,[ppvObject]
- cmp eax,0
- jne @f
- ; E_FAIL
- mov eax,0x80004005
- jmp .loc_ret
- @@:
- ; Это интерфейс IActiveScriptSite?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_IActiveScriptSite
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; Это интерфейс IUnknown?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_IUnknown
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; E_NOINTERFACE
- mov eax,0x80004002
- jmp .loc_ret
- .loc_call:
- mov eax,[pthis]
- ; Установить интерфейс
- mov ecx,[ppvObject]
- mov [ecx],eax
- mov ecx,[eax]
- stdcall dword [ecx+IActiveScriptSite.AddRef],eax
- .loc_ok:
- ; S_OK
- xor eax,eax
- .loc_ret:
- mov [esp+28],eax
- popa
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода AddRef
- ;----------------------------------------------------------------------------
- proc My_AddRef pthis:DWORD
- mov eax,[pthis]
- inc [eax+IActiveScriptSite.refcount]
- mov eax,[eax+IActiveScriptSite.refcount]
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода Release
- ;----------------------------------------------------------------------------
- proc My_Release pthis:DWORD
- push ecx
- mov eax,[pthis]
- mov ecx,[eax+IActiveScriptSite.refcount]
- or ecx,ecx
- jz @f
- dec [eax+IActiveScriptSite.refcount]
- dec ecx
- @@:
- mov eax,ecx
- pop ecx
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода GetItemInfo
- ;----------------------------------------------------------------------------
- proc My_GetItemInfo pthis:DWORD, objectName:DWORD,\
- dwReturnMask:DWORD, objPtr:DWORD, ppti:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода OnScriptError
- ;----------------------------------------------------------------------------
- proc My_OnScriptError pthis:DWORD, scriptError:DWORD
- ; Получить текст строки с ошибкой
- mov eax,[scriptError]
- mov eax,[eax]
- stdcall dword [eax+IActiveScriptError.GetSourceLineText],\
- [scriptError],\
- tmp
- ; Вывести строку с ошибкой
- invoke MessageBox,0,[tmp],0,MB_ICONERROR
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода GetLCID
- ;----------------------------------------------------------------------------
- proc My_GetLCID pthis:DWORD, plcid:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода GetDocVersionString
- ;----------------------------------------------------------------------------
- proc My_GetDocVersionString pthis:DWORD, version:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода OnScriptTerminate
- ;----------------------------------------------------------------------------
- proc My_OnScriptTerminate pthis:DWORD, pvr:DWORD, pei:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода OnStateChange
- ;----------------------------------------------------------------------------
- proc My_OnStateChange pthis:DWORD, state:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода OnEnterScript
- ;----------------------------------------------------------------------------
- proc My_OnEnterScript pthis:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ; Обработчик метода OnLeaveScript
- ;----------------------------------------------------------------------------
- proc My_OnLeaveScript pthis:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
В приложении примеры программ с исходными текстами, одна из которых выводит список установленных в системе скриптовых движков, а вторая запускает на выполнение скрипт JScript из памяти.
Просмотров: 704 | Комментариев: 4
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(05.03.2024 в 14:50):
Ничего удивительного, малвара очень активно использует такие приколы со скриптами.
Grey
(05.03.2024 в 14:49):
Прикольно, заменил на XML, каспер (или бранмауэр) сразу убивает исполняемый файл.
ManHunter
(05.03.2024 в 14:10):
szLang = значение "Program ID" из программы enum_engines.exe для соответствующего языка.
Grey
(05.03.2024 в 13:41):
Спасибо, интересно. Прости за тупой вопрос, на сайте MS не смог найти: если в CLSIDFromProgID захочется скормить не JScript а XML или vbs какие заклинания нужно писать для szLang и langID?
Добавить комментарий
Заполните форму для добавления комментария