Instrumenting Binary Applications with VBScript and Deviare

July 10th, 2012 | Posted by Sebastian Wain in Deviare | VBScript

The VBScript script below shows how to intercept Win32 registry APIs such as RegOpenKey and RegQueryValue using the Deviare Interception Engine. Windows Internals’ Process Monitor, the tool most often used to monitor registry operations, cannot be customized. There is a large VBScript community that will benefit from adding intercepting options to scripts. Registry interception can help administrators to pinpoint daily IT issues without being experts on Windows internals. Deviare handles all the complexities related to instrumenting binary applications.

VBScript has been part of Microsoft Windows since 1998. It was initially aimed at web developers. It has since been used by a much wider audience. For example, OutlookSpy embeds a VBScript interpreter as a scripting language and to improve the debugging of Outlook add-ons.

Embedding a VBScript interpreter is a quick way to extend any application. Although PowerShell is gaining adepts and leaving VBScript behind, since VBScript is already installed on Microsoft Windows and is much simpler, it continues to be a good option. PowerShell’s learning curve is also harder.

Note

The Deviare interception engine works both in STA and MTA models. The best and really fast performance is achieved under the MTA model. Like every module running on an STA model, Deviare messages competes with the application messages in a single thread and have a penalty in the performance.

Code

This code can also be downloaded from github.

regmon.vbs

Rem regmon.vbs
Dim functions(56)

functions(0) = "advapi32.dll!RegCloseKey"
functions(1) = "advapi32.dll!RegConnectRegistryW"
functions(2) = "advapi32.dll!RegCopyTreeW"
functions(3) = "advapi32.dll!RegCreateKeyW"
functions(4) = "advapi32.dll!RegCreateKeyExW"
functions(5) = "advapi32.dll!RegCreateKeyTransactedW"
functions(6) = "advapi32.dll!RegDeleteKeyW"
functions(7) = "advapi32.dll!RegDeleteKeyExW"
functions(8) = "advapi32.dll!RegDeleteKeyTransactedW"
functions(9) = "advapi32.dll!RegDeleteKeyValueW"
functions(10) = "advapi32.dll!RegDeleteTreeW"
functions(11) = "advapi32.dll!RegDeleteValueW"
functions(12) = "advapi32.dll!RegDisablePredefinedCacheW"
functions(13) = "advapi32.dll!RegDisablePredefinedCacheExW"
functions(14) = "advapi32.dll!RegDisableReflectionKeyW"
functions(15) = "advapi32.dll!RegEnableReflectionKeyW"
functions(16) = "advapi32.dll!RegEnumKeyW"
functions(17) = "advapi32.dll!RegEnumKeyExW"
functions(18) = "advapi32.dll!RegEnumValueW"
functions(19) = "advapi32.dll!RegFlushKeyW"
functions(20) = "advapi32.dll!RegGetValueW"
functions(21) = "advapi32.dll!RegLoadAppKeyW"
functions(22) = "advapi32.dll!RegLoadKeyW"
functions(23) = "advapi32.dll!RegLoadMUIStringW"
functions(24) = "advapi32.dll!RegNotifyChangeKeyValue"
functions(25) = "advapi32.dll!RegOpenCurrentUserW"
functions(26) = "advapi32.dll!RegOpenKeyW"
functions(27) = "advapi32.dll!RegOpenKeyExW"
functions(28) = "advapi32.dll!RegOpenKeyTransactedW"
functions(29) = "advapi32.dll!RegOpenUserClassesRootW"
functions(30) = "advapi32.dll!RegOverridePredefKeyW"
functions(31) = "advapi32.dll!RegQueryInfoKeyW"
functions(32) = "advapi32.dll!RegQueryMultipleValuesW"
functions(33) = "advapi32.dll!RegQueryReflectionKeyW"
functions(34) = "advapi32.dll!RegQueryValueW"
functions(35) = "advapi32.dll!RegQueryValueExW"
functions(36) = "advapi32.dll!RegReplaceKeyW"
functions(37) = "advapi32.dll!RegRestoreKeyW"
functions(38) = "advapi32.dll!RegSaveKeyW"
functions(39) = "advapi32.dll!RegSaveKeyExW"
functions(40) = "advapi32.dll!RegSetKeyValueW"
functions(41) = "advapi32.dll!RegSetValueW"
functions(42) = "advapi32.dll!RegSetValueExW"
functions(43) = "advapi32.dll!RegUnLoadKeyW"
functions(44) = "kernel32.dll!GetPrivateProfileIntW"
functions(45) = "kernel32.dll!GetPrivateProfileSectionW"
functions(46) = "kernel32.dll!GetPrivateProfileSectionNamesW"
functions(47) = "kernel32.dll!GetPrivateProfileStringW"
functions(48) = "kernel32.dll!GetPrivateProfileStructW"
functions(49) = "kernel32.dll!GetProfileIntW"
functions(50) = "kernel32.dll!GetProfileSectionW"
functions(51) = "kernel32.dll!GetProfileStringW"
functions(52) = "kernel32.dll!WritePrivateProfileSectionW"
functions(53) = "kernel32.dll!WritePrivateProfileStringW"
functions(54) = "kernel32.dll!WritePrivateProfileStructW"
functions(55) = "kernel32.dll!WriteProfileSectionW"
functions(56) = "kernel32.dll!WriteProfileStringW"

