diff --git a/NanaZip.Shared/Detours/Detours.h b/NanaZip.Shared/Detours/Detours.h deleted file mode 100644 index 3fdd842..0000000 --- a/NanaZip.Shared/Detours/Detours.h +++ /dev/null @@ -1,1233 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// Core Detours Functionality (detours.h of detours.lib) -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -#pragma once -#ifndef _DETOURS_H_ -#define _DETOURS_H_ - -#define DETOURS_VERSION 0x4c0c1 // 0xMAJORcMINORcPATCH - -////////////////////////////////////////////////////////////////////////////// -// - -#ifdef DETOURS_INTERNAL - -#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 -#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1 - -#pragma warning(disable:4068) // unknown pragma (suppress) - -#if _MSC_VER >= 1900 -#pragma warning(push) -#pragma warning(disable:4091) // empty typedef -#endif - -// Suppress declspec(dllimport) for the sake of Detours -// users that provide kernel32 functionality themselves. -// This is ok in the mainstream case, it will just cost -// an extra instruction calling some functions, which -// LTCG optimizes away. -// -#define _KERNEL32_ 1 -#define _USER32_ 1 - -#include -#if (_MSC_VER < 1310) -#else -#pragma warning(push) -#if _MSC_VER > 1400 -#pragma warning(disable:6102 6103) // /analyze warnings -#endif -#include -#include -#pragma warning(pop) -#endif -#include - -// Allow Detours to cleanly compile with the MingW toolchain. -// -#ifdef __GNUC__ -#define __try -#define __except(x) if (0) -#include -#include -#endif - -// From winerror.h, as this error isn't found in some SDKs: -// -// MessageId: ERROR_DYNAMIC_CODE_BLOCKED -// -// MessageText: -// -// The operation was blocked as the process prohibits dynamic code generation. -// -#define ERROR_DYNAMIC_CODE_BLOCKED 1655L - -#endif // DETOURS_INTERNAL - -////////////////////////////////////////////////////////////////////////////// -// - -#undef DETOURS_X64 -#undef DETOURS_X86 -#undef DETOURS_IA64 -#undef DETOURS_ARM -#undef DETOURS_ARM64 -#undef DETOURS_BITS -#undef DETOURS_32BIT -#undef DETOURS_64BIT - -#if defined(_X86_) -#define DETOURS_X86 -#define DETOURS_OPTION_BITS 64 - -#elif defined(_AMD64_) -#define DETOURS_X64 -#define DETOURS_OPTION_BITS 32 - -#elif defined(_IA64_) -#define DETOURS_IA64 -#define DETOURS_OPTION_BITS 32 - -#elif defined(_ARM_) -#define DETOURS_ARM - -#elif defined(_ARM64_) -#define DETOURS_ARM64 - -#else -#error Unknown architecture (x86, amd64, ia64, arm, arm64) -#endif - -#ifdef _WIN64 -#undef DETOURS_32BIT -#define DETOURS_64BIT 1 -#define DETOURS_BITS 64 -// If all 64bit kernels can run one and only one 32bit architecture. -//#define DETOURS_OPTION_BITS 32 -#else -#define DETOURS_32BIT 1 -#undef DETOURS_64BIT -#define DETOURS_BITS 32 -// If all 64bit kernels can run one and only one 32bit architecture. -//#define DETOURS_OPTION_BITS 32 -#endif - -/////////////////////////////////////////////////////////////// Helper Macros. -// -#define DETOURS_STRINGIFY_(x) #x -#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) - -#define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS) - -////////////////////////////////////////////////////////////////////////////// -// - -#if (_MSC_VER < 1299) && !defined(__MINGW32__) -typedef LONG LONG_PTR; -typedef ULONG ULONG_PTR; -#endif - -///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. -// -// These definitions are include so that Detours will build even if the -// compiler doesn't have full SAL 2.0 support. -// -#ifndef DETOURS_DONT_REMOVE_SAL_20 - -#ifdef DETOURS_TEST_REMOVE_SAL_20 -#undef _Analysis_assume_ -#undef _Benign_race_begin_ -#undef _Benign_race_end_ -#undef _Field_range_ -#undef _Field_size_ -#undef _In_ -#undef _In_bytecount_ -#undef _In_count_ -#undef __in_ecount -#undef _In_opt_ -#undef _In_opt_bytecount_ -#undef _In_opt_count_ -#undef _In_opt_z_ -#undef _In_range_ -#undef _In_reads_ -#undef _In_reads_bytes_ -#undef _In_reads_opt_ -#undef _In_reads_opt_bytes_ -#undef _In_reads_or_z_ -#undef _In_z_ -#undef _Inout_ -#undef _Inout_opt_ -#undef _Inout_z_count_ -#undef _Out_ -#undef _Out_opt_ -#undef _Out_writes_ -#undef _Outptr_result_maybenull_ -#undef _Readable_bytes_ -#undef _Success_ -#undef _Writable_bytes_ -#undef _Pre_notnull_ -#endif - -#if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) -#define _Outptr_result_maybenull_ _Deref_out_opt_z_ -#endif - -#if defined(_In_count_) && !defined(_In_reads_) -#define _In_reads_(x) _In_count_(x) -#endif - -#if defined(_In_opt_count_) && !defined(_In_reads_opt_) -#define _In_reads_opt_(x) _In_opt_count_(x) -#endif - -#if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) -#define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) -#endif - -#if defined(_In_bytecount_) && !defined(_In_reads_bytes_) -#define _In_reads_bytes_(x) _In_bytecount_(x) -#endif - -#ifndef _In_ -#define _In_ -#endif - -#ifndef _In_bytecount_ -#define _In_bytecount_(x) -#endif - -#ifndef _In_count_ -#define _In_count_(x) -#endif - -#ifndef __in_ecount -#define __in_ecount(x) -#endif - -#ifndef _In_opt_ -#define _In_opt_ -#endif - -#ifndef _In_opt_bytecount_ -#define _In_opt_bytecount_(x) -#endif - -#ifndef _In_opt_count_ -#define _In_opt_count_(x) -#endif - -#ifndef _In_opt_z_ -#define _In_opt_z_ -#endif - -#ifndef _In_range_ -#define _In_range_(x,y) -#endif - -#ifndef _In_reads_ -#define _In_reads_(x) -#endif - -#ifndef _In_reads_bytes_ -#define _In_reads_bytes_(x) -#endif - -#ifndef _In_reads_opt_ -#define _In_reads_opt_(x) -#endif - -#ifndef _In_reads_opt_bytes_ -#define _In_reads_opt_bytes_(x) -#endif - -#ifndef _In_reads_or_z_ -#define _In_reads_or_z_ -#endif - -#ifndef _In_z_ -#define _In_z_ -#endif - -#ifndef _Inout_ -#define _Inout_ -#endif - -#ifndef _Inout_opt_ -#define _Inout_opt_ -#endif - -#ifndef _Inout_z_count_ -#define _Inout_z_count_(x) -#endif - -#ifndef _Out_ -#define _Out_ -#endif - -#ifndef _Out_opt_ -#define _Out_opt_ -#endif - -#ifndef _Out_writes_ -#define _Out_writes_(x) -#endif - -#ifndef _Outptr_result_maybenull_ -#define _Outptr_result_maybenull_ -#endif - -#ifndef _Writable_bytes_ -#define _Writable_bytes_(x) -#endif - -#ifndef _Readable_bytes_ -#define _Readable_bytes_(x) -#endif - -#ifndef _Success_ -#define _Success_(x) -#endif - -#ifndef _Pre_notnull_ -#define _Pre_notnull_ -#endif - -#ifdef DETOURS_INTERNAL - -#pragma warning(disable:4615) // unknown warning type (suppress with older compilers) - -#ifndef _Benign_race_begin_ -#define _Benign_race_begin_ -#endif - -#ifndef _Benign_race_end_ -#define _Benign_race_end_ -#endif - -#ifndef _Field_size_ -#define _Field_size_(x) -#endif - -#ifndef _Field_range_ -#define _Field_range_(x,y) -#endif - -#ifndef _Analysis_assume_ -#define _Analysis_assume_(x) -#endif - -#endif // DETOURS_INTERNAL -#endif // DETOURS_DONT_REMOVE_SAL_20 - -////////////////////////////////////////////////////////////////////////////// -// -#ifndef GUID_DEFINED -#define GUID_DEFINED -typedef struct _GUID -{ - DWORD Data1; - WORD Data2; - WORD Data3; - BYTE Data4[ 8 ]; -} GUID; - -#ifdef INITGUID -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - const GUID name \ - = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#else -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - const GUID name -#endif // INITGUID -#endif // !GUID_DEFINED - -#if defined(__cplusplus) -#ifndef _REFGUID_DEFINED -#define _REFGUID_DEFINED -#define REFGUID const GUID & -#endif // !_REFGUID_DEFINED -#else // !__cplusplus -#ifndef _REFGUID_DEFINED -#define _REFGUID_DEFINED -#define REFGUID const GUID * const -#endif // !_REFGUID_DEFINED -#endif // !__cplusplus - -#ifndef ARRAYSIZE -#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) -#endif - -// -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/////////////////////////////////////////////////// Instruction Target Macros. -// -#define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) -#define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) -#define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" - -extern const GUID DETOUR_EXE_RESTORE_GUID; -extern const GUID DETOUR_EXE_HELPER_GUID; - -#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! -typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; - -#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS -#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32 -#endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS - -/////////////////////////////////////////////////////////// Binary Structures. -// -#pragma pack(push, 8) -typedef struct _DETOUR_SECTION_HEADER -{ - DWORD cbHeaderSize; - DWORD nSignature; - DWORD nDataOffset; - DWORD cbDataSize; - - DWORD nOriginalImportVirtualAddress; - DWORD nOriginalImportSize; - DWORD nOriginalBoundImportVirtualAddress; - DWORD nOriginalBoundImportSize; - - DWORD nOriginalIatVirtualAddress; - DWORD nOriginalIatSize; - DWORD nOriginalSizeOfImage; - DWORD cbPrePE; - - DWORD nOriginalClrFlags; - DWORD reserved1; - DWORD reserved2; - DWORD reserved3; - - // Followed by cbPrePE bytes of data. -} DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; - -typedef struct _DETOUR_SECTION_RECORD -{ - DWORD cbBytes; - DWORD nReserved; - GUID guid; -} DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; - -typedef struct _DETOUR_CLR_HEADER -{ - // Header versioning - ULONG cb; - USHORT MajorRuntimeVersion; - USHORT MinorRuntimeVersion; - - // Symbol table and startup information - IMAGE_DATA_DIRECTORY MetaData; - ULONG Flags; - - // Followed by the rest of the IMAGE_COR20_HEADER -} DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; - -typedef struct _DETOUR_EXE_RESTORE -{ - DWORD cb; - DWORD cbidh; - DWORD cbinh; - DWORD cbclr; - - PBYTE pidh; - PBYTE pinh; - PBYTE pclr; - - IMAGE_DOS_HEADER idh; - union { - IMAGE_NT_HEADERS inh; // all environments have this -#ifdef IMAGE_NT_OPTIONAL_HDR32_MAGIC // some environments do not have this - IMAGE_NT_HEADERS32 inh32; -#endif -#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this - IMAGE_NT_HEADERS64 inh64; -#endif -#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this - BYTE raw[sizeof(IMAGE_NT_HEADERS64) + - sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS]; -#else - BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS]; -#endif - }; - DETOUR_CLR_HEADER clr; - -} DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; - -#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC -C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == 0x108); -#endif - -// The size can change, but assert for clarity due to the muddying #ifdefs. -#ifdef _WIN64 -C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x688); -#else -C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x678); -#endif - -typedef struct _DETOUR_EXE_HELPER -{ - DWORD cb; - DWORD pid; - DWORD nDlls; - CHAR rDlls[4]; -} DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; - -#pragma pack(pop) - -#define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ -{ \ - sizeof(DETOUR_SECTION_HEADER),\ - DETOUR_SECTION_HEADER_SIGNATURE,\ - sizeof(DETOUR_SECTION_HEADER),\ - (cbSectionSize),\ - \ - 0,\ - 0,\ - 0,\ - 0,\ - \ - 0,\ - 0,\ - 0,\ - 0,\ -} - -///////////////////////////////////////////////////////////// Binary Typedefs. -// -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( - _In_opt_ PVOID pContext, - _In_opt_ LPCSTR pszFile, - _Outptr_result_maybenull_ LPCSTR *ppszOutFile); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( - _In_opt_ PVOID pContext, - _In_ LPCSTR pszOrigFile, - _In_ LPCSTR pszFile, - _Outptr_result_maybenull_ LPCSTR *ppszOutFile); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( - _In_opt_ PVOID pContext, - _In_ ULONG nOrigOrdinal, - _In_ ULONG nOrdinal, - _Out_ ULONG *pnOutOrdinal, - _In_opt_ LPCSTR pszOrigSymbol, - _In_opt_ LPCSTR pszSymbol, - _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( - _In_opt_ PVOID pContext); - -typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, - _In_ ULONG nOrdinal, - _In_opt_ LPCSTR pszName, - _In_opt_ PVOID pCode); - -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, - _In_opt_ HMODULE hModule, - _In_opt_ LPCSTR pszFile); - -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, - _In_ DWORD nOrdinal, - _In_opt_ LPCSTR pszFunc, - _In_opt_ PVOID pvFunc); - -// Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, - _In_ DWORD nOrdinal, - _In_opt_ LPCSTR pszFunc, - _In_opt_ PVOID* ppvFunc); - -typedef VOID * PDETOUR_BINARY; -typedef VOID * PDETOUR_LOADED_BINARY; - -//////////////////////////////////////////////////////////// Transaction APIs. -// -LONG WINAPI DetourTransactionBegin(VOID); -LONG WINAPI DetourTransactionAbort(VOID); -LONG WINAPI DetourTransactionCommit(VOID); -LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); - -LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); - -LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour); - -LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour, - _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, - _Out_opt_ PVOID *ppRealTarget, - _Out_opt_ PVOID *ppRealDetour); - -LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour); - -BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); -BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); -PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); -PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); - -////////////////////////////////////////////////////////////// Code Functions. -// -PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, - _In_ LPCSTR pszFunction); -PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, - _Out_opt_ PVOID *ppGlobals); -PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, - _Inout_opt_ PVOID *ppDstPool, - _In_ PVOID pSrc, - _Out_opt_ PVOID *ppTarget, - _Out_opt_ LONG *plExtra); -BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, - _In_ BOOL fLimitReferencesToModule); -PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, - _Out_ PDWORD pcbAllocatedSize); -BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode, - _In_ PBYTE pbAddress); - -///////////////////////////////////////////////////// Loaded Binary Functions. -// -HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); -HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); -PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); -ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); -BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); -BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, - _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); - -BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, - _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, - _In_ REFGUID rguid, - _Out_opt_ DWORD *pcbData); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, - _Out_opt_ DWORD *pcbData); - -DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); - -BOOL WINAPI DetourFreePayload(_In_ PVOID pvData); -///////////////////////////////////////////////// Persistent Binary Functions. -// - -PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, - _Out_opt_ GUID *pGuid, - _Out_ DWORD *pcbData, - _Inout_ DWORD *pnIterator); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, - _In_ REFGUID rguid, - _Out_ DWORD *pcbData); - -PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, - _In_ REFGUID rguid, - _In_reads_opt_(cbData) PVOID pData, - _In_ DWORD cbData); -BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); -BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); -BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); -BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, - _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, - _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, - _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); -BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); -BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); - -/////////////////////////////////////////////////// Create Process & Load Dll. -// -_Success_(return != NULL) -PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _Out_opt_ DWORD *pcbData); - -typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( - _In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation); - -typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( - _In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation); - -BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDll DetourCreateProcessWithDllW -#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW -#else -#define DetourCreateProcessWithDll DetourCreateProcessWithDllA -#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA -#endif // !UNICODE - -BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW -#else -#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA -#endif // !UNICODE - -BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW -#else -#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA -#endif // !UNICODE - -BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourProcessViaHelper DetourProcessViaHelperW -#else -#define DetourProcessViaHelper DetourProcessViaHelperA -#endif // !UNICODE - -BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW -#else -#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA -#endif // !UNICODE - -BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls); - -BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, - _In_ HMODULE hImage, - _In_ BOOL bIs32Bit, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls); - -BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _In_reads_bytes_(cbData) LPCVOID pvData, - _In_ DWORD cbData); -_Success_(return != NULL) -PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _In_reads_bytes_(cbData) LPCVOID pvData, - _In_ DWORD cbData); - -BOOL WINAPI DetourRestoreAfterWith(VOID); -BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, - _In_ DWORD cbData); -BOOL WINAPI DetourIsHelperProcess(VOID); -VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, - _In_ HINSTANCE, - _In_ LPSTR, - _In_ INT); - -// -////////////////////////////////////////////////////////////////////////////// -#ifdef __cplusplus -} -#endif // __cplusplus - -/////////////////////////////////////////////////// Type-safe overloads for C++ -// -#if __cplusplus >= 201103L || _MSVC_LANG >= 201103L -#include - -template -struct DetoursIsFunctionPointer : std::false_type {}; - -template -struct DetoursIsFunctionPointer : std::is_function::type> {}; - -template< - typename T, - typename std::enable_if::value, int>::type = 0> -LONG DetourAttach(_Inout_ T *ppPointer, - _In_ T pDetour) noexcept -{ - return DetourAttach( - reinterpret_cast(ppPointer), - reinterpret_cast(pDetour)); -} - -template< - typename T, - typename std::enable_if::value, int>::type = 0> -LONG DetourAttachEx(_Inout_ T *ppPointer, - _In_ T pDetour, - _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, - _Out_opt_ T *ppRealTarget, - _Out_opt_ T *ppRealDetour) noexcept -{ - return DetourAttachEx( - reinterpret_cast(ppPointer), - reinterpret_cast(pDetour), - ppRealTrampoline, - reinterpret_cast(ppRealTarget), - reinterpret_cast(ppRealDetour)); -} - -template< - typename T, - typename std::enable_if::value, int>::type = 0> -LONG DetourDetach(_Inout_ T *ppPointer, - _In_ T pDetour) noexcept -{ - return DetourDetach( - reinterpret_cast(ppPointer), - reinterpret_cast(pDetour)); -} - -#endif // __cplusplus >= 201103L || _MSVC_LANG >= 201103L -// -////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////// Detours Internal Definitions. -// -#ifdef __cplusplus -#ifdef DETOURS_INTERNAL - -#define NOTHROW -// #define NOTHROW (nothrow) - -////////////////////////////////////////////////////////////////////////////// -// -#if (_MSC_VER < 1299) && !defined(__GNUC__) -#include -typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; -typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; -typedef IMAGEHLP_SYMBOL SYMBOL_INFO; -typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; - -static inline -LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) -{ - return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); -} -#else -#pragma warning(push) -#pragma warning(disable:4091) // empty typedef -#include -#pragma warning(pop) -#endif - -#ifdef IMAGEAPI // defined by DBGHELP.H -typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); - -typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, - _In_opt_ LPCSTR UserSearchPath, - _In_ BOOL fInvadeProcess); -typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); -typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); -typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, - _In_opt_ HANDLE hFile, - _In_opt_ LPSTR ImageName, - _In_opt_ LPSTR ModuleName, - _In_ DWORD64 BaseOfDll, - _In_ DWORD SizeOfDll); -typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, - _In_ DWORD64 qwAddr, - _Out_ PIMAGEHLP_MODULE64 ModuleInfo); -typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, - _In_ LPSTR Name, - _Out_ PSYMBOL_INFO Symbol); - -typedef struct _DETOUR_SYM_INFO -{ - HANDLE hProcess; - HMODULE hDbgHelp; - PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; - PF_SymInitialize pfSymInitialize; - PF_SymSetOptions pfSymSetOptions; - PF_SymGetOptions pfSymGetOptions; - PF_SymLoadModule64 pfSymLoadModule64; - PF_SymGetModuleInfo64 pfSymGetModuleInfo64; - PF_SymFromName pfSymFromName; -} DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; - -PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); - -#endif // IMAGEAPI - -#if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) -#error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) -#endif -#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 - -#ifdef _DEBUG - -int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg); - -#define DETOUR_ASSERT_EXPR_WITH_FUNCTION(expr, msg) \ - (void) ((expr) || \ - (1 != Detour_AssertExprWithFunctionName(_CRT_ASSERT, __FILE__, __LINE__,__FUNCTION__, msg)) || \ - (_CrtDbgBreak(), 0)) - -#define DETOUR_ASSERT(expr) DETOUR_ASSERT_EXPR_WITH_FUNCTION((expr), #expr) - -#else// _DEBUG -#define DETOUR_ASSERT(expr) -#endif// _DEBUG - -#ifndef DETOUR_TRACE -#if DETOUR_DEBUG -#define DETOUR_TRACE(x) printf x -#define DETOUR_BREAK() __debugbreak() -#include -#include -#else -#define DETOUR_TRACE(x) -#define DETOUR_BREAK() -#endif -#endif - -#if 1 || defined(DETOURS_IA64) - -// -// IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. -// - -#define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) - -#define DETOUR_IA64_TEMPLATE_OFFSET (0) -#define DETOUR_IA64_TEMPLATE_SIZE (5) - -#define DETOUR_IA64_INSTRUCTION_SIZE (41) -#define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) -#define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) -#define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) - -C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); - -__declspec(align(16)) struct DETOUR_IA64_BUNDLE -{ - public: - union - { - BYTE data[16]; - UINT64 wide[2]; - }; - - enum { - A_UNIT = 1u, - I_UNIT = 2u, - M_UNIT = 3u, - B_UNIT = 4u, - F_UNIT = 5u, - L_UNIT = 6u, - X_UNIT = 7u, - }; - struct DETOUR_IA64_METADATA - { - ULONG nTemplate : 8; // Instruction template. - ULONG nUnit0 : 4; // Unit for slot 0 - ULONG nUnit1 : 4; // Unit for slot 1 - ULONG nUnit2 : 4; // Unit for slot 2 - }; - - protected: - static const DETOUR_IA64_METADATA s_rceCopyTable[33]; - - UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; - - bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, - _In_ BYTE slot, - _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; - - // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 - // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. - - // 00 - // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. - // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] - // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] - // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] - // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] - // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] - // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] - // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] - BYTE GetTemplate() const; - // Get 4 bit opcodes. - BYTE GetInst0() const; - BYTE GetInst1() const; - BYTE GetInst2() const; - BYTE GetUnit(BYTE slot) const; - BYTE GetUnit0() const; - BYTE GetUnit1() const; - BYTE GetUnit2() const; - // Get 37 bit data. - UINT64 GetData0() const; - UINT64 GetData1() const; - UINT64 GetData2() const; - - // Get/set the full 41 bit instructions. - UINT64 GetInstruction(BYTE slot) const; - UINT64 GetInstruction0() const; - UINT64 GetInstruction1() const; - UINT64 GetInstruction2() const; - void SetInstruction(BYTE slot, UINT64 instruction); - void SetInstruction0(UINT64 instruction); - void SetInstruction1(UINT64 instruction); - void SetInstruction2(UINT64 instruction); - - // Get/set bitfields. - static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); - static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); - - // Get specific read-only fields. - static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode - static UINT64 GetX(UINT64 instruction); // 1bit opcode extension - static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension - static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension - - // Get/set specific fields. - static UINT64 GetImm7a(UINT64 instruction); - static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); - static UINT64 GetImm13c(UINT64 instruction); - static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); - static UINT64 GetSignBit(UINT64 instruction); - static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); - static UINT64 GetImm20a(UINT64 instruction); - static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); - static UINT64 GetImm20b(UINT64 instruction); - static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); - - static UINT64 SignExtend(UINT64 Value, UINT64 Offset); - - BOOL IsMovlGp() const; - - VOID SetInst(BYTE Slot, BYTE nInst); - VOID SetInst0(BYTE nInst); - VOID SetInst1(BYTE nInst); - VOID SetInst2(BYTE nInst); - VOID SetData(BYTE Slot, UINT64 nData); - VOID SetData0(UINT64 nData); - VOID SetData1(UINT64 nData); - VOID SetData2(UINT64 nData); - BOOL SetNop(BYTE Slot); - BOOL SetNop0(); - BOOL SetNop1(); - BOOL SetNop2(); - - public: - BOOL IsBrl() const; - VOID SetBrl(); - VOID SetBrl(UINT64 target); - UINT64 GetBrlTarget() const; - VOID SetBrlTarget(UINT64 target); - VOID SetBrlImm(UINT64 imm); - UINT64 GetBrlImm() const; - - UINT64 GetMovlGp() const; - VOID SetMovlGp(UINT64 gp); - - VOID SetStop(); - - UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; -}; -#endif // DETOURS_IA64 - -#ifdef DETOURS_ARM - -#define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) -#define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) - -#endif // DETOURS_ARM - -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#define DETOUR_OFFLINE_LIBRARY(x) \ -PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ - _Inout_opt_ PVOID *ppDstPool, \ - _In_ PVOID pSrc, \ - _Out_opt_ PVOID *ppTarget, \ - _Out_opt_ LONG *plExtra); \ - \ -BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ - _In_ BOOL fLimitReferencesToModule); \ - -DETOUR_OFFLINE_LIBRARY(X86) -DETOUR_OFFLINE_LIBRARY(X64) -DETOUR_OFFLINE_LIBRARY(ARM) -DETOUR_OFFLINE_LIBRARY(ARM64) -DETOUR_OFFLINE_LIBRARY(IA64) - -#undef DETOUR_OFFLINE_LIBRARY - -////////////////////////////////////////////////////////////////////////////// -// -// Helpers for manipulating page protection. -// - -_Success_(return != FALSE) -BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, - _In_ PVOID pAddress, - _In_ SIZE_T nSize, - _In_ DWORD dwNewProtect, - _Out_ PDWORD pdwOldProtect); - -_Success_(return != FALSE) -BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, - _In_ SIZE_T nSize, - _In_ DWORD dwNewProtect, - _Out_ PDWORD pdwOldProtect); - -// Detours must depend only on kernel32.lib, so we cannot use IsEqualGUID -BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right); -#ifdef __cplusplus -} -#endif // __cplusplus - -////////////////////////////////////////////////////////////////////////////// - -#define MM_ALLOCATION_GRANULARITY 0x10000 - -////////////////////////////////////////////////////////////////////////////// - -#endif // DETOURS_INTERNAL -#endif // __cplusplus - -#endif // _DETOURS_H_ -// -//////////////////////////////////////////////////////////////// End of File. diff --git a/NanaZip.Shared/Detours/creatwth.cpp b/NanaZip.Shared/Detours/creatwth.cpp deleted file mode 100644 index fa8c381..0000000 --- a/NanaZip.Shared/Detours/creatwth.cpp +++ /dev/null @@ -1,1783 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Create a process with a DLL (creatwth.cpp of detours.lib) -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -// #define DETOUR_DEBUG 1 -#define DETOURS_INTERNAL -#include "detours.h" -#include - -#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH -#error detours.h version mismatch -#endif - -#define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] -#define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] -#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] -#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] - -////////////////////////////////////////////////////////////////////////////// -// -const GUID DETOUR_EXE_HELPER_GUID = { /* ea0251b9-5cde-41b5-98d0-2af4a26b0fee */ - 0xea0251b9, 0x5cde, 0x41b5, - { 0x98, 0xd0, 0x2a, 0xf4, 0xa2, 0x6b, 0x0f, 0xee }}; - -////////////////////////////////////////////////////////////////////////////// -// -// Enumerate through modules in the target process. -// -static PVOID LoadNtHeaderFromProcess(_In_ HANDLE hProcess, - _In_ HMODULE hModule, - _Out_ PIMAGE_NT_HEADERS32 pNtHeader) -{ - ZeroMemory(pNtHeader, sizeof(*pNtHeader)); - PBYTE pbModule = (PBYTE)hModule; - - if (pbModule == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - MEMORY_BASIC_INFORMATION mbi; - ZeroMemory(&mbi, sizeof(mbi)); - - if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) { - return NULL; - } - - IMAGE_DOS_HEADER idh; - if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", - pbModule, pbModule + sizeof(idh), GetLastError())); - return NULL; - } - - if (idh.e_magic != IMAGE_DOS_SIGNATURE || - (DWORD)idh.e_lfanew > mbi.RegionSize || - (DWORD)idh.e_lfanew < sizeof(idh)) { - - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } - - if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, - pNtHeader, sizeof(*pNtHeader), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %lu\n", - pbModule + idh.e_lfanew, - pbModule + idh.e_lfanew + sizeof(*pNtHeader), - pbModule, - GetLastError())); - return NULL; - } - - if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return NULL; - } - - return pbModule + idh.e_lfanew; -} - -static HMODULE EnumerateModulesInProcess(_In_ HANDLE hProcess, - _In_opt_ HMODULE hModuleLast, - _Out_ PIMAGE_NT_HEADERS32 pNtHeader, - _Out_opt_ PVOID *pRemoteNtHeader) -{ - ZeroMemory(pNtHeader, sizeof(*pNtHeader)); - if (pRemoteNtHeader) { - *pRemoteNtHeader = NULL; - } - - PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY; - - MEMORY_BASIC_INFORMATION mbi; - ZeroMemory(&mbi, sizeof(mbi)); - - // Find the next memory region that contains a mapped PE image. - // - - for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { - if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) == 0) { - break; - } - - // Usermode address space has such an unaligned region size always at the - // end and only at the end. - // - if ((mbi.RegionSize & 0xfff) == 0xfff) { - break; - } - if (((PBYTE)mbi.BaseAddress + mbi.RegionSize) < pbLast) { - break; - } - - // Skip uncommitted regions and guard pages. - // - if ((mbi.State != MEM_COMMIT) || - ((mbi.Protect & 0xff) == PAGE_NOACCESS) || - (mbi.Protect & PAGE_GUARD)) { - continue; - } - - PVOID remoteHeader - = LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader); - if (remoteHeader) { - if (pRemoteNtHeader) { - *pRemoteNtHeader = remoteHeader; - } - - return (HMODULE)pbLast; - } - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////////// -// -// Find payloads in target process. -// - -static PVOID FindDetourSectionInRemoteModule(_In_ HANDLE hProcess, - _In_ HMODULE hModule, - _In_ const IMAGE_NT_HEADERS32 *pNtHeader, - _In_ PVOID pRemoteNtHeader) -{ - if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { - SetLastError(ERROR_EXE_MARKED_INVALID); - return NULL; - } - - PIMAGE_SECTION_HEADER pRemoteSectionHeaders - = (PIMAGE_SECTION_HEADER)((PBYTE)pRemoteNtHeader - + sizeof(pNtHeader->Signature) - + sizeof(pNtHeader->FileHeader) - + pNtHeader->FileHeader.SizeOfOptionalHeader); - - IMAGE_SECTION_HEADER header; - for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; ++n) { - if (!ReadProcessMemory(hProcess, pRemoteSectionHeaders + n, &header, sizeof(header), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", - pRemoteSectionHeaders + n, - (PBYTE)(pRemoteSectionHeaders + n) + sizeof(header), - GetLastError())); - - return NULL; - } - - if (strcmp((PCHAR)header.Name, ".detour") == 0) { - if (header.VirtualAddress == 0 || - header.SizeOfRawData == 0) { - - break; - } - - SetLastError(NO_ERROR); - return (PBYTE)hModule + header.VirtualAddress; - } - } - - SetLastError(ERROR_EXE_MARKED_INVALID); - return NULL; -} - -static PVOID FindPayloadInRemoteDetourSection(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _Out_opt_ DWORD *pcbData, - _In_ PVOID pvRemoteDetoursSection) -{ - if (pcbData) { - *pcbData = 0; - } - - PBYTE pbData = (PBYTE)pvRemoteDetoursSection; - - DETOUR_SECTION_HEADER header; - if (!ReadProcessMemory(hProcess, pbData, &header, sizeof(header), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(dsh@%p..%p) failed: %lu\n", - pbData, - pbData + sizeof(header), - GetLastError())); - return NULL; - } - - if (header.cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || - header.nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { - SetLastError(ERROR_EXE_MARKED_INVALID); - return NULL; - } - - if (header.nDataOffset == 0) { - header.nDataOffset = header.cbHeaderSize; - } - - for (PVOID pvSection = pbData + header.nDataOffset; pvSection < pbData + header.cbDataSize;) { - DETOUR_SECTION_RECORD section; - if (!ReadProcessMemory(hProcess, pvSection, §ion, sizeof(section), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(dsr@%p..%p) failed: %lu\n", - pvSection, - (PBYTE)pvSection + sizeof(section), - GetLastError())); - return NULL; - } - - if (DetourAreSameGuid(section.guid, rguid)) { - if (pcbData) { - *pcbData = section.cbBytes - sizeof(section); - } - SetLastError(NO_ERROR); - return (DETOUR_SECTION_RECORD *)pvSection + 1; - } - - pvSection = (PBYTE)pvSection + section.cbBytes; - } - - return NULL; -} - -_Success_(return != NULL) -PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _Out_opt_ DWORD *pcbData) -{ - if (hProcess == NULL) { - SetLastError(ERROR_INVALID_HANDLE); - return NULL; - } - - IMAGE_NT_HEADERS32 header; - PVOID pvRemoteHeader; - for (HMODULE hMod = NULL; (hMod = EnumerateModulesInProcess(hProcess, hMod, &header, &pvRemoteHeader)) != NULL;) { - PVOID pvData = FindDetourSectionInRemoteModule(hProcess, hMod, &header, pvRemoteHeader); - if (pvData != NULL) { - pvData = FindPayloadInRemoteDetourSection(hProcess, rguid, pcbData, pvData); - if (pvData != NULL) { - return pvData; - } - } - } - - SetLastError(ERROR_MOD_NOT_FOUND); - return NULL; -} - -////////////////////////////////////////////////////////////////////////////// -// -// Find a region of memory in which we can create a replacement import table. -// -static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBase, DWORD cbAlloc) -{ - MEMORY_BASIC_INFORMATION mbi; - ZeroMemory(&mbi, sizeof(mbi)); - - PBYTE pbLast = pbBase; - for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { - - ZeroMemory(&mbi, sizeof(mbi)); - if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) == 0) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - break; - } - DETOUR_TRACE(("VirtualQueryEx(%p) failed: %lu\n", - pbLast, GetLastError())); - break; - } - // Usermode address space has such an unaligned region size always at the - // end and only at the end. - // - if ((mbi.RegionSize & 0xfff) == 0xfff) { - break; - } - - // Skip anything other than a pure free region. - // - if (mbi.State != MEM_FREE) { - continue; - } - - // Use the max of mbi.BaseAddress and pbBase, in case mbi.BaseAddress < pbBase. - PBYTE pbAddress = (PBYTE)mbi.BaseAddress > pbBase ? (PBYTE)mbi.BaseAddress : pbBase; - - // Round pbAddress up to the nearest MM allocation boundary. - const DWORD_PTR mmGranularityMinusOne = (DWORD_PTR)(MM_ALLOCATION_GRANULARITY -1); - pbAddress = (PBYTE)(((DWORD_PTR)pbAddress + mmGranularityMinusOne) & ~mmGranularityMinusOne); - -#ifdef _WIN64 - // The offset from pbModule to any replacement import must fit into 32 bits. - // For simplicity, we check that the offset to the last byte fits into 32 bits, - // instead of the largest offset we'll actually use. The values are very similar. - const size_t GB4 = ((((size_t)1) << 32) - 1); - if ((size_t)(pbAddress + cbAlloc - 1 - pbModule) > GB4) { - DETOUR_TRACE(("FindAndAllocateNearBase(1) failing due to distance >4GB %p\n", pbAddress)); - return NULL; - } -#else - UNREFERENCED_PARAMETER(pbModule); -#endif - - DETOUR_TRACE(("Free region %p..%p\n", - mbi.BaseAddress, - (PBYTE)mbi.BaseAddress + mbi.RegionSize)); - - for (; pbAddress < (PBYTE)mbi.BaseAddress + mbi.RegionSize; pbAddress += MM_ALLOCATION_GRANULARITY) { - PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (pbAlloc == NULL) { - DETOUR_TRACE(("VirtualAllocEx(%p) failed: %lu\n", pbAddress, GetLastError())); - continue; - } -#ifdef _WIN64 - // The offset from pbModule to any replacement import must fit into 32 bits. - if ((size_t)(pbAddress + cbAlloc - 1 - pbModule) > GB4) { - DETOUR_TRACE(("FindAndAllocateNearBase(2) failing due to distance >4GB %p\n", pbAddress)); - return NULL; - } -#endif - DETOUR_TRACE(("[%p..%p] Allocated for import table.\n", - pbAlloc, pbAlloc + cbAlloc)); - return pbAlloc; - } - } - return NULL; -} - -static inline DWORD PadToDword(DWORD dw) -{ - return (dw + 3) & ~3u; -} - -static inline DWORD PadToDwordPtr(DWORD dw) -{ - return (dw + 7) & ~7u; -} - -static inline HRESULT ReplaceOptionalSizeA(_Inout_z_count_(cchDest) LPSTR pszDest, - _In_ size_t cchDest, - _In_z_ LPCSTR pszSize) -{ - if (cchDest == 0 || pszDest == NULL || pszSize == NULL || - pszSize[0] == '\0' || pszSize[1] == '\0' || pszSize[2] != '\0') { - - // can not write into empty buffer or with string other than two chars. - return ERROR_INVALID_PARAMETER; - } - - for (; cchDest >= 2; cchDest--, pszDest++) { - if (pszDest[0] == '?' && pszDest[1] == '?') { - pszDest[0] = pszSize[0]; - pszDest[1] = pszSize[1]; - break; - } - } - - return S_OK; -} - -static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTORE& der) -{ - // Save the various headers for DetourRestoreAfterWith. - ZeroMemory(&der, sizeof(der)); - der.cb = sizeof(der); - - der.pidh = (PBYTE)hModule; - der.cbidh = sizeof(der.idh); - if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", - der.pidh, der.pidh + der.cbidh, GetLastError())); - return FALSE; - } - DETOUR_TRACE(("IDH: %p..%p\n", der.pidh, der.pidh + der.cbidh)); - - // We read the NT header in two passes to get the full size. - // First we read just the Signature and FileHeader. - der.pinh = der.pidh + der.idh.e_lfanew; - der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader); - if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", - der.pinh, der.pinh + der.cbinh, GetLastError())); - return FALSE; - } - - // Second we read the OptionalHeader and Section headers. - der.cbinh = (FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + - der.inh.FileHeader.SizeOfOptionalHeader + - der.inh.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); - - if (der.cbinh > sizeof(der.raw)) { - return FALSE; - } - - if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", - der.pinh, der.pinh + der.cbinh, GetLastError())); - return FALSE; - } - DETOUR_TRACE(("INH: %p..%p\n", der.pinh, der.pinh + der.cbinh)); - - // Third, we read the CLR header - - if (der.inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 && - der.inh32.CLR_DIRECTORY.Size != 0) { - - DETOUR_TRACE(("CLR32.VirtAddr=%08lx, CLR.Size=%lu\n", - der.inh32.CLR_DIRECTORY.VirtualAddress, - der.inh32.CLR_DIRECTORY.Size)); - - der.pclr = ((PBYTE)hModule) + der.inh32.CLR_DIRECTORY.VirtualAddress; - } - } - else if (der.inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 && - der.inh64.CLR_DIRECTORY.Size != 0) { - - DETOUR_TRACE(("CLR64.VirtAddr=%08lx, CLR.Size=%lu\n", - der.inh64.CLR_DIRECTORY.VirtualAddress, - der.inh64.CLR_DIRECTORY.Size)); - - der.pclr = ((PBYTE)hModule) + der.inh64.CLR_DIRECTORY.VirtualAddress; - } - } - - if (der.pclr != 0) { - der.cbclr = sizeof(der.clr); - if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %lu\n", - der.pclr, der.pclr + der.cbclr, GetLastError())); - return FALSE; - } - DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr)); - } - - return TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// -#if DETOURS_32BIT -#define DWORD_XX DWORD32 -#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32 -#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC -#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32 -#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA32 -#define UPDATE_IMPORTS_XX UpdateImports32 -#define DETOURS_BITS_XX 32 -#include "uimports.cpp" -#undef DETOUR_EXE_RESTORE_FIELD_XX -#undef DWORD_XX -#undef IMAGE_NT_HEADERS_XX -#undef IMAGE_NT_OPTIONAL_HDR_MAGIC_XX -#undef IMAGE_ORDINAL_FLAG_XX -#undef UPDATE_IMPORTS_XX -#endif // DETOURS_32BIT - -#if DETOURS_64BIT -#define DWORD_XX DWORD64 -#define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64 -#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC -#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64 -#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA64 -#define UPDATE_IMPORTS_XX UpdateImports64 -#define DETOURS_BITS_XX 64 -#include "uimports.cpp" -#undef DETOUR_EXE_RESTORE_FIELD_XX -#undef DWORD_XX -#undef IMAGE_NT_HEADERS_XX -#undef IMAGE_NT_OPTIONAL_HDR_MAGIC_XX -#undef IMAGE_ORDINAL_FLAG_XX -#undef UPDATE_IMPORTS_XX -#endif // DETOURS_64BIT - -////////////////////////////////////////////////////////////////////////////// -// -#if DETOURS_64BIT - -C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == sizeof(IMAGE_NT_HEADERS32) + 16); - -static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, - DETOUR_EXE_RESTORE& der) -{ - IMAGE_DOS_HEADER idh; - IMAGE_NT_HEADERS32 inh32; - IMAGE_NT_HEADERS64 inh64; - IMAGE_SECTION_HEADER sects[32]; - PBYTE pbModule = (PBYTE)hModule; - DWORD n; - - ZeroMemory(&inh32, sizeof(inh32)); - ZeroMemory(&inh64, sizeof(inh64)); - ZeroMemory(sects, sizeof(sects)); - - DETOUR_TRACE(("UpdateFrom32To64(%04x)\n", machine)); - //////////////////////////////////////////////////////// Read old headers. - // - if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", - pbModule, pbModule + sizeof(idh), GetLastError())); - return FALSE; - } - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p)\n", - pbModule, pbModule + sizeof(idh))); - - PBYTE pnh = pbModule + idh.e_lfanew; - if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", - pnh, pnh + sizeof(inh32), GetLastError())); - return FALSE; - } - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p)\n", pnh, pnh + sizeof(inh32))); - - if (inh32.FileHeader.NumberOfSections > (sizeof(sects)/sizeof(sects[0]))) { - return FALSE; - } - - PBYTE psects = pnh + - FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + - inh32.FileHeader.SizeOfOptionalHeader; - ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); - if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", - psects, psects + cb, GetLastError())); - return FALSE; - } - DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p)\n", psects, psects + cb)); - - ////////////////////////////////////////////////////////// Convert header. - // - inh64.Signature = inh32.Signature; - inh64.FileHeader = inh32.FileHeader; - inh64.FileHeader.Machine = machine; - inh64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); - - inh64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; - inh64.OptionalHeader.MajorLinkerVersion = inh32.OptionalHeader.MajorLinkerVersion; - inh64.OptionalHeader.MinorLinkerVersion = inh32.OptionalHeader.MinorLinkerVersion; - inh64.OptionalHeader.SizeOfCode = inh32.OptionalHeader.SizeOfCode; - inh64.OptionalHeader.SizeOfInitializedData = inh32.OptionalHeader.SizeOfInitializedData; - inh64.OptionalHeader.SizeOfUninitializedData = inh32.OptionalHeader.SizeOfUninitializedData; - inh64.OptionalHeader.AddressOfEntryPoint = inh32.OptionalHeader.AddressOfEntryPoint; - inh64.OptionalHeader.BaseOfCode = inh32.OptionalHeader.BaseOfCode; - inh64.OptionalHeader.ImageBase = inh32.OptionalHeader.ImageBase; - inh64.OptionalHeader.SectionAlignment = inh32.OptionalHeader.SectionAlignment; - inh64.OptionalHeader.FileAlignment = inh32.OptionalHeader.FileAlignment; - inh64.OptionalHeader.MajorOperatingSystemVersion - = inh32.OptionalHeader.MajorOperatingSystemVersion; - inh64.OptionalHeader.MinorOperatingSystemVersion - = inh32.OptionalHeader.MinorOperatingSystemVersion; - inh64.OptionalHeader.MajorImageVersion = inh32.OptionalHeader.MajorImageVersion; - inh64.OptionalHeader.MinorImageVersion = inh32.OptionalHeader.MinorImageVersion; - inh64.OptionalHeader.MajorSubsystemVersion = inh32.OptionalHeader.MajorSubsystemVersion; - inh64.OptionalHeader.MinorSubsystemVersion = inh32.OptionalHeader.MinorSubsystemVersion; - inh64.OptionalHeader.Win32VersionValue = inh32.OptionalHeader.Win32VersionValue; - inh64.OptionalHeader.SizeOfImage = inh32.OptionalHeader.SizeOfImage; - inh64.OptionalHeader.SizeOfHeaders = inh32.OptionalHeader.SizeOfHeaders; - inh64.OptionalHeader.CheckSum = inh32.OptionalHeader.CheckSum; - inh64.OptionalHeader.Subsystem = inh32.OptionalHeader.Subsystem; - inh64.OptionalHeader.DllCharacteristics = inh32.OptionalHeader.DllCharacteristics; - inh64.OptionalHeader.SizeOfStackReserve = inh32.OptionalHeader.SizeOfStackReserve; - inh64.OptionalHeader.SizeOfStackCommit = inh32.OptionalHeader.SizeOfStackCommit; - inh64.OptionalHeader.SizeOfHeapReserve = inh32.OptionalHeader.SizeOfHeapReserve; - inh64.OptionalHeader.SizeOfHeapCommit = inh32.OptionalHeader.SizeOfHeapCommit; - inh64.OptionalHeader.LoaderFlags = inh32.OptionalHeader.LoaderFlags; - inh64.OptionalHeader.NumberOfRvaAndSizes = inh32.OptionalHeader.NumberOfRvaAndSizes; - for (n = 0; n < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; n++) { - inh64.OptionalHeader.DataDirectory[n] = inh32.OptionalHeader.DataDirectory[n]; - } - - /////////////////////////////////////////////////////// Write new headers. - // - DWORD dwProtect = 0; - if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh64.OptionalHeader.SizeOfHeaders, - PAGE_EXECUTE_READWRITE, &dwProtect)) { - return FALSE; - } - - if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n", - pnh, pnh + sizeof(inh64), GetLastError())); - return FALSE; - } - DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p)\n", pnh, pnh + sizeof(inh64))); - - psects = pnh + - FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + - inh64.FileHeader.SizeOfOptionalHeader; - cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); - if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) { - DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %lu\n", - psects, psects + cb, GetLastError())); - return FALSE; - } - DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p)\n", psects, psects + cb)); - - // Record the updated headers. - if (!RecordExeRestore(hProcess, hModule, der)) { - return FALSE; - } - - // Remove the import table. - if (der.pclr != NULL && (der.clr.Flags & COMIMAGE_FLAGS_ILONLY)) { - inh64.IMPORT_DIRECTORY.VirtualAddress = 0; - inh64.IMPORT_DIRECTORY.Size = 0; - - if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n", - pnh, pnh + sizeof(inh64), GetLastError())); - return FALSE; - } - } - - DWORD dwOld = 0; - if (!VirtualProtectEx(hProcess, pbModule, inh64.OptionalHeader.SizeOfHeaders, - dwProtect, &dwOld)) { - return FALSE; - } - - return TRUE; -} -#endif // DETOURS_64BIT - -typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); - -static BOOL IsWow64ProcessHelper(HANDLE hProcess, - PBOOL Wow64Process) -{ -#ifdef _X86_ - if (Wow64Process == NULL) { - return FALSE; - } - - // IsWow64Process is not available on all supported versions of Windows. - // - HMODULE hKernel32 = LoadLibraryW(L"KERNEL32.DLL"); - if (hKernel32 == NULL) { - DETOUR_TRACE(("LoadLibraryW failed: %lu\n", GetLastError())); - return FALSE; - } - - LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( - hKernel32, "IsWow64Process"); - - if (pfnIsWow64Process == NULL) { - DETOUR_TRACE(("GetProcAddress failed: %lu\n", GetLastError())); - return FALSE; - } - return pfnIsWow64Process(hProcess, Wow64Process); -#else - return IsWow64Process(hProcess, Wow64Process); -#endif -} - -////////////////////////////////////////////////////////////////////////////// -// -BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls) -{ - // Find the next memory region that contains a mapped PE image. - // - BOOL bIs32BitProcess; - BOOL bIs64BitOS = FALSE; - HMODULE hModule = NULL; - HMODULE hLast = NULL; - - DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%lu)\n", hProcess, nDlls)); - - for (;;) { - IMAGE_NT_HEADERS32 inh; - - if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh, NULL)) == NULL) { - break; - } - - DETOUR_TRACE(("%p machine=%04x magic=%04x\n", - hLast, inh.FileHeader.Machine, inh.OptionalHeader.Magic)); - - if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) { - hModule = hLast; - DETOUR_TRACE(("%p Found EXE\n", hLast)); - } - } - - if (hModule == NULL) { - SetLastError(ERROR_INVALID_OPERATION); - return FALSE; - } - - // Determine if the target process is 32bit or 64bit. This is a two-stop process: - // - // 1. First, determine if we're running on a 64bit operating system. - // - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true. - // - If we're running 32bit code (i.e. _WIN64 is not defined), test if - // we're running under Wow64. If so, it implies that the operating system - // is 64bit. - // -#ifdef _WIN64 - bIs64BitOS = TRUE; -#else - if (!IsWow64ProcessHelper(GetCurrentProcess(), &bIs64BitOS)) { - return FALSE; - } -#endif - - // 2. With the operating system bitness known, we can now consider the target process: - // - If we're running on a 64bit OS, the target process is 32bit in case - // it is running under Wow64. Otherwise, it's 64bit, running natively - // (without Wow64). - // - If we're running on a 32bit OS, the target process must be 32bit, too. - // - if (bIs64BitOS) { - if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) { - return FALSE; - } - } else { - bIs32BitProcess = TRUE; - } - - DETOUR_TRACE((" 32BitProcess=%d\n", bIs32BitProcess)); - - return DetourUpdateProcessWithDllEx(hProcess, - hModule, - bIs32BitProcess, - rlpDlls, - nDlls); -} - -BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, - _In_ HMODULE hModule, - _In_ BOOL bIs32BitProcess, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls) -{ - // Find the next memory region that contains a mapped PE image. - // - BOOL bIs32BitExe = FALSE; - - DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%lu)\n", hProcess, hModule, nDlls)); - - IMAGE_NT_HEADERS32 inh; - - if (hModule == NULL || !LoadNtHeaderFromProcess(hProcess, hModule, &inh)) { - SetLastError(ERROR_INVALID_OPERATION); - return FALSE; - } - - if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC - && inh.FileHeader.Machine != 0) { - - bIs32BitExe = TRUE; - } - - DETOUR_TRACE((" 32BitExe=%d\n", bIs32BitExe)); - - if (hModule == NULL) { - SetLastError(ERROR_INVALID_OPERATION); - return FALSE; - } - - // Save the various headers for DetourRestoreAfterWith. - // - DETOUR_EXE_RESTORE der; - - if (!RecordExeRestore(hProcess, hModule, der)) { - return FALSE; - } - -#if defined(DETOURS_64BIT) - // Try to convert a neutral 32-bit managed binary to a 64-bit managed binary. - if (bIs32BitExe && !bIs32BitProcess) { - if (!der.pclr // Native binary - || (der.clr.Flags & COMIMAGE_FLAGS_ILONLY) == 0 // Or mixed-mode MSIL - || (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) != 0) { // Or 32BIT Required MSIL - - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (!UpdateFrom32To64(hProcess, hModule, -#if defined(DETOURS_X64) - IMAGE_FILE_MACHINE_AMD64, -#elif defined(DETOURS_IA64) - IMAGE_FILE_MACHINE_IA64, -#elif defined(DETOURS_ARM64) - IMAGE_FILE_MACHINE_ARM64, -#else -#error Must define one of DETOURS_X64 or DETOURS_IA64 or DETOURS_ARM64 on 64-bit. -#endif - der)) { - return FALSE; - } - bIs32BitExe = FALSE; - } -#endif // DETOURS_64BIT - - // Now decide if we can insert the detour. - -#if defined(DETOURS_32BIT) - if (bIs32BitProcess) { - // 32-bit native or 32-bit managed process on any platform. - if (!UpdateImports32(hProcess, hModule, rlpDlls, nDlls)) { - return FALSE; - } - } - else { - // 64-bit native or 64-bit managed process. - // - // Can't detour a 64-bit process with 32-bit code. - // Note: This happens for 32-bit PE binaries containing only - // manage code that have been marked as 64-bit ready. - // - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } -#elif defined(DETOURS_64BIT) - if (bIs32BitProcess || bIs32BitExe) { - // Can't detour a 32-bit process with 64-bit code. - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - else { - // 64-bit native or 64-bit managed process on any platform. - if (!UpdateImports64(hProcess, hModule, rlpDlls, nDlls)) { - return FALSE; - } - } -#else -#pragma Must define one of DETOURS_32BIT or DETOURS_64BIT. -#endif // DETOURS_64BIT - - /////////////////////////////////////////////////// Update the CLR header. - // - if (der.pclr != NULL) { - DETOUR_CLR_HEADER clr; - CopyMemory(&clr, &der.clr, sizeof(clr)); - clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag. - - DWORD dwProtect; - if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %lu\n", GetLastError())); - return FALSE; - } - - if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(clr) failed: %lu\n", GetLastError())); - return FALSE; - } - - if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %lu\n", GetLastError())); - return FALSE; - } - DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr)); - -#if DETOURS_64BIT - if (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) { // Is the 32BIT Required Flag set? - // X64 never gets here because the process appears as a WOW64 process. - // However, on IA64, it doesn't appear to be a WOW process. - DETOUR_TRACE(("CLR Requires 32-bit\n")); - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } -#endif // DETOURS_64BIT - } - - //////////////////////////////// Save the undo data to the target process. - // - if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); - return FALSE; - } - return TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// -BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) -{ - DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED); - PROCESS_INFORMATION pi; - BOOL fResult = FALSE; - - if (pfCreateProcessA == NULL) { - pfCreateProcessA = CreateProcessA; - } - - fResult = pfCreateProcessA(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwMyCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - &pi); - - if (lpProcessInformation != NULL) { - CopyMemory(lpProcessInformation, &pi, sizeof(pi)); - } - - if (!fResult) { - return FALSE; - } - - LPCSTR rlpDlls[2]; - DWORD nDlls = 0; - if (lpDllName != NULL) { - rlpDlls[nDlls++] = lpDllName; - } - - if (!DetourUpdateProcessWithDll(pi.hProcess, rlpDlls, nDlls)) { - TerminateProcess(pi.hProcess, ~0u); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(pi.hThread); - } - return TRUE; -} - - -BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) -{ - DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED); - PROCESS_INFORMATION pi; - - if (pfCreateProcessW == NULL) { - pfCreateProcessW = CreateProcessW; - } - - BOOL fResult = pfCreateProcessW(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwMyCreationFlags, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - &pi); - - if (lpProcessInformation) { - CopyMemory(lpProcessInformation, &pi, sizeof(pi)); - } - - if (!fResult) { - return FALSE; - } - - LPCSTR rlpDlls[2]; - DWORD nDlls = 0; - if (lpDllName != NULL) { - rlpDlls[nDlls++] = lpDllName; - } - - if (!DetourUpdateProcessWithDll(pi.hProcess, rlpDlls, nDlls)) { - TerminateProcess(pi.hProcess, ~0u); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(pi.hThread); - } - return TRUE; -} - -BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _In_reads_bytes_(cbData) LPCVOID pvData, - _In_ DWORD cbData) -{ - return DetourCopyPayloadToProcessEx(hProcess, rguid, pvData, cbData) != NULL; -} - -_Success_(return != NULL) -PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _In_reads_bytes_(cbData) LPCVOID pvData, - _In_ DWORD cbData) -{ - if (hProcess == NULL) { - SetLastError(ERROR_INVALID_HANDLE); - return NULL; - } - - DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) + - sizeof(IMAGE_NT_HEADERS) + - sizeof(IMAGE_SECTION_HEADER) + - sizeof(DETOUR_SECTION_HEADER) + - sizeof(DETOUR_SECTION_RECORD) + - cbData); - - PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal, - MEM_COMMIT, PAGE_READWRITE); - if (pbBase == NULL) { - DETOUR_TRACE(("VirtualAllocEx(%lu) failed: %lu\n", cbTotal, GetLastError())); - return NULL; - } - - // As you can see in the following code, - // the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file, - // so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer, - // pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree. - - PBYTE pbTarget = pbBase; - IMAGE_DOS_HEADER idh; - IMAGE_NT_HEADERS inh; - IMAGE_SECTION_HEADER ish; - DETOUR_SECTION_HEADER dsh; - DETOUR_SECTION_RECORD dsr; - SIZE_T cbWrote = 0; - - ZeroMemory(&idh, sizeof(idh)); - idh.e_magic = IMAGE_DOS_SIGNATURE; - idh.e_lfanew = sizeof(idh); - if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) || - cbWrote != sizeof(idh)) { - DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError())); - return NULL; - } - pbTarget += sizeof(idh); - - ZeroMemory(&inh, sizeof(inh)); - inh.Signature = IMAGE_NT_SIGNATURE; - inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader); - inh.FileHeader.Characteristics = IMAGE_FILE_DLL; - inh.FileHeader.NumberOfSections = 1; - inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; - if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) || - cbWrote != sizeof(inh)) { - return NULL; - } - pbTarget += sizeof(inh); - - ZeroMemory(&ish, sizeof(ish)); - memcpy(ish.Name, ".detour", sizeof(ish.Name)); - ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase); - ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) + - sizeof(DETOUR_SECTION_RECORD) + - cbData); - if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) || - cbWrote != sizeof(ish)) { - return NULL; - } - pbTarget += sizeof(ish); - - ZeroMemory(&dsh, sizeof(dsh)); - dsh.cbHeaderSize = sizeof(dsh); - dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE; - dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER); - dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) + - sizeof(DETOUR_SECTION_RECORD) + - cbData); - if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) || - cbWrote != sizeof(dsh)) { - return NULL; - } - pbTarget += sizeof(dsh); - - ZeroMemory(&dsr, sizeof(dsr)); - dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD); - dsr.nReserved = 0; - dsr.guid = rguid; - if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) || - cbWrote != sizeof(dsr)) { - return NULL; - } - pbTarget += sizeof(dsr); - - if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) || - cbWrote != cbData) { - return NULL; - } - - DETOUR_TRACE(("Copied %lu byte payload into target process at %p\n", - cbData, pbTarget)); - - SetLastError(NO_ERROR); - return pbTarget; -} - -static BOOL s_fSearchedForHelper = FALSE; -static PDETOUR_EXE_HELPER s_pHelper = NULL; - -VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, - _In_ HINSTANCE, - _In_ LPSTR, - _In_ INT) -{ - LPCSTR * rlpDlls = NULL; - DWORD Result = 9900; - DWORD cOffset = 0; - DWORD cSize = 0; - HANDLE hProcess = NULL; - - if (s_pHelper == NULL) { - DETOUR_TRACE(("DetourFinishHelperProcess called with s_pHelper = NULL.\n")); - Result = 9905; - goto Cleanup; - } - - hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid); - if (hProcess == NULL) { - DETOUR_TRACE(("OpenProcess(pid=%lu) failed: %lu\n", - s_pHelper->pid, GetLastError())); - Result = 9901; - goto Cleanup; - } - - rlpDlls = new NOTHROW LPCSTR [s_pHelper->nDlls]; - cSize = s_pHelper->cb - sizeof(DETOUR_EXE_HELPER); - for (DWORD n = 0; n < s_pHelper->nDlls; n++) { - size_t cchDest = 0; - HRESULT hr = StringCchLengthA(&s_pHelper->rDlls[cOffset], cSize - cOffset, &cchDest); - if (!SUCCEEDED(hr)) { - Result = 9902; - goto Cleanup; - } - - rlpDlls[n] = &s_pHelper->rDlls[cOffset]; - cOffset += (DWORD)cchDest + 1; - } - - if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) { - DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%lu) failed: %lu\n", - s_pHelper->pid, GetLastError())); - Result = 9903; - goto Cleanup; - } - Result = 0; - - Cleanup: - if (rlpDlls != NULL) { - delete[] rlpDlls; - rlpDlls = NULL; - } - - // Note: s_pHelper is allocated as part of injecting the payload in DetourCopyPayloadToProcess(..), - // it's a fake section and not data allocated by the system PE loader. - - // Delete the payload after execution to release the memory occupied by it - if (s_pHelper != NULL) { - DetourFreePayload(s_pHelper); - s_pHelper = NULL; - } - - ExitProcess(Result); -} - -BOOL WINAPI DetourIsHelperProcess(VOID) -{ - PVOID pvData; - DWORD cbData; - - if (s_fSearchedForHelper) { - return (s_pHelper != NULL); - } - - s_fSearchedForHelper = TRUE; - pvData = DetourFindPayloadEx(DETOUR_EXE_HELPER_GUID, &cbData); - - if (pvData == NULL || cbData < sizeof(DETOUR_EXE_HELPER)) { - return FALSE; - } - - s_pHelper = (PDETOUR_EXE_HELPER)pvData; - if (s_pHelper->cb < sizeof(*s_pHelper)) { - s_pHelper = NULL; - return FALSE; - } - - return TRUE; -} - -static -BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper, - _In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls) -{ - PDETOUR_EXE_HELPER Helper = NULL; - BOOL Result = FALSE; - _Field_range_(0, cSize - 4) DWORD cOffset = 0; - DWORD cSize = 4; - - if (pHelper == NULL) { - goto Cleanup; - } - *pHelper = NULL; - - if (nDlls < 1 || nDlls > 4096) { - SetLastError(ERROR_INVALID_PARAMETER); - goto Cleanup; - } - - for (DWORD n = 0; n < nDlls; n++) { - HRESULT hr; - size_t cchDest = 0; - - hr = StringCchLengthA(rlpDlls[n], 4096, &cchDest); - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - cSize += (DWORD)cchDest + 1; - } - - Helper = (PDETOUR_EXE_HELPER) new NOTHROW BYTE[sizeof(DETOUR_EXE_HELPER) + cSize]; - if (Helper == NULL) { - goto Cleanup; - } - - Helper->cb = sizeof(DETOUR_EXE_HELPER) + cSize; - Helper->pid = dwTargetPid; - Helper->nDlls = nDlls; - - for (DWORD n = 0; n < nDlls; n++) { - HRESULT hr; - size_t cchDest = 0; - - if (cOffset > 0x10000 || cSize > 0x10000 || cOffset + 2 >= cSize) { - goto Cleanup; - } - - if (cOffset + 2 >= cSize || cOffset + 65536 < cSize) { - goto Cleanup; - } - - _Analysis_assume_(cOffset + 1 < cSize); - _Analysis_assume_(cOffset < 0x10000); - _Analysis_assume_(cSize < 0x10000); - - PCHAR psz = &Helper->rDlls[cOffset]; - - hr = StringCchCopyA(psz, cSize - cOffset, rlpDlls[n]); - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - -// REVIEW 28020 The expression '1<=_Param_(2)& &_Param_(2)<=2147483647' is not true at this call. -// REVIEW 28313 Analysis will not proceed past this point because of annotation evaluation. The annotation expression *_Param_(3)<_Param_(2)&&*_Param_(3)<=stringLength$(_Param_(1)) cannot be true under any assumptions at this point in the program. -#pragma warning(suppress:28020 28313) - hr = StringCchLengthA(psz, cSize - cOffset, &cchDest); - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - // Replace "32." with "64." or "64." with "32." - - for (DWORD c = (DWORD)cchDest + 1; c > 3; c--) { -#if DETOURS_32BIT - if (psz[c - 3] == '3' && psz[c - 2] == '2' && psz[c - 1] == '.') { - psz[c - 3] = '6'; psz[c - 2] = '4'; - break; - } -#else - if (psz[c - 3] == '6' && psz[c - 2] == '4' && psz[c - 1] == '.') { - psz[c - 3] = '3'; psz[c - 2] = '2'; - break; - } -#endif - } - - cOffset += (DWORD)cchDest + 1; - } - - *pHelper = Helper; - Helper = NULL; - Result = TRUE; - - Cleanup: - if (Helper != NULL) { - delete[] (PBYTE)Helper; - Helper = NULL; - } - return Result; -} - -static -VOID WINAPI FreeExeHelper(PDETOUR_EXE_HELPER *pHelper) -{ - if (*pHelper != NULL) { - delete[] (PBYTE)*pHelper; - *pHelper = NULL; - } -} - -BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) -{ - return DetourProcessViaHelperDllsA(dwTargetPid, 1, &lpDllName, pfCreateProcessA); -} - - -BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) -{ - BOOL Result = FALSE; - PROCESS_INFORMATION pi; - STARTUPINFOA si; - CHAR szExe[MAX_PATH]; - CHAR szCommand[MAX_PATH]; - PDETOUR_EXE_HELPER helper = NULL; - HRESULT hr; - DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe)); - - DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls)); - if (nDlls < 1 || nDlls > 4096) { - SetLastError(ERROR_INVALID_PARAMETER); - goto Cleanup; - } - if (!AllocExeHelper(&helper, dwTargetPid, nDlls, rlpDlls)) { - goto Cleanup; - } - - if (nLen == 0 || nLen >= ARRAYSIZE(szExe)) { - goto Cleanup; - } - -#if DETOURS_OPTION_BITS -#if DETOURS_32BIT - hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\sysnative\\rundll32.exe"); -#else // !DETOURS_32BIT - hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\syswow64\\rundll32.exe"); -#endif // !DETOURS_32BIT -#else // DETOURS_OPTIONS_BITS - hr = StringCchCatA(szExe, ARRAYSIZE(szExe), "\\system32\\rundll32.exe"); -#endif // DETOURS_OPTIONS_BITS - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - //for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP")); - //so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before - hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), - "rundll32.exe \"%s\",#1", &helper->rDlls[0]); - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - DETOUR_TRACE(("DetourProcessViaHelperDlls(\"%hs\", \"%hs\")\n", szExe, szCommand)); - if (pfCreateProcessA(szExe, szCommand, NULL, NULL, FALSE, CREATE_SUSPENDED, - NULL, NULL, &si, &pi)) { - - if (!DetourCopyPayloadToProcess(pi.hProcess, - DETOUR_EXE_HELPER_GUID, - helper, helper->cb)) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); - TerminateProcess(pi.hProcess, ~0u); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - goto Cleanup; - } - - ResumeThread(pi.hThread); - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD dwResult = 500; - GetExitCodeProcess(pi.hProcess, &dwResult); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - if (dwResult != 0) { - DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult)); - goto Cleanup; - } - Result = TRUE; - } - else { - DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError())); - goto Cleanup; - } - - Cleanup: - FreeExeHelper(&helper); - return Result; -} - -BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) -{ - return DetourProcessViaHelperDllsW(dwTargetPid, 1, &lpDllName, pfCreateProcessW); -} - -BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) -{ - BOOL Result = FALSE; - PROCESS_INFORMATION pi; - STARTUPINFOW si; - WCHAR szExe[MAX_PATH]; - WCHAR szCommand[MAX_PATH]; - PDETOUR_EXE_HELPER helper = NULL; - HRESULT hr; - WCHAR szDllName[MAX_PATH]; - int cchWrittenWideChar; - DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe)); - - DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls)); - if (nDlls < 1 || nDlls > 4096) { - SetLastError(ERROR_INVALID_PARAMETER); - goto Cleanup; - } - if (!AllocExeHelper(&helper, dwTargetPid, nDlls, rlpDlls)) { - goto Cleanup; - } - - if (nLen == 0 || nLen >= ARRAYSIZE(szExe)) { - goto Cleanup; - } - -#if DETOURS_OPTION_BITS -#if DETOURS_32BIT - hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\sysnative\\rundll32.exe"); -#else // !DETOURS_32BIT - hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\syswow64\\rundll32.exe"); -#endif // !DETOURS_32BIT -#else // DETOURS_OPTIONS_BITS - hr = StringCchCatW(szExe, ARRAYSIZE(szExe), L"\\system32\\rundll32.exe"); -#endif // DETOURS_OPTIONS_BITS - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - //for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP")); - //so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before - - cchWrittenWideChar = MultiByteToWideChar(CP_ACP, 0, &helper->rDlls[0], -1, szDllName, ARRAYSIZE(szDllName)); - if (cchWrittenWideChar >= ARRAYSIZE(szDllName) || cchWrittenWideChar <= 0) { - goto Cleanup; - } - hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), - L"rundll32.exe \"%s\",#1", szDllName); - if (!SUCCEEDED(hr)) { - goto Cleanup; - } - - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - DETOUR_TRACE(("DetourProcessViaHelperDlls(\"%ls\", \"%ls\")\n", szExe, szCommand)); - if (pfCreateProcessW(szExe, szCommand, NULL, NULL, FALSE, CREATE_SUSPENDED, - NULL, NULL, &si, &pi)) { - - if (!DetourCopyPayloadToProcess(pi.hProcess, - DETOUR_EXE_HELPER_GUID, - helper, helper->cb)) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); - TerminateProcess(pi.hProcess, ~0u); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - goto Cleanup; - } - - ResumeThread(pi.hThread); - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD dwResult = 500; - GetExitCodeProcess(pi.hProcess, &dwResult); - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - if (dwResult != 0) { - DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult)); - goto Cleanup; - } - Result = TRUE; - } - else { - DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError())); - goto Cleanup; - } - - Cleanup: - FreeExeHelper(&helper); - return Result; -} - -BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) -{ - if (pfCreateProcessA == NULL) { - pfCreateProcessA = CreateProcessA; - } - - PROCESS_INFORMATION backup; - if (lpProcessInformation == NULL) { - lpProcessInformation = &backup; - ZeroMemory(&backup, sizeof(backup)); - } - - if (!pfCreateProcessA(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags | CREATE_SUSPENDED, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation)) { - return FALSE; - } - - LPCSTR szDll = lpDllName; - - if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, &szDll, 1) && - !DetourProcessViaHelperA(lpProcessInformation->dwProcessId, - lpDllName, - pfCreateProcessA)) { - - TerminateProcess(lpProcessInformation->hProcess, ~0u); - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(lpProcessInformation->hThread); - } - - if (lpProcessInformation == &backup) { - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - } - - return TRUE; -} - -BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) -{ - if (pfCreateProcessW == NULL) { - pfCreateProcessW = CreateProcessW; - } - - PROCESS_INFORMATION backup; - if (lpProcessInformation == NULL) { - lpProcessInformation = &backup; - ZeroMemory(&backup, sizeof(backup)); - } - - if (!pfCreateProcessW(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags | CREATE_SUSPENDED, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation)) { - return FALSE; - } - - - LPCSTR sz = lpDllName; - - if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, &sz, 1) && - !DetourProcessViaHelperW(lpProcessInformation->dwProcessId, - lpDllName, - pfCreateProcessW)) { - - TerminateProcess(lpProcessInformation->hProcess, ~0u); - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(lpProcessInformation->hThread); - } - - if (lpProcessInformation == &backup) { - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - } - return TRUE; -} - -BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA) -{ - if (pfCreateProcessA == NULL) { - pfCreateProcessA = CreateProcessA; - } - - PROCESS_INFORMATION backup; - if (lpProcessInformation == NULL) { - lpProcessInformation = &backup; - ZeroMemory(&backup, sizeof(backup)); - } - - if (!pfCreateProcessA(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags | CREATE_SUSPENDED, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation)) { - return FALSE; - } - - if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, rlpDlls, nDlls) && - !DetourProcessViaHelperDllsA(lpProcessInformation->dwProcessId, - nDlls, - rlpDlls, - pfCreateProcessA)) { - - TerminateProcess(lpProcessInformation->hProcess, ~0u); - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(lpProcessInformation->hThread); - } - - if (lpProcessInformation == &backup) { - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - } - - return TRUE; -} - -BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW) -{ - if (pfCreateProcessW == NULL) { - pfCreateProcessW = CreateProcessW; - } - - PROCESS_INFORMATION backup; - if (lpProcessInformation == NULL) { - lpProcessInformation = &backup; - ZeroMemory(&backup, sizeof(backup)); - } - - if (!pfCreateProcessW(lpApplicationName, - lpCommandLine, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags | CREATE_SUSPENDED, - lpEnvironment, - lpCurrentDirectory, - lpStartupInfo, - lpProcessInformation)) { - return FALSE; - } - - - if (!DetourUpdateProcessWithDll(lpProcessInformation->hProcess, rlpDlls, nDlls) && - !DetourProcessViaHelperDllsW(lpProcessInformation->dwProcessId, - nDlls, - rlpDlls, - pfCreateProcessW)) { - - TerminateProcess(lpProcessInformation->hProcess, ~0u); - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - return FALSE; - } - - if (!(dwCreationFlags & CREATE_SUSPENDED)) { - ResumeThread(lpProcessInformation->hThread); - } - - if (lpProcessInformation == &backup) { - CloseHandle(lpProcessInformation->hProcess); - CloseHandle(lpProcessInformation->hThread); - } - return TRUE; -} - -// -///////////////////////////////////////////////////////////////// End of File. diff --git a/NanaZip.Shared/Detours/detours.cpp b/NanaZip.Shared/Detours/detours.cpp deleted file mode 100644 index 7d0495d..0000000 --- a/NanaZip.Shared/Detours/detours.cpp +++ /dev/null @@ -1,2604 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Core Detours Functionality (detours.cpp of detours.lib) -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - - -//#define DETOUR_DEBUG 1 -#define DETOURS_INTERNAL -#include "detours.h" - -#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH -#error detours.h version mismatch -#endif - -#define NOTHROW - -////////////////////////////////////////////////////////////////////////////// -// - -#ifdef _DEBUG -extern "C" IMAGE_DOS_HEADER __ImageBase; -int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg) -{ - int nRet = 0; - DWORD dwLastError = GetLastError(); - CHAR szModuleNameWithFunctionName[MAX_PATH * 2]; - szModuleNameWithFunctionName[0] = 0; - GetModuleFileNameA((HMODULE)&__ImageBase, szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName)); - StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), ",", ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1); - StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), FunctionName, ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1); - SetLastError(dwLastError); - nRet = _CrtDbgReport(reportType, filename, linenumber, szModuleNameWithFunctionName, msg); - SetLastError(dwLastError); - return nRet; -} -#endif// _DEBUG - -////////////////////////////////////////////////////////////////////////////// -// -struct _DETOUR_ALIGN -{ - BYTE obTarget : 3; - BYTE obTrampoline : 5; -}; - -C_ASSERT(sizeof(_DETOUR_ALIGN) == 1); - -////////////////////////////////////////////////////////////////////////////// -// -// Region reserved for system DLLs, which cannot be used for trampolines. -// -static PVOID s_pSystemRegionLowerBound = (PVOID)(ULONG_PTR)0x70000000; -static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000; - -////////////////////////////////////////////////////////////////////////////// -// -static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) -{ - MEMORY_BASIC_INFORMATION mbi; - VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); - __try { - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; - if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - return false; - } - - PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + - pDosHeader->e_lfanew); - if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { - return false; - } - - if (pbAddress >= ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && - pbAddress < ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { - return true; - } - } -#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.") - __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? - EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { - return false; - } - return false; -} - -inline ULONG_PTR detour_2gb_below(ULONG_PTR address) -{ - return (address > (ULONG_PTR)0x7ff80000) ? address - 0x7ff80000 : 0x80000; -} - -inline ULONG_PTR detour_2gb_above(ULONG_PTR address) -{ -#if defined(DETOURS_64BIT) - return (address < (ULONG_PTR)0xffffffff80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfffffffffff80000; -#else - return (address < (ULONG_PTR)0x80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfff80000; -#endif -} - -///////////////////////////////////////////////////////////////////////// X86. -// -#ifdef DETOURS_X86 - -struct _DETOUR_TRAMPOLINE -{ - BYTE rbCode[30]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[22]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 72); - -enum { - SIZE_OF_JMP = 5 -}; - -inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 5; - *pbCode++ = 0xE9; // jmp +imm32 - *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) -{ - *pbCode++ = 0xff; // jmp [+imm32] - *pbCode++ = 0x25; - *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal); - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - *pbCode++ = 0xcc; // brk; - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - - // Then, skip over a patch jump - if (pbCode[0] == 0xeb) { // jmp +imm8 - PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); - pbCode = pbNew; - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - // Finally, skip over a long jump if it is the target of the patch jump. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); - - // And, within +/- 2GB of relative jmp targets. - if (pbCode[0] == 0xe9) { // jmp +imm32 - PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi)); - } - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - if (pbCode[0] == 0xeb || // jmp +imm8 - pbCode[0] == 0xe9 || // jmp +imm32 - pbCode[0] == 0xe0 || // jmp eax - pbCode[0] == 0xc2 || // ret +imm8 - pbCode[0] == 0xc3 || // ret - pbCode[0] == 0xcc) { // brk - return TRUE; - } - else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret - return TRUE; - } - else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - return TRUE; - } - else if ((pbCode[0] == 0x26 || // jmp es: - pbCode[0] == 0x2e || // jmp cs: - pbCode[0] == 0x36 || // jmp ss: - pbCode[0] == 0x3e || // jmp ds: - pbCode[0] == 0x64 || // jmp fs: - pbCode[0] == 0x65) && // jmp gs: - pbCode[1] == 0xff && // jmp [+imm32] - pbCode[2] == 0x25) { - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // 1-byte through 11-byte NOPs. - if (pbCode[0] == 0x90) { - return 1; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { - return 2; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { - return 3; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && - pbCode[3] == 0x00) { - return 4; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && - pbCode[3] == 0x00 && pbCode[4] == 0x00) { - return 5; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { - return 6; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00) { - return 7; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00) { - return 8; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { - return 9; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && - pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00) { - return 10; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && - pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00 && pbCode[10] == 0x00) { - return 11; - } - - // int 3. - if (pbCode[0] == 0xcc) { - return 1; - } - return 0; -} - -#endif // DETOURS_X86 - -///////////////////////////////////////////////////////////////////////// X64. -// -#ifdef DETOURS_X64 - -struct _DETOUR_TRAMPOLINE -{ - // An X64 instuction can be 15 bytes long. - // In practice 11 seems to be the limit. - BYTE rbCode[30]; // target code + jmp to pbRemain. - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[30]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. - BYTE rbCodeIn[8]; // jmp [pbDetour] -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 96); - -enum { - SIZE_OF_JMP = 5 -}; - -inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 5; - *pbCode++ = 0xE9; // jmp +imm32 - *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 6; - *pbCode++ = 0xff; // jmp [+imm32] - *pbCode++ = 0x25; - *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - *pbCode++ = 0xcc; // brk; - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - - // Then, skip over a patch jump - if (pbCode[0] == 0xeb) { // jmp +imm8 - PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); - pbCode = pbNew; - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - // Finally, skip over a long jump if it is the target of the patch jump. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); - - // And, within +/- 2GB of relative jmp vectors. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - PBYTE pbNew = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", (PVOID)lo, pbCode, (PVOID)hi)); - } - // And, within +/- 2GB of relative jmp targets. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi)); - } - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - if (pbCode[0] == 0xeb || // jmp +imm8 - pbCode[0] == 0xe9 || // jmp +imm32 - pbCode[0] == 0xe0 || // jmp eax - pbCode[0] == 0xc2 || // ret +imm8 - pbCode[0] == 0xc3 || // ret - pbCode[0] == 0xcc) { // brk - return TRUE; - } - else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret - return TRUE; - } - else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - return TRUE; - } - else if ((pbCode[0] == 0x26 || // jmp es: - pbCode[0] == 0x2e || // jmp cs: - pbCode[0] == 0x36 || // jmp ss: - pbCode[0] == 0x3e || // jmp ds: - pbCode[0] == 0x64 || // jmp fs: - pbCode[0] == 0x65) && // jmp gs: - pbCode[1] == 0xff && // jmp [+imm32] - pbCode[2] == 0x25) { - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // 1-byte through 11-byte NOPs. - if (pbCode[0] == 0x90) { - return 1; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { - return 2; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { - return 3; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && - pbCode[3] == 0x00) { - return 4; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && - pbCode[3] == 0x00 && pbCode[4] == 0x00) { - return 5; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { - return 6; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00) { - return 7; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00) { - return 8; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { - return 9; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && - pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00) { - return 10; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && - pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00 && pbCode[10] == 0x00) { - return 11; - } - - // int 3. - if (pbCode[0] == 0xcc) { - return 1; - } - return 0; -} - -#endif // DETOURS_X64 - -//////////////////////////////////////////////////////////////////////// IA64. -// -#ifdef DETOURS_IA64 - -struct _DETOUR_TRAMPOLINE -{ - // On the IA64, a trampoline is used for both incoming and outgoing calls. - // - // The trampoline contains the following bundles for the outgoing call: - // movl gp=target_gp; - // - // brl target_code; - // - // The trampoline contains the following bundles for the incoming call: - // alloc r41=ar.pfs, b, 0, 8, 0 - // mov r40=rp - // - // adds r50=0, r39 - // adds r49=0, r38 - // adds r48=0, r37 ;; - // - // adds r47=0, r36 - // adds r46=0, r35 - // adds r45=0, r34 - // - // adds r44=0, r33 - // adds r43=0, r32 - // adds r42=0, gp ;; - // - // movl gp=ffffffff`ffffffff ;; - // - // brl.call.sptk.few rp=disas!TestCodes+20e0 (00000000`00404ea0) ;; - // - // adds gp=0, r42 - // mov rp=r40, +0 ;; - // mov.i ar.pfs=r41 - // - // br.ret.sptk.many rp ;; - // - // This way, we only have to relocate a single bundle. - // - // The complicated incoming trampoline is required because we have to - // create an additional stack frame so that we save and restore the gp. - // We must do this because gp is a caller-saved register, but not saved - // if the caller thinks the target is in the same DLL, which changes - // when we insert a detour. - // - DETOUR_IA64_BUNDLE bMovlTargetGp; // Bundle which sets target GP - BYTE rbCode[sizeof(DETOUR_IA64_BUNDLE)]; // moved bundle. - DETOUR_IA64_BUNDLE bBrlRemainEip; // Brl to pbRemain - // This must be adjacent to bBranchIslands. - - // Each instruction in the moved bundle could be a IP-relative chk or branch or call. - // Any such instructions are changed to point to a brl in bBranchIslands. - // This must be adjacent to bBrlRemainEip -- see "pbPool". - DETOUR_IA64_BUNDLE bBranchIslands[DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE]; - - // Target of brl inserted in target function - DETOUR_IA64_BUNDLE bAllocFrame; // alloc frame - DETOUR_IA64_BUNDLE bSave37to39; // save r37, r38, r39. - DETOUR_IA64_BUNDLE bSave34to36; // save r34, r35, r36. - DETOUR_IA64_BUNDLE bSaveGPto33; // save gp, r32, r33. - DETOUR_IA64_BUNDLE bMovlDetourGp; // set detour GP. - DETOUR_IA64_BUNDLE bCallDetour; // call detour. - DETOUR_IA64_BUNDLE bPopFrameGp; // pop frame and restore gp. - DETOUR_IA64_BUNDLE bReturn; // return to caller. - - PLABEL_DESCRIPTOR pldTrampoline; - - BYTE rbRestore[sizeof(DETOUR_IA64_BUNDLE)]; // original target bundle. - BYTE cbRestore; // size of original target code. - BYTE cbCode; // size of moved target code. - _DETOUR_ALIGN rAlign[14]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. - PPLABEL_DESCRIPTOR ppldDetour; // [pbDetour,gpDetour] - PPLABEL_DESCRIPTOR ppldTarget; // [pbTarget,gpDetour] -}; - -C_ASSERT(sizeof(DETOUR_IA64_BUNDLE) == 16); -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 256 + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * 16); - -enum { - SIZE_OF_JMP = sizeof(DETOUR_IA64_BUNDLE) -}; - -inline PBYTE detour_skip_jmp(PBYTE pPointer, PVOID *ppGlobals) -{ - PBYTE pGlobals = NULL; - PBYTE pbCode = NULL; - - if (pPointer != NULL) { - PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)pPointer; - pbCode = (PBYTE)ppld->EntryPoint; - pGlobals = (PBYTE)ppld->GlobalPointer; - } - if (ppGlobals != NULL) { - *ppGlobals = pGlobals; - } - if (pbCode == NULL) { - return NULL; - } - - DETOUR_IA64_BUNDLE *pb = (DETOUR_IA64_BUNDLE *)pbCode; - - // IA64 Local Import Jumps look like: - // addl r2=ffffffff`ffe021c0, gp ;; - // ld8 r2=[r2] - // nop.i 0 ;; - // - // ld8 r3=[r2], 8 ;; - // ld8 gp=[r2] - // mov b6=r3, +0 - // - // nop.m 0 - // nop.i 0 - // br.cond.sptk.few b6 - // - - // 002024000200100b - if ((pb[0].wide[0] & 0xfffffc000603ffff) == 0x002024000200100b && - pb[0].wide[1] == 0x0004000000203008 && - pb[1].wide[0] == 0x001014180420180a && - pb[1].wide[1] == 0x07000830c0203008 && - pb[2].wide[0] == 0x0000000100000010 && - pb[2].wide[1] == 0x0080006000000200) { - - ULONG64 offset = - ((pb[0].wide[0] & 0x0000000001fc0000) >> 18) | // imm7b - ((pb[0].wide[0] & 0x000001ff00000000) >> 25) | // imm9d - ((pb[0].wide[0] & 0x00000000f8000000) >> 11); // imm5c - if (pb[0].wide[0] & 0x0000020000000000) { // sign - offset |= 0xffffffffffe00000; - } - PBYTE pbTarget = pGlobals + offset; - DETOUR_TRACE(("%p: potential import jump, target=%p\n", pb, pbTarget)); - - if (detour_is_imported(pbCode, pbTarget) && *(PBYTE*)pbTarget != NULL) { - DETOUR_TRACE(("%p: is import jump, label=%p\n", pb, *(PBYTE *)pbTarget)); - - PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)*(PBYTE *)pbTarget; - pbCode = (PBYTE)ppld->EntryPoint; - pGlobals = (PBYTE)ppld->GlobalPointer; - if (ppGlobals != NULL) { - *ppGlobals = pGlobals; - } - } - } - return pbCode; -} - - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - (void)pbCode; - *ppLower = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0x0000000000080000; - *ppUpper = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0xfffffffffff80000; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - // Routine not needed on IA64. - (void)pbCode; - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // Routine not needed on IA64. - (void)pbCode; - return 0; -} - -#endif // DETOURS_IA64 - -#ifdef DETOURS_ARM - -struct _DETOUR_TRAMPOLINE -{ - // A Thumb-2 instruction can be 2 or 4 bytes long. - BYTE rbCode[62]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[22]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 104); - -enum { - SIZE_OF_JMP = 8 -}; - -inline PBYTE align4(PBYTE pValue) -{ - return (PBYTE)(((ULONG)pValue) & ~(ULONG)3u); -} - -inline ULONG fetch_thumb_opcode(PBYTE pbCode) -{ - ULONG Opcode = *(UINT16 *)&pbCode[0]; - if (Opcode >= 0xe800) { - Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2]; - } - return Opcode; -} - -inline void write_thumb_opcode(PBYTE &pbCode, ULONG Opcode) -{ - if (Opcode >= 0x10000) { - *((UINT16*&)pbCode)++ = Opcode >> 16; - } - *((UINT16*&)pbCode)++ = (UINT16)Opcode; -} - -PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) -{ - PBYTE pbLiteral; - if (ppPool != NULL) { - *ppPool = *ppPool - 4; - pbLiteral = *ppPool; - } - else { - pbLiteral = align4(pbCode + 6); - } - - *((PBYTE*&)pbLiteral) = DETOURS_PBYTE_TO_PFUNC(pbJmpVal); - LONG delta = pbLiteral - align4(pbCode + 4); - - write_thumb_opcode(pbCode, 0xf8dff000 | delta); // LDR PC,[PC+n] - - if (ppPool == NULL) { - if (((ULONG)pbCode & 2) != 0) { - write_thumb_opcode(pbCode, 0xdefe); // BREAK - } - pbCode += 4; - } - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - write_thumb_opcode(pbCode, 0xdefe); - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // Skip over the import jump if there is one. - pbCode = (PBYTE)DETOURS_PFUNC_TO_PBYTE(pbCode); - ULONG Opcode = fetch_thumb_opcode(pbCode); - - if ((Opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx - ULONG Opcode2 = fetch_thumb_opcode(pbCode+4); - - if ((Opcode2 & 0xfbf08f00) == 0xf2c00c00) { // movt r12,#xxxx - ULONG Opcode3 = fetch_thumb_opcode(pbCode+8); - if (Opcode3 == 0xf8dcf000) { // ldr pc,[r12] - PBYTE pbTarget = (PBYTE)(((Opcode2 << 12) & 0xf7000000) | - ((Opcode2 << 1) & 0x08000000) | - ((Opcode2 << 16) & 0x00ff0000) | - ((Opcode >> 4) & 0x0000f700) | - ((Opcode >> 15) & 0x00000800) | - ((Opcode >> 0) & 0x000000ff)); - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(PBYTE *)pbTarget; - pbNew = DETOURS_PFUNC_TO_PBYTE(pbNew); - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - return pbNew; - } - } - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - ULONG Opcode = fetch_thumb_opcode(pbCode); - if ((Opcode & 0xffffff87) == 0x4700 || // bx - (Opcode & 0xf800d000) == 0xf0009000) { // b - return TRUE; - } - if ((Opcode & 0xffff8000) == 0xe8bd8000) { // pop {...,pc} - __debugbreak(); - return TRUE; - } - if ((Opcode & 0xffffff00) == 0x0000bd00) { // pop {...,pc} - __debugbreak(); - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - if (pbCode[0] == 0x00 && pbCode[1] == 0xbf) { // nop. - return 2; - } - if (pbCode[0] == 0x00 && pbCode[1] == 0x00) { // zero-filled padding. - return 2; - } - return 0; -} - -#endif // DETOURS_ARM - -#ifdef DETOURS_ARM64 - -struct _DETOUR_TRAMPOLINE -{ - // An ARM64 instruction is 4 bytes long. - // - // The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump - // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. - // - // Copied instructions can expand. - // - // The scheme using MovImmediate can cause an instruction - // to grow as much as 6 times. - // That would be Bcc or Tbz with a large address space: - // 4 instructions to form immediate - // inverted tbz/bcc - // br - // - // An expansion of 4 is not uncommon -- bl/blr and small address space: - // 3 instructions to form immediate - // br or brl - // - // A theoretical maximum for rbCode is thefore 4*4*6 + 16 = 112 (another 16 for jmp to pbRemain). - // - // With literals, the maximum expansion is 5, including the literals: 4*4*5 + 16 = 96. - // - // The number is rounded up to 128. m_rbScratchDst should match this. - // - BYTE rbCode[128]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak[3]; // padding to make debugging easier. - BYTE rbRestore[24]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak[3]; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 184); - -enum { - SIZE_OF_JMP = 12 -}; - -inline ULONG fetch_opcode(PBYTE pbCode) -{ - return *(ULONG *)pbCode; -} - -inline void write_opcode(PBYTE &pbCode, ULONG Opcode) -{ - *(ULONG *)pbCode = Opcode; - pbCode += 4; -} - -struct ARM64_INDIRECT_JMP { - struct { - ULONG Rd : 5; - ULONG immhi : 19; - ULONG iop : 5; - ULONG immlo : 2; - ULONG op : 1; - } ardp; - - struct { - ULONG Rt : 5; - ULONG Rn : 5; - ULONG imm : 12; - ULONG opc : 2; - ULONG iop1 : 2; - ULONG V : 1; - ULONG iop2 : 3; - ULONG size : 2; - } ldr; - - ULONG br; -}; - -#pragma warning(push) -#pragma warning(disable:4201) - -union ARM64_INDIRECT_IMM { - struct { - ULONG64 pad : 12; - ULONG64 adrp_immlo : 2; - ULONG64 adrp_immhi : 19; - }; - - LONG64 value; -}; - -#pragma warning(pop) - -PBYTE detour_gen_jmp_indirect(BYTE *pbCode, ULONG64 *pbJmpVal) -{ - // adrp x17, [jmpval] - // ldr x17, [x17, jmpval] - // br x17 - - struct ARM64_INDIRECT_JMP *pIndJmp; - union ARM64_INDIRECT_IMM jmpIndAddr; - - jmpIndAddr.value = (((LONG64)pbJmpVal) & 0xFFFFFFFFFFFFF000) - - (((LONG64)pbCode) & 0xFFFFFFFFFFFFF000); - - pIndJmp = (struct ARM64_INDIRECT_JMP *)pbCode; - pbCode = (BYTE *)(pIndJmp + 1); - - pIndJmp->ardp.Rd = 17; - pIndJmp->ardp.immhi = jmpIndAddr.adrp_immhi; - pIndJmp->ardp.iop = 0x10; - pIndJmp->ardp.immlo = jmpIndAddr.adrp_immlo; - pIndJmp->ardp.op = 1; - - pIndJmp->ldr.Rt = 17; - pIndJmp->ldr.Rn = 17; - pIndJmp->ldr.imm = (((ULONG64)pbJmpVal) & 0xFFF) / 8; - pIndJmp->ldr.opc = 1; - pIndJmp->ldr.iop1 = 1; - pIndJmp->ldr.V = 0; - pIndJmp->ldr.iop2 = 7; - pIndJmp->ldr.size = 3; - - pIndJmp->br = 0xD61F0220; - - return pbCode; -} - -PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) -{ - PBYTE pbLiteral; - if (ppPool != NULL) { - *ppPool = *ppPool - 8; - pbLiteral = *ppPool; - } - else { - pbLiteral = pbCode + 8; - } - - *((PBYTE*&)pbLiteral) = pbJmpVal; - LONG delta = (LONG)(pbLiteral - pbCode); - - write_opcode(pbCode, 0x58000011 | ((delta / 4) << 5)); // LDR X17,[PC+n] - write_opcode(pbCode, 0xd61f0000 | (17 << 5)); // BR X17 - - if (ppPool == NULL) { - pbCode += 8; - } - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - write_opcode(pbCode, 0xd4100000 | (0xf000 << 5)); - } - return pbCode; -} - -inline INT64 detour_sign_extend(UINT64 value, UINT bits) -{ - const UINT left = 64 - bits; - const INT64 m1 = -1; - const INT64 wide = (INT64)(value << left); - const INT64 sign = (wide < 0) ? (m1 << left) : 0; - return value | sign; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // Skip over the import jump if there is one. - pbCode = (PBYTE)pbCode; - ULONG Opcode = fetch_opcode(pbCode); - - if ((Opcode & 0x9f00001f) == 0x90000010) { // adrp x16, IAT - ULONG Opcode2 = fetch_opcode(pbCode + 4); - - if ((Opcode2 & 0xffe003ff) == 0xf9400210) { // ldr x16, [x16, IAT] - ULONG Opcode3 = fetch_opcode(pbCode + 8); - - if (Opcode3 == 0xd61f0200) { // br x16 - -/* https://static.docs.arm.com/ddi0487/bb/DDI0487B_b_armv8_arm.pdf - The ADRP instruction shifts a signed, 21-bit immediate left by 12 bits, adds it to the value of the program counter with - the bottom 12 bits cleared to zero, and then writes the result to a general-purpose register. This permits the - calculation of the address at a 4KB aligned memory region. In conjunction with an ADD (immediate) instruction, or - a Load/Store instruction with a 12-bit immediate offset, this allows for the calculation of, or access to, any address - within +/- 4GB of the current PC. - -PC-rel. addressing - This section describes the encoding of the PC-rel. addressing instruction class. The encodings in this section are - decoded from Data Processing -- Immediate on page C4-226. - Add/subtract (immediate) - This section describes the encoding of the Add/subtract (immediate) instruction class. The encodings in this section - are decoded from Data Processing -- Immediate on page C4-226. - Decode fields - Instruction page - op - 0 ADR - 1 ADRP - -C6.2.10 ADRP - Form PC-relative address to 4KB page adds an immediate value that is shifted left by 12 bits, to the PC value to - form a PC-relative address, with the bottom 12 bits masked out, and writes the result to the destination register. - ADRP ,