686 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			686 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | //  Detours Test Program (trclnk.cpp of trclnk.dll)
 | ||
|  | //
 | ||
|  | //  Microsoft Research Detours Package
 | ||
|  | //
 | ||
|  | //  Copyright (c) Microsoft Corporation.  All rights reserved.
 | ||
|  | //
 | ||
|  | #define _WIN32_WINNT        0x0400
 | ||
|  | #define WIN32
 | ||
|  | #define NT
 | ||
|  | 
 | ||
|  | #define DBG_TRACE   0
 | ||
|  | 
 | ||
|  | #include <windows.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include "detours.h"
 | ||
|  | #include "syelog.h"
 | ||
|  | 
 | ||
|  | #define PULONG_PTR          PVOID
 | ||
|  | #define PLONG_PTR           PVOID
 | ||
|  | #define ULONG_PTR           PVOID
 | ||
|  | #define ENUMRESNAMEPROCA    PVOID
 | ||
|  | #define ENUMRESNAMEPROCW    PVOID
 | ||
|  | #define ENUMRESLANGPROCA    PVOID
 | ||
|  | #define ENUMRESLANGPROCW    PVOID
 | ||
|  | #define ENUMRESTYPEPROCA    PVOID
 | ||
|  | #define ENUMRESTYPEPROCW    PVOID
 | ||
|  | #define STGOPTIONS          PVOID
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | #pragma warning(disable:4127)   // Many of our asserts are constants.
 | ||
|  | 
 | ||
|  | #define ASSERT_ALWAYS(x)   \
 | ||