Dim spyMgr

Set spyMgr = WScript.CreateObject("DeviareCOM.NktSpyMgr", "spyMgr_")

spyMgr.Initialize

WScript.Echo "NkySpyMgr Initialized"

Dim hooks
Set hooks = CreateObject("Scripting.Dictionary")
Dim func

Dim hook
For Each func in functions
	Set hook = spyMgr.CreateHook(func, 33)
	'hook.Hook True
	hooks.add func, hook
Next

WScript.Echo "Hooks Created"

Dim processes, process

Set processes = spyMgr.Processes()
Set process = processes.First()

Do While Not process Is Nothing
If LCase(process.Name) = "outlook.exe" And process.PlatformBits = 32 Then
'If LCase(process.Name) = "iexplore.exe" And process.PlatformBits = 32 Then
		For Each key in hooks
			'WScript.Echo key
			WScript.Echo "Before hooking " & key & " on iexplore.exe"
			'MsgBox TypeName(hooks.Item(key))
			hooks.Item(key).Attach process, False
			WScript.Echo "After hooking " & key & " on iexplore.exe"
		Next
	End If
	Set process = processes.Next()
Loop

WScript.Echo "Hooks attached to processes"

For Each key in hooks
	hooks.Item(key).Hook True
Next

WScript.Echo "Hooks in True"

Sub spyMgr_OnFunctionCalled(ByVal hook, ByVal proc, ByVal callInfo)
	Dim params, param, log

	log = hook.FunctionName
	Set params = callInfo.Params()
	If Not params Is Nothing Then
		log = log & " #parameters = " & params.Count & " param names: "
		Set param = params.First()
		Do While Not param is Nothing
			log = log & param.Name & " "
			Set param = params.Next()
		Loop

	End If

	WScript.Echo log
End Sub

Dim wshShell
Set wshShell = WScript.CreateObject("WScript.Shell")
wshShell.Popup "Press the OK button to exit this script"

Related Services

  1. Reverse Engineering
  2. Interception and Filter Drivers Services
  3. Application Virtualization and Packaging

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

  • http://trevorsullivan.net/ Trevor Sullivan

    Why can’t the
    DeviareCOM.NktSpyMgr object be created using PowerShell?

    $SpyMgr = New-Object -ComObject DeviareCOM.NktSpyMgr;

    • http://blog.databigbang.com Sebastian Wain

      Currently the issue with PowerShell is that events are fired asynchronously there is a specific event queue that handles that. When the OnFunctionCalled event is fired the params don’t exist anymore. We can change the implementation to block the processing but it will impact on the performance of the hooked application. This issue delayed the PowerShell article. Do you know of any workaround? because it is the way PowerShell works.