├── Monitor ├── logger.h ├── monitor.cpp ├── monitor.h └── MinHook.h ├── README.md └── injector.cpp /Monitor/logger.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jayo78/win-api-monitor/HEAD/Monitor/logger.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | This is a basic API monitoring program for running windows executables and intercepting their calls to the WinAPI. It uses minhook as an inline hooking engine and DLL injection as the process injection technique. 4 | 5 | #### injector 6 | 7 | The injector uses DLL injection and may be flagged by AV as it uses common API calls found in malware injection. 8 | 9 | - Creates target process as suspended 10 | - Writes to process space with VirtualAlloc and WriteProcessMemory 11 | - Executes remote thread to load the monitor DLL and install hooks 12 | - Resumes target thread after hooks have been installed 13 | 14 | #### monitor 15 | 16 | The monitor, once injected, installs hooks that report intercepted calls made by the injected process. **Compilation:** use `/LD` (MSVC compiler) to create as a DLL. The monitor depends on [minhook](https://github.com/TsudaKageyu/minhook) so be sure to link that library and use the minhook.h header. 17 | 18 | #### todo 19 | - add native (Nt/Zw) hooks 20 | 21 | -------------------------------------------------------------------------------- /Monitor/monitor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "MinHook.h" 4 | #include "monitor.h" 5 | #include "logger.h" 6 | 7 | #pragma comment(lib, "libMinHook-x86mt.lib") 8 | 9 | 10 | // Hooks that will be installed (see monitor.h) 11 | //============================================ 12 | 13 | HOOK_INFO hooks[]= { 14 | { 15 | L"ws2_32", 16 | "connect", 17 | &ProxyConnect, 18 | &fpConnect 19 | }, 20 | { 21 | L"kernelbase", 22 | "CreateProcessInternalW", 23 | &ProxyCreateProcessInternalW, 24 | &fpCreateProcessInternalW 25 | }, 26 | { 27 | L"kernel32", 28 | "LoadLibraryExW", 29 | &ProxyLoadLibraryExW, 30 | &fpLoadLibraryExW 31 | }, 32 | { 33 | L"kernel32", 34 | "LoadLibraryW", 35 | &ProxyLoadLibraryW, 36 | &fpLoadLibraryW 37 | }, 38 | { 39 | L"kernel32", 40 | "LoadLibraryA", 41 | &ProxyLoadLibraryA, 42 | &fpLoadLibraryA 43 | }, 44 | { 45 | L"kernel32", 46 | "GetProcAddress", 47 | &ProxyGetProcAddress, 48 | &fpGetProcAddress 49 | } 50 | }; 51 | 52 | 53 | // Hook installation functions 54 | //============================================ 55 | 56 | __forceinline BOOL install_hook(HOOK_INFO *pHookInfo) 57 | { 58 | if (MH_CreateHookApi(pHookInfo->lib, pHookInfo->target, pHookInfo->proxy, (LPVOID *)(pHookInfo->fp)) != MH_OK) 59 | return FALSE; 60 | 61 | return TRUE; 62 | } 63 | 64 | VOID install_all() 65 | { 66 | int numElts= sizeof(hooks)/sizeof(hooks[0]); 67 | 68 | for (int i= 0; i < numElts; i++) 69 | { 70 | if (install_hook(&hooks[i])) 71 | logger << L"[+] Installed hook in: " << hooks[i].target << "\n"; 72 | } 73 | } 74 | 75 | 76 | // DLL entry 77 | //============================================ 78 | 79 | BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved) 80 | { 81 | switch (reason) 82 | { 83 | case DLL_PROCESS_ATTACH: 84 | logger << L"[+] Installing hooks...\n"; 85 | 86 | MH_Initialize(); 87 | install_all(); 88 | MH_EnableHook(MH_ALL_HOOKS); 89 | 90 | logger << L"[+] Hooks installed, Resuming main thread..." << std::endl; 91 | break; 92 | } 93 | 94 | return TRUE; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /injector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma comment(lib, "shell32.lib") 6 | 7 | 8 | // Inject a DLL with CreateRemoteThread 9 | //==================================================== 10 | 11 | void inject_DLL(TCHAR *dllPath, HANDLE process) 12 | { 13 | LPVOID lpBaseAddress; 14 | HANDLE hRemoteThread; 15 | HMODULE kernel32; 16 | FARPROC loadlibrary; 17 | SIZE_T pathLen; 18 | 19 | lpBaseAddress= NULL; 20 | hRemoteThread= NULL; 21 | loadlibrary= NULL; 22 | kernel32= NULL; 23 | pathLen= _tcslen(dllPath) * sizeof(TCHAR); 24 | 25 | kernel32= GetModuleHandle(_T("kernel32.dll")); 26 | loadlibrary= GetProcAddress(kernel32, _T("LoadLibraryA")); 27 | 28 | lpBaseAddress= VirtualAllocEx(process, NULL, pathLen, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 29 | if (lpBaseAddress == NULL) 30 | std::cout << "VirtualAllocEx failed: " << GetLastError() << std::endl; 31 | 32 | if (!WriteProcessMemory(process, lpBaseAddress, dllPath, pathLen, NULL)) 33 | std::cout << "WriteProcessMemory failed: " << GetLastError() << std::endl; 34 | 35 | hRemoteThread= CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)(VOID *)loadlibrary, lpBaseAddress, NULL, 0); 36 | if (hRemoteThread == NULL) 37 | std::cout << "CreateRemoteThread failed: " << GetLastError() << std::endl; 38 | 39 | WaitForSingleObject(hRemoteThread, INFINITE); 40 | CloseHandle(hRemoteThread); 41 | } 42 | 43 | 44 | // Open a log generated by the monitor 45 | //==================================================== 46 | 47 | void open_log(TCHAR *exePath) 48 | { 49 | TCHAR logPath[MAX_PATH + 4]= {0}; 50 | 51 | exePath[_tcslen(exePath) - 4]= '\0'; 52 | _tcscat(logPath, exePath); 53 | _tcscat(logPath, "_log.txt"); 54 | 55 | ShellExecute(0, 0, logPath, 0, 0 , SW_SHOW ); 56 | } 57 | 58 | 59 | // Entry: Createprocess (suspended) > inject > resume 60 | //==================================================== 61 | 62 | int main(int argc, TCHAR *argv[]) 63 | { 64 | STARTUPINFO si; 65 | PROCESS_INFORMATION pi; 66 | TCHAR *targetExe; 67 | TCHAR *dllName; 68 | TCHAR dllPath[MAX_PATH]; 69 | SIZE_T pathLen; 70 | HANDLE serverThread; 71 | 72 | if (argc < 3) 73 | { 74 | std::cout << "Not enough arguments\n" << "Usage: injector.exe \n"; 75 | return 1; 76 | } 77 | 78 | targetExe= _T(argv[1]); 79 | dllName= _T(argv[2]); 80 | GetFullPathName(dllName, MAX_PATH, dllPath, NULL); 81 | 82 | ZeroMemory( &si, sizeof(si)); 83 | ZeroMemory( &pi, sizeof(pi)); 84 | si.cb = sizeof(si); 85 | 86 | if(!CreateProcess(NULL, targetExe, NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) 87 | { 88 | std::cout << "CreateProcess failed: " << GetLastError() << std::endl; 89 | return 1; 90 | } 91 | 92 | inject_DLL(dllPath, pi.hProcess); 93 | 94 | ResumeThread(pi.hThread); 95 | WaitForSingleObject(pi.hProcess, INFINITE); 96 | 97 | CloseHandle(pi.hProcess); 98 | CloseHandle(pi.hThread); 99 | 100 | open_log(targetExe); 101 | 102 | return 0; 103 | } -------------------------------------------------------------------------------- /Monitor/monitor.h: -------------------------------------------------------------------------------- 1 | #include "logger.h" 2 | 3 | #pragma once 4 | 5 | 6 | // standard information for every hook 7 | struct HOOK_INFO { 8 | LPCWSTR lib; 9 | LPCSTR target; 10 | LPVOID proxy; 11 | LPVOID fp; 12 | }; 13 | 14 | // logger object - exposes a stream to report to the IPC channel 15 | Logger logger; 16 | 17 | 18 | // Proxy Function Definitions 19 | //============================================ 20 | 21 | typedef int (WINAPI *CONNECT)(SOCKET, const SOCKADDR*, int); 22 | typedef int (WINAPI *CREATEPROCESSINTERNALW)(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION, PHANDLE); 23 | typedef int (WINAPI *LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); 24 | typedef int (WINAPI *LOADLIBRARYW)(LPCWSTR); 25 | typedef int (WINAPI *LOADLIBRARYA)(LPCSTR); 26 | typedef FARPROC (WINAPI *GETPROCADDRESS)(HMODULE, LPCSTR); 27 | 28 | 29 | // Trampoline Function Declarations 30 | //============================================ 31 | 32 | GETPROCADDRESS fpGetProcAddress= NULL; 33 | LOADLIBRARYA fpLoadLibraryA= NULL; 34 | LOADLIBRARYW fpLoadLibraryW= NULL; 35 | LOADLIBRARYEXW fpLoadLibraryExW= NULL; 36 | CONNECT fpConnect= NULL; 37 | CREATEPROCESSINTERNALW fpCreateProcessInternalW= NULL; 38 | 39 | 40 | // Proxy Functions 41 | //============================================ 42 | 43 | int WINAPI ProxyConnect(SOCKET s, const sockaddr* name, int namelen) 44 | { 45 | /* 46 | ** dynamically loading the WSAAddressToStringW function from the ws2_32 dll in order to 47 | ** resolve a standard IP dot notation from the sockaddr struct. uses GetModuleHandle so the 48 | ** ws2_32 dll isn't loaded if the target process isn't using it (no need to hook in that case) 49 | */ 50 | typedef int (WINAPI *WSAADDRESSTOSTRINGW)(LPSOCKADDR, DWORD, LPDWORD, LPWSTR, LPDWORD); 51 | HMODULE hModule= GetModuleHandle("ws2_32"); 52 | WSAADDRESSTOSTRINGW WSAAddressToStringW= (WSAADDRESSTOSTRINGW) GetProcAddress(hModule, "WSAAddressToStringW"); 53 | 54 | wchar_t addr[32]; 55 | DWORD sz= 32; 56 | WSAAddressToStringW((SOCKADDR *)name, namelen, NULL, addr, &sz); 57 | 58 | logger << L"[HOOK] Intercepted call to connect:\n" << L"- IP Address: " << addr << std::endl; 59 | return fpConnect(s, name, namelen); 60 | } 61 | 62 | int WINAPI ProxyCreateProcessInternalW 63 | (HANDLE hToken, 64 | LPCWSTR lpApplicationName, 65 | LPWSTR lpCommandLine, 66 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 67 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 68 | BOOL bInheritHandles, 69 | DWORD dwCreationFlags, 70 | LPVOID lpEnvironment, 71 | LPCWSTR lpCurrentDirectory, 72 | LPSTARTUPINFOW lpStartupInfo, 73 | LPPROCESS_INFORMATION lpProcessInformation, 74 | PHANDLE hNewToken) 75 | { 76 | logger << L"[HOOK] Intercepted call to CreateProcessInternalW:\n" << L"- Application Name: " << lpCommandLine << std::endl; 77 | return fpCreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); 78 | } 79 | 80 | int WINAPI ProxyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) 81 | { 82 | logger << L"[HOOK] Intercepted call to LoadLibraryExW:\n" << L"- Library Name: " << lpLibFileName << std::endl; 83 | return fpLoadLibraryExW(lpLibFileName, hFile, dwFlags); 84 | } 85 | 86 | int WINAPI ProxyLoadLibraryW(LPCWSTR lpLibFileName) 87 | { 88 | logger << L"[HOOK] Intercepted call to LoadLibraryW:\n" << L"- Library Name: " << lpLibFileName << std::endl; 89 | return fpLoadLibraryW(lpLibFileName); 90 | } 91 | 92 | int WINAPI ProxyLoadLibraryA(LPCSTR lpLibFileName) 93 | { 94 | wchar_t wLibName[128]; 95 | MultiByteToWideChar(CP_THREAD_ACP, (DWORD)0, lpLibFileName, -1, wLibName, 128); 96 | logger << L"[HOOK] Intercepted call to LoadLibraryA:\n" << L"- Library Name: " << wLibName << std::endl; 97 | return fpLoadLibraryA(lpLibFileName); 98 | } 99 | 100 | FARPROC WINAPI ProxyGetProcAddress(HMODULE hModule, LPCSTR lpProcName) 101 | { 102 | wchar_t wProcName[128]; 103 | MultiByteToWideChar(CP_THREAD_ACP, (DWORD)0, lpProcName, -1, wProcName, 128); 104 | logger << L"[HOOK] Intercepted call to GetProcAddress:\n" << L"- Function Name: " << wProcName << std::endl; 105 | return fpGetProcAddress(hModule, lpProcName); 106 | } 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /Monitor/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | --------------------------------------------------------------------------------