|  |     do {                                                        \ | ||
|  |     if (!(x)) {                                                 \ | ||
|  |             AssertMessage(#x, __FILE__, __LINE__);              \ | ||
|  |             DebugBreak();                                       \ | ||
|  |     }                                                           \ | ||
|  |     } while (0) | ||
|  | 
 | ||
|  | #ifndef NDEBUG
 | ||
|  | #define ASSERT(x)           ASSERT_ALWAYS(x)
 | ||
|  | #else
 | ||
|  | #define ASSERT(x)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define UNUSED(c)    (c) = (c)
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | static HMODULE s_hInst = NULL; | ||
|  | static WCHAR s_wzDllPath[MAX_PATH]; | ||
|  | 
 | ||
|  | BOOL ProcessEnumerate(); | ||
|  | BOOL InstanceEnumerate(HINSTANCE hInst); | ||
|  | BOOL ImportEnumerate(HINSTANCE hInst); | ||
|  | 
 | ||
|  | VOID _PrintEnter(const CHAR *psz, ...); | ||
|  | VOID _PrintExit(const CHAR *psz, ...); | ||
|  | VOID _Print(const CHAR *psz, ...); | ||
|  | VOID _VPrint(PCSTR msg, va_list args, PCHAR pszBuf, LONG cbBuf); | ||
|  | 
 | ||
|  | VOID AssertMessage(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine); | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | // Trampolines
 | ||
|  | //
 | ||
|  | extern "C" { | ||
|  |     //  Trampolines for SYELOG library.
 | ||
|  |     //
 | ||
|  |     HANDLE (WINAPI * | ||
|  |             Real_CreateFileW)(LPCWSTR a0, DWORD a1, DWORD a2, | ||
|  |                               LPSECURITY_ATTRIBUTES a3, DWORD a4, DWORD a5, | ||
|  |                               HANDLE a6) | ||
|  |         = CreateFileW; | ||
|  | 
 | ||
|  |     BOOL (WINAPI * | ||
|  |           Real_WriteFile)(HANDLE hFile, | ||
|  |                           LPCVOID lpBuffer, | ||
|  |                           DWORD nNumberOfBytesToWrite, | ||
|  |                           LPDWORD lpNumberOfBytesWritten, | ||
|  |                           LPOVERLAPPED lpOverlapped) | ||
|  |         = WriteFile; | ||
|  |     BOOL (WINAPI * | ||
|  |           Real_FlushFileBuffers)(HANDLE hFile) | ||
|  |         = FlushFileBuffers; | ||
|  |     BOOL (WINAPI * | ||
|  |           Real_CloseHandle)(HANDLE hObject) | ||
|  |         = CloseHandle; | ||
|  | 
 | ||
|  |     BOOL (WINAPI * | ||
|  |           Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut) | ||
|  |         = WaitNamedPipeW; | ||
|  |     BOOL (WINAPI * | ||
|  |           Real_SetNamedPipeHandleState)(HANDLE hNamedPipe, | ||
|  |                                         LPDWORD lpMode, | ||
|  |                                         LPDWORD lpMaxCollectionCount, | ||
|  |                                         LPDWORD lpCollectDataTimeout) | ||
|  |         = SetNamedPipeHandleState; | ||
|  | 
 | ||
|  |     DWORD (WINAPI * | ||
|  |            Real_GetCurrentProcessId)(VOID) | ||
|  |         = GetCurrentProcessId; | ||
|  |     VOID (WINAPI * | ||
|  |           Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime) | ||
|  |         = GetSystemTimeAsFileTime; | ||
|  | 
 | ||
|  |     VOID (WINAPI * | ||
|  |           Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = InitializeCriticalSection; | ||
|  |     VOID (WINAPI * | ||
|  |           Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = EnterCriticalSection; | ||
|  |     VOID (WINAPI * | ||
|  |           Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection) | ||
|  |         = LeaveCriticalSection; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL (WINAPI * | ||
|  |       Real_FreeLibrary)(HMODULE a0) | ||
|  |     = FreeLibrary; | ||
|  | 
 | ||
|  | DWORD (WINAPI * | ||
|  |        Real_GetModuleFileNameW)(HMODULE a0, | ||
|  |                                 LPWSTR a1, | ||
|  |                                 DWORD a2) | ||
|  |     = GetModuleFileNameW; | ||
|  | 
 | ||
|  | HMODULE (WINAPI * | ||
|  |          Real_GetModuleHandleW)(LPCWSTR a0) | ||
|  |     = GetModuleHandleW; | ||
|  | 
 | ||
|  | FARPROC (WINAPI * | ||
|  |          Real_GetProcAddress)(HMODULE a0, | ||
|  |                               LPCSTR a1) | ||
|  |     = GetProcAddress; | ||
|  | 
 | ||
|  | HMODULE (WINAPI * | ||
|  |          Real_LoadLibraryExW)(LPCWSTR a0, | ||
|  |                               HANDLE a1, | ||
|  |                               DWORD a2) | ||
|  |     = LoadLibraryExW; | ||
|  | 
 | ||
|  | HMODULE (WINAPI * | ||
|  |          Real_LoadLibraryW)(LPCWSTR a0) | ||
|  |     = LoadLibraryW; | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | BOOL WINAPI Mine_FreeLibrary(HMODULE a0) | ||
|  | { | ||
|  |     (void)a0; | ||
|  | 
 | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | DWORD WINAPI Mine_GetModuleFileNameW(HMODULE a0, | ||
|  |                                      LPWSTR a1, | ||
|  |                                      DWORD a2) | ||
|  | { | ||
|  |     return Real_GetModuleFileNameW(a0, a1, a2); | ||
|  | } | ||
|  | 
 | ||
|  | HMODULE WINAPI Mine_GetModuleHandleW(LPCWSTR a0) | ||
|  | { | ||
|  |     return Real_GetModuleHandleW(a0); | ||
|  | } | ||
|  | 
 | ||
|  | FARPROC WINAPI Mine_GetProcAddress(HMODULE a0, | ||
|  |                                    LPCSTR a1) | ||
|  | { | ||
|  |     _PrintEnter("GetProcAddress(%p,%hs)\n", a0, a1); | ||
|  | 
 | ||
|  |     FARPROC rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_GetProcAddress(a0, a1); | ||
|  |     } __finally { | ||
|  |         _PrintExit("GetProcAddress(,) -> %p\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | HMODULE WINAPI Mine_LoadLibraryExW(LPCWSTR a0, | ||
|  |                                    HANDLE a1, | ||
|  |                                    DWORD a2) | ||
|  | { | ||
|  |     _PrintEnter("LoadLibraryExW(%ls,%p,%x)\n", a0, a1, a2); | ||
|  | 
 | ||
|  |     HMODULE rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_LoadLibraryExW(a0, a1, a2); | ||
|  |     } __finally { | ||
|  |         _PrintExit("LoadLibraryExW(,,) -> %p\n", rv); | ||
|  |         if (rv) { | ||
|  |             InstanceEnumerate(rv); | ||
|  |             ImportEnumerate(rv); | ||
|  |         } | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | HMODULE WINAPI Mine_LoadLibraryW(LPCWSTR a0) | ||
|  | { | ||
|  |     _PrintEnter("LoadLibraryW(%ls)\n", a0); | ||
|  | 
 | ||
|  |     HMODULE rv = 0; | ||
|  |     __try { | ||
|  |         rv = Real_LoadLibraryW(a0); | ||
|  |     } __finally { | ||
|  |         _PrintExit("LoadLibraryW() -> %p\n", rv); | ||
|  |     }; | ||
|  |     return rv; | ||
|  | } | ||
|  | 
 | ||
|  | /////////////////////////////////////////////////////////////
 | ||
|  | // AttachDetours
 | ||
|  | //
 | ||
|  | PCHAR DetRealName(PCHAR psz) | ||
|  | { | ||
|  |     PCHAR pszBeg = psz; | ||
|  |     // Move to end of name.
 | ||
|  |     while (*psz) { | ||
|  |         psz++; | ||
|  |     } | ||
|  |     // Move back through A-Za-z0-9 names.
 | ||
|  |     while (psz > pszBeg && | ||
|  |            ((psz[-1] >= 'A' && psz[-1] <= 'Z') || | ||
|  |             (psz[-1] >= 'a' && psz[-1] <= 'z') || | ||
|  |             (psz[-1] >= '0' && psz[-1] <= '9'))) { | ||
|  |         psz--; | ||
|  |     } | ||
|  |     return psz; | ||
|  | } | ||
|  | 
 | ||
|  | VOID DetAttach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) | ||
|  | { | ||
|  |     LONG l = DetourAttach(ppbReal, pbMine); | ||
|  |     if (l != 0) { | ||
|  |         Syelog(SYELOG_SEVERITY_NOTICE, | ||
|  |                "Attach failed: `%s': error %d\n", DetRealName(psz), l); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) | ||
|  | { | ||
|  |     LONG l = DetourDetach(ppbReal, pbMine); | ||
|  |     if (l != 0) { | ||
|  |         Syelog(SYELOG_SEVERITY_NOTICE, | ||
|  |                "Detach failed: `%s': error %d\n", DetRealName(psz), l); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | #define ATTACH(x)       DetAttach(&(PVOID&)Real_##x,Mine_##x,#x)
 | ||
|  | #define DETACH(x)       DetDetach(&(PVOID&)Real_##x,Mine_##x,#x)
 | ||
|  | 
 | ||
|  | LONG AttachDetours(VOID) | ||
|  | { | ||
|  |     DetourTransactionBegin(); | ||
|  |     DetourUpdateThread(GetCurrentThread()); | ||
|  | 
 | ||
|  |     ATTACH(FreeLibrary); | ||
|  |     ATTACH(GetModuleHandleW); | ||
|  |     ATTACH(GetProcAddress); | ||
|  |     ATTACH(LoadLibraryExW); | ||
|  |     ATTACH(LoadLibraryW); | ||
|  | 
 | ||
|  |     return DetourTransactionCommit(); | ||
|  | } | ||
|  | 
 | ||
|  | LONG DetachDetours(VOID) | ||
|  | { | ||
|  |     DetourTransactionBegin(); | ||
|  |     DetourUpdateThread(GetCurrentThread()); | ||
|  | 
 | ||
|  |     DETACH(FreeLibrary); | ||
|  |     DETACH(GetModuleHandleW); | ||
|  |     DETACH(GetProcAddress); | ||
|  |     DETACH(LoadLibraryExW); | ||
|  |     DETACH(LoadLibraryW); | ||
|  | 
 | ||
|  |     return DetourTransactionCommit(); | ||
|  | } | ||
|  | 
 | ||
|  | ////////////////////////////////////////////////////////////// Logging System.
 | ||
|  | //
 | ||
|  | static BOOL s_bLog = 1; | ||
|  | static LONG s_nTlsIndent = -1; | ||
|  | static LONG s_nTlsThread = -1; | ||
|  | static LONG s_nThreadCnt = 0; | ||
|  | 
 | ||
|  | VOID _PrintEnter(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent); | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)(LONG_PTR)(nIndent + 1)); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID _PrintExit(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent) - 1; | ||
|  |         ASSERT(nIndent >= 0); | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)(LONG_PTR)nIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID _Print(const CHAR *psz, ...) | ||
|  | { | ||
|  |     DWORD dwErr = GetLastError(); | ||
|  | 
 | ||
|  |     LONG nIndent = 0; | ||
|  |     LONG nThread = 0; | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         nIndent = (LONG)(LONG_PTR)TlsGetValue(s_nTlsIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         nThread = (LONG)(LONG_PTR)TlsGetValue(s_nTlsThread); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (s_bLog && psz) { | ||
|  |         CHAR szBuf[1024]; | ||
|  |         PCHAR pszBuf = szBuf; | ||
|  |         PCHAR pszEnd = szBuf + ARRAYSIZE(szBuf) - 1; | ||
|  |         LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); | ||
|  |         *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); | ||
|  |         *pszBuf++ = ' '; | ||
|  |         while (nLen-- > 0) { | ||
|  |             *pszBuf++ = ' '; | ||
|  |         } | ||
|  | 
 | ||
|  |         va_list  args; | ||
|  |         va_start(args, psz); | ||
|  | 
 | ||
|  |         while ((*pszBuf++ = *psz++) != 0 && pszBuf < pszEnd) { | ||
|  |             // Copy characters.
 | ||
|  |         } | ||
|  |         *pszEnd = '\0'; | ||
|  |         SyelogV(SYELOG_SEVERITY_INFORMATION, szBuf, args); | ||
|  | 
 | ||
|  |         va_end(args); | ||
|  |     } | ||
|  |     SetLastError(dwErr); | ||
|  | } | ||
|  | 
 | ||
|  | VOID AssertMessage(CONST PCHAR pszMsg, CONST PCHAR pszFile, ULONG nLine) | ||
|  | { | ||
|  |     Syelog(SYELOG_SEVERITY_FATAL, | ||
|  |            "ASSERT(%s) failed in %s, line %d.\n", pszMsg, pszFile, nLine); | ||
|  | } | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | PIMAGE_NT_HEADERS NtHeadersForInstance(HINSTANCE hInst) | ||
|  | { | ||
|  |     PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hInst; | ||
|  |     __try { | ||
|  |         if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { | ||
|  |             SetLastError(ERROR_BAD_EXE_FORMAT); | ||
|  |             return NULL; | ||
|  |         } | ||
|  | 
 | ||
|  |         PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + | ||
|  |                                                           pDosHeader->e_lfanew); | ||
|  |         if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { | ||
|  |             SetLastError(ERROR_INVALID_EXE_SIGNATURE); | ||
|  |             return NULL; | ||
|  |         } | ||
|  |         if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { | ||
|  |             SetLastError(ERROR_EXE_MARKED_INVALID); | ||
|  |             return NULL; | ||
|  |         } | ||
|  |         return pNtHeader; | ||
|  |     } __except(EXCEPTION_EXECUTE_HANDLER) { | ||
|  |     } | ||
|  |     SetLastError(ERROR_EXE_MARKED_INVALID); | ||
|  | 
 | ||
|  |     return NULL; | ||
|  | } | ||
|  | 
 | ||
|  | static inline PBYTE RvaToVa(PBYTE pbBase, DWORD nOffset) | ||
|  | { | ||
|  |     return nOffset ? pbBase + nOffset : NULL; | ||
|  | } | ||
|  | 
 | ||
|  | #if _MSC_VER >= 1900
 | ||
|  | #pragma warning(push)
 | ||
|  | #pragma warning(disable:4456) // declaration hides previous local declaration
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | BOOL ImportEnumerate(HINSTANCE hInst) | ||
|  | { | ||
|  |     PBYTE pbBase = (PBYTE)hInst; | ||
|  |     PIMAGE_NT_HEADERS pNtHeader;                    // Read & Write
 | ||
|  |     PIMAGE_SECTION_HEADER pSectionHeaders; | ||
|  |     DWORD nPeOffset; | ||
|  |     DWORD nSectionsOffset; | ||
|  | 
 | ||
|  |     ////////////////////////////////////////////////////// Process DOS Header.
 | ||
|  |     //
 | ||
|  |     PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbBase; | ||
|  |     if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  |     nPeOffset = pDosHeader->e_lfanew; | ||
|  | 
 | ||
|  |     /////////////////////////////////////////////////////// Process PE Header.
 | ||
|  |     //
 | ||
|  |     pNtHeader = (PIMAGE_NT_HEADERS)RvaToVa(pbBase, nPeOffset); | ||
|  |     if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  |     if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  |     nSectionsOffset = nPeOffset | ||
|  |         + sizeof(pNtHeader->Signature) | ||
|  |         + sizeof(pNtHeader->FileHeader) | ||
|  |         + pNtHeader->FileHeader.SizeOfOptionalHeader; | ||
|  | 
 | ||
|  |     ///////////////////////////////////////////////// Process Section Headers.
 | ||
|  |     //
 | ||
|  |     pSectionHeaders = (PIMAGE_SECTION_HEADER)RvaToVa(pbBase, nSectionsOffset); | ||
|  | 
 | ||
|  |     //////////////////////////////////////////////////////// Get Import Table.
 | ||
|  |     //
 | ||
|  |     DWORD rvaImageDirectory = pNtHeader->OptionalHeader | ||
|  |         .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; | ||
|  |     PIMAGE_IMPORT_DESCRIPTOR iidp | ||
|  |         = (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(pbBase, rvaImageDirectory); | ||
|  | 
 | ||
|  |     if (iidp == NULL) { | ||
|  |         return FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |     DWORD nFiles = 0; | ||
|  |     for (; iidp[nFiles].Characteristics != 0; nFiles++) { | ||
|  |         // Count the files.
 | ||
|  |     } | ||
|  | 
 | ||
|  |     for (DWORD n = 0; n < nFiles; n++, iidp++) { | ||
|  |         DWORD rvaName = iidp->Name; | ||
|  |         PCHAR pszName = (PCHAR)RvaToVa(pbBase, rvaName); | ||
|  | 
 | ||
|  |         DWORD rvaThunk = (DWORD)iidp->OriginalFirstThunk; | ||
|  |         PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk); | ||
|  |         rvaThunk = (DWORD)iidp->FirstThunk; | ||
|  |         PIMAGE_THUNK_DATA pBoundThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk); | ||
|  | 
 | ||
|  |         Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |                "%s [%p %p]\n", pszName, pThunk, pBoundThunk); | ||
|  | 
 | ||
|  |         DWORD nNames = 0; | ||
|  |         if (pThunk == NULL) { | ||
|  |             break; | ||
|  |         } | ||
|  | 
 | ||
|  |         for (; pThunk[nNames].u1.Ordinal; nNames++) { | ||
|  |             // Count the imports.
 | ||
|  |         } | ||
|  | 
 | ||
|  |         for (DWORD f = 0; f < nNames; f++) { | ||
|  |             DWORD nOrdinal = 0; | ||
|  |             PCHAR pszName = NULL; | ||
|  |             PDWORD pFunc = (PDWORD)pBoundThunk[f].u1.Function; | ||
|  |             DWORD rvaName = (DWORD)pThunk[f].u1.Ordinal; | ||
|  | 
 | ||
|  |             if (rvaName & IMAGE_ORDINAL_FLAG) { | ||
|  |                 nOrdinal = IMAGE_ORDINAL(rvaName); | ||
|  |             } | ||
|  |             else { | ||
|  |                 PIMAGE_IMPORT_BY_NAME pName | ||
|  |                     = (PIMAGE_IMPORT_BY_NAME)RvaToVa(pbBase, rvaName); | ||
|  |                 if (pName) { | ||
|  |                     pszName = (PCHAR)pName->Name; | ||
|  |                 } | ||
|  |             } | ||
|  |             Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |                    "  %-32.32s %4I64d %p\n", pszName, nOrdinal, pFunc); | ||
|  |         } | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | #if _MSC_VER >= 1900
 | ||
|  | #pragma warning(pop)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | BOOL InstanceEnumerate(HINSTANCE hInst) | ||
|  | { | ||
|  |     WCHAR wzDllName[MAX_PATH]; | ||
|  | 
 | ||
|  |     PIMAGE_NT_HEADERS pinh = NtHeadersForInstance(hInst); | ||
|  |     if (pinh && Real_GetModuleFileNameW(hInst, wzDllName, ARRAYSIZE(wzDllName))) { | ||
|  |         Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |                "### %08lx: %-43.43ls %08x\n", | ||
|  |                hInst, wzDllName, pinh->OptionalHeader.CheckSum); | ||
|  |         return TRUE; | ||
|  |     } | ||
|  |     return FALSE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ProcessEnumerate() | ||
|  | { | ||
|  |     Syelog(SYELOG_SEVERITY_INFORMATION, | ||
|  |            "######################################################### Binaries\n"); | ||
|  |     for (HINSTANCE hInst = NULL; (hInst = DetourEnumerateModules(hInst)) != NULL;) { | ||
|  |         InstanceEnumerate(hInst); | ||
|  |     } | ||
|  |     Syelog(SYELOG_SEVERITY_INFORMATION, "###\n"); | ||
|  | 
 | ||
|  |     return ImportEnumerate(GetModuleHandle(NULL)); | ||
|  | } | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | // DLL module information
 | ||
|  | //
 | ||
|  | BOOL ThreadAttach(HMODULE hDll) | ||
|  | { | ||
|  |     (void)hDll; | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)0); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         LONG nThread = InterlockedIncrement(&s_nThreadCnt); | ||
|  |         TlsSetValue(s_nTlsThread, (PVOID)(LONG_PTR)nThread); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ThreadDetach(HMODULE hDll) | ||
|  | { | ||
|  |     (void)hDll; | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsSetValue(s_nTlsIndent, (PVOID)0); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         TlsSetValue(s_nTlsThread, (PVOID)0); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ProcessAttach(HMODULE hDll) | ||
|  | { | ||
|  |     s_bLog = FALSE; | ||
|  |     s_nTlsIndent = TlsAlloc(); | ||
|  |     s_nTlsThread = TlsAlloc(); | ||
|  |     ThreadAttach(hDll); | ||
|  | 
 | ||
|  |     WCHAR wzExeName[MAX_PATH]; | ||
|  | 
 | ||
|  |     s_hInst = hDll; | ||
|  |     Real_GetModuleFileNameW(hDll, s_wzDllPath, ARRAYSIZE(s_wzDllPath)); | ||
|  |     Real_GetModuleFileNameW(NULL, wzExeName, ARRAYSIZE(wzExeName)); | ||
|  | 
 | ||
|  |     SyelogOpen("trclnk" DETOURS_STRINGIFY(DETOURS_BITS), SYELOG_FACILITY_APPLICATION); | ||
|  |     ProcessEnumerate(); | ||
|  | 
 | ||
|  |     LONG error = AttachDetours(); | ||
|  |     if (error != NO_ERROR) { | ||
|  |         Syelog(SYELOG_SEVERITY_FATAL, "### Error attaching detours: %d\n", error); | ||
|  |     } | ||
|  | 
 | ||
|  |     s_bLog = TRUE; | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL ProcessDetach(HMODULE hDll) | ||
|  | { | ||
|  |     ThreadDetach(hDll); | ||
|  |     s_bLog = FALSE; | ||
|  | 
 | ||
|  |     LONG error = DetachDetours(); | ||
|  |     if (error != NO_ERROR) { | ||
|  |         Syelog(SYELOG_SEVERITY_FATAL, "### Error detaching detours: %d\n", error); | ||
|  |     } | ||
|  | 
 | ||
|  |     Syelog(SYELOG_SEVERITY_NOTICE, "### Closing.\n"); | ||
|  |     SyelogClose(FALSE); | ||
|  | 
 | ||
|  |     if (s_nTlsIndent >= 0) { | ||
|  |         TlsFree(s_nTlsIndent); | ||
|  |     } | ||
|  |     if (s_nTlsThread >= 0) { | ||
|  |         TlsFree(s_nTlsThread); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved) | ||
|  | { | ||
|  |     (void)hModule; | ||
|  |     (void)lpReserved; | ||
|  | 
 | ||
|  |     if (DetourIsHelperProcess()) { | ||
|  |         return TRUE; | ||
|  |     } | ||
|  | 
 | ||
|  |     switch (dwReason) { | ||
|  |       case DLL_PROCESS_ATTACH: | ||
|  |         DetourRestoreAfterWith(); | ||
|  |         return ProcessAttach(hModule); | ||
|  |       case DLL_PROCESS_DETACH: | ||
|  |         return ProcessDetach(hModule); | ||
|  |       case DLL_THREAD_ATTACH: | ||
|  |         return ThreadAttach(hModule); | ||
|  |       case DLL_THREAD_DETACH: | ||
|  |         return ThreadDetach(hModule); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | //
 | ||
|  | ///////////////////////////////////////////////////////////////// End of File.
 |