1211
This commit is contained in:
103
test/Detours/samples/tracelnk/Makefile
Normal file
103
test/Detours/samples/tracelnk/Makefile
Normal file
@@ -0,0 +1,103 @@
|
||||
##############################################################################
|
||||
##
|
||||
## Utility to trace Dynamic Linking.
|
||||
##
|
||||
## Microsoft Research Detours Package
|
||||
##
|
||||
## Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
##
|
||||
|
||||
!include ..\common.mak
|
||||
|
||||
LIBS=$(LIBS) kernel32.lib
|
||||
|
||||
##############################################################################
|
||||
|
||||
all: dirs \
|
||||
$(BIND)\trclnk$(DETOURS_BITS).dll \
|
||||
!IF $(DETOURS_SOURCE_BROWSING)==1
|
||||
$(OBJD)\trclnk$(DETOURS_BITS).bsc \
|
||||
!ENDIF
|
||||
option
|
||||
|
||||
##############################################################################
|
||||
|
||||
clean:
|
||||
-del *~ test.txt 2>nul
|
||||
-del $(BIND)\trclnk*.* 2>nul
|
||||
-rmdir /q /s $(OBJD) 2>nul
|
||||
|
||||
realclean: clean
|
||||
-rmdir /q /s $(OBJDS) 2>nul
|
||||
|
||||
dirs:
|
||||
@if not exist $(BIND) mkdir $(BIND) && echo . Created $(BIND)
|
||||
@if not exist $(OBJD) mkdir $(OBJD) && echo . Created $(OBJD)
|
||||
|
||||
##############################################################################
|
||||
|
||||
$(OBJD)\trclnk.obj : trclnk.cpp
|
||||
|
||||
$(OBJD)\trclnk.res : trclnk.rc
|
||||
|
||||
$(BIND)\trclnk$(DETOURS_BITS).dll : $(OBJD)\trclnk.obj $(OBJD)\trclnk.res $(DEPS)
|
||||
cl /LD $(CFLAGS) /Fe$@ /Fd$(@R).pdb \
|
||||
$(OBJD)\trclnk.obj $(OBJD)\trclnk.res \
|
||||
/link $(LINKFLAGS) /subsystem:console \
|
||||
/export:DetourFinishHelperProcess,@1,NONAME \
|
||||
$(LIBS)
|
||||
|
||||
$(OBJD)\trclnk$(DETOURS_BITS).bsc : $(OBJD)\trclnk.obj
|
||||
bscmake /v /n /o $@ $(OBJD)\trclnk.sbr
|
||||
|
||||
############################################### Install non-bit-size binaries.
|
||||
|
||||
!IF "$(DETOURS_OPTION_PROCESSOR)" != ""
|
||||
|
||||
$(OPTD)\trclnk$(DETOURS_OPTION_BITS).dll:
|
||||
$(OPTD)\trclnk$(DETOURS_OPTION_BITS).pdb:
|
||||
|
||||
$(BIND)\trclnk$(DETOURS_OPTION_BITS).dll : $(OPTD)\trclnk$(DETOURS_OPTION_BITS).dll
|
||||
@if exist $? copy /y $? $(BIND) >nul && echo $@ copied from $(DETOURS_OPTION_PROCESSOR).
|
||||
$(BIND)\trclnk$(DETOURS_OPTION_BITS).pdb : $(OPTD)\trclnk$(DETOURS_OPTION_BITS).pdb
|
||||
@if exist $? copy /y $? $(BIND) >nul && echo $@ copied from $(DETOURS_OPTION_PROCESSOR).
|
||||
|
||||
option: \
|
||||
$(BIND)\trclnk$(DETOURS_OPTION_BITS).dll \
|
||||
$(BIND)\trclnk$(DETOURS_OPTION_BITS).pdb \
|
||||
|
||||
!ELSE
|
||||
|
||||
option:
|
||||
|
||||
!ENDIF
|
||||
|
||||
##############################################################################
|
||||
|
||||
notepad: all
|
||||
@echo -------- Logging output to test.txt ------------
|
||||
start $(BIND)\syelogd.exe /o test.txt
|
||||
$(BIND)\sleep5.exe 1
|
||||
@echo -------- Should load trclnk$(DETOURS_BITS).dll dynamically using withdll.exe ------------
|
||||
@echo .
|
||||
@echo ** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE **
|
||||
@echo **
|
||||
@echo ** Close the NotePad window to continue test.
|
||||
@echo **
|
||||
@echo ** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE **
|
||||
@echo .
|
||||
$(BIND)\withdll -d:$(BIND)\trclnk$(DETOURS_BITS).dll $(SYSTEMROOT)\system32\notepad.exe
|
||||
@echo -------- Log from syelog -------------
|
||||
type test.txt
|
||||
|
||||
test: all
|
||||
@echo -------- Logging output to test.txt ------------
|
||||
start $(BIND)\syelogd.exe /o test.txt
|
||||
$(BIND)\sleep5.exe 1
|
||||
@echo -------- Should load trclnk$(DETOURS_BITS).dll dynamically using withdll.exe ------------
|
||||
@echo .
|
||||
$(BIND)\withdll -d:$(BIND)\trclnk$(DETOURS_BITS).dll $(SYSTEMROOT)\system32\cmd.exe /c dir
|
||||
@echo -------- Log from syelog -------------
|
||||
type test.txt
|
||||
|
||||
################################################################# End of File.
|
||||
685
test/Detours/samples/tracelnk/trclnk.cpp
Normal file
685
test/Detours/samples/tracelnk/trclnk.cpp
Normal file
@@ -0,0 +1,685 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
17
test/Detours/samples/tracelnk/trclnk.rc
Normal file
17
test/Detours/samples/tracelnk/trclnk.rc
Normal file
@@ -0,0 +1,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version information for trclnk.rc.
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
|
||||
#include "detver.h"
|
||||
|
||||
#define VER_INTERNALNAME_STR "trclnk" DETOURS_STRINGIFY(DETOURS_BITS)
|
||||
#define VER_ORIGINALFILENAME_STR "trclnk" DETOURS_STRINGIFY(DETOURS_BITS) ".dll"
|
||||
#define VER_FILEDESCRIPTION_STR "Detours Dynamic Linking Trace Module"
|
||||
#define VER_COMPANYNAME_STR "Microsoft Corporation"
|
||||
|
||||
#include "common.ver"
|
||||
Reference in New Issue
Block a user