Update detours library.

This commit is contained in:
Mr_Goldberg 2020-05-20 18:40:59 -04:00
parent 3b3dc98b3a
commit 7039d10159
No known key found for this signature in database
GPG key ID: 8597D87419DEF278
7 changed files with 308 additions and 176 deletions

View file

@ -7,34 +7,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// //
#if _MSC_VER >= 1900
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#include <stddef.h>
#pragma warning(push)
#if _MSC_VER > 1400
#pragma warning(disable:6102 6103) // /analyze warnings
#endif
#include <strsafe.h>
#pragma warning(pop)
// #define DETOUR_DEBUG 1 // #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL #define DETOURS_INTERNAL
#include "detours.h" #include "detours.h"
#include <stddef.h>
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch #error detours.h version mismatch
#endif #endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
#define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] #define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
#define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] #define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]

View file

@ -7,33 +7,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// //
#pragma warning(disable:4068) // unknown pragma (suppress)
#if _MSC_VER >= 1900
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#if (_MSC_VER < 1299)
#pragma warning(disable: 4710)
#endif
//#define DETOUR_DEBUG 1 //#define DETOUR_DEBUG 1
#define DETOURS_INTERNAL #define DETOURS_INTERNAL
#include "detours.h" #include "detours.h"
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch #error detours.h version mismatch
#endif #endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
#define NOTHROW #define NOTHROW
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -880,7 +862,8 @@ struct _DETOUR_TRAMPOLINE
{ {
// An ARM64 instruction is 4 bytes long. // An ARM64 instruction is 4 bytes long.
// //
// The overwrite is always 2 instructions plus a literal, so 16 bytes, 4 instructions. // 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. // Copied instructions can expand.
// //
@ -915,7 +898,7 @@ struct _DETOUR_TRAMPOLINE
C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 184); C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 184);
enum { enum {
SIZE_OF_JMP = 16 SIZE_OF_JMP = 12
}; };
inline ULONG fetch_opcode(PBYTE pbCode) inline ULONG fetch_opcode(PBYTE pbCode)
@ -929,6 +912,79 @@ inline void write_opcode(PBYTE &pbCode, ULONG Opcode)
pbCode += 4; 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 detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal)
{ {
PBYTE pbLiteral; PBYTE pbLiteral;
@ -995,7 +1051,7 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
the bottom 12 bits cleared to zero, and then writes the result to a general-purpose register. This permits the 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 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 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. within +/- 4GB of the current PC.
PC-rel. addressing PC-rel. addressing
This section describes the encoding of the PC-rel. addressing instruction class. The encodings in this section are This section describes the encoding of the PC-rel. addressing instruction class. The encodings in this section are
@ -1062,7 +1118,10 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
PDETOUR_TRAMPOLINE *ppLower, PDETOUR_TRAMPOLINE *ppLower,
PDETOUR_TRAMPOLINE *ppUpper) PDETOUR_TRAMPOLINE *ppUpper)
{ {
// We have to place trampolines within +/- 2GB of code. // The encoding used by detour_gen_jmp_indirect actually enables a
// displacement of +/- 4GiB. In the future, this could be changed to
// reflect that. For now, just reuse the x86 logic which is plenty.
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode);
DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi));
@ -1250,6 +1309,65 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
return NULL; return NULL;
} }
static PVOID detour_alloc_trampoline_allocate_new(PBYTE pbTarget,
PDETOUR_TRAMPOLINE pLo,
PDETOUR_TRAMPOLINE pHi)
{
PVOID pbTry = NULL;
// NB: We must always also start the search at an offset from pbTarget
// in order to maintain ASLR entropy.
#if defined(DETOURS_64BIT)
// Try looking 1GB below or lower.
if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget - 0x40000000);
}
// Try looking 1GB above or higher.
if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
pbTry = detour_alloc_region_from_lo(pbTarget + 0x40000000, (PBYTE)pHi);
}
// Try looking 1GB below or higher.
if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
pbTry = detour_alloc_region_from_lo(pbTarget - 0x40000000, pbTarget);
}
// Try looking 1GB above or lower.
if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
pbTry = detour_alloc_region_from_hi(pbTarget, pbTarget + 0x40000000);
}
#endif
// Try anything below.
if (pbTry == NULL) {
pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget);
}
// try anything above.
if (pbTry == NULL) {
pbTry = detour_alloc_region_from_lo(pbTarget, (PBYTE)pHi);
}
return pbTry;
}
PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
_Out_ PDWORD pcbAllocatedSize)
{
PDETOUR_TRAMPOLINE pLo;
PDETOUR_TRAMPOLINE pHi;
detour_find_jmp_bounds((PBYTE)pbTarget, &pLo, &pHi);
PVOID pbNewlyAllocated =
detour_alloc_trampoline_allocate_new((PBYTE)pbTarget, pLo, pHi);
if (pbNewlyAllocated == NULL) {
DETOUR_TRACE(("Couldn't find available memory region!\n"));
*pcbAllocatedSize = 0;
return NULL;
}
*pcbAllocatedSize = DETOUR_REGION_SIZE;
return pbNewlyAllocated;
}
static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget) static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
{ {
// We have to place trampolines within +/- 2GB of target. // We have to place trampolines within +/- 2GB of target.
@ -1294,41 +1412,10 @@ static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
// Round pbTarget down to 64KB block. // Round pbTarget down to 64KB block.
pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff); pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff);
PVOID pbTry = NULL; PVOID pbNewlyAllocated =
detour_alloc_trampoline_allocate_new(pbTarget, pLo, pHi);
// NB: We must always also start the search at an offset from pbTarget if (pbNewlyAllocated != NULL) {
// in order to maintain ASLR entropy. s_pRegion = (DETOUR_REGION*)pbNewlyAllocated;
#if defined(DETOURS_64BIT)
// Try looking 1GB below or lower.
if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget - 0x40000000);
}
// Try looking 1GB above or higher.
if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
pbTry = detour_alloc_region_from_lo(pbTarget + 0x40000000, (PBYTE)pHi);
}
// Try looking 1GB below or higher.
if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
pbTry = detour_alloc_region_from_lo(pbTarget - 0x40000000, pbTarget);
}
// Try looking 1GB above or lower.
if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
pbTry = detour_alloc_region_from_hi(pbTarget, pbTarget + 0x40000000);
}
#endif
// Try anything below.
if (pbTry == NULL) {
pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget);
}
// try anything above.
if (pbTry == NULL) {
pbTry = detour_alloc_region_from_lo(pbTarget, (PBYTE)pHi);
}
if (pbTry != NULL) {
s_pRegion = (DETOUR_REGION*)pbTry;
s_pRegion->dwSignature = DETOUR_REGION_SIGNATURE; s_pRegion->dwSignature = DETOUR_REGION_SIGNATURE;
s_pRegion->pFree = NULL; s_pRegion->pFree = NULL;
s_pRegion->pNext = s_pRegions; s_pRegion->pNext = s_pRegions;
@ -1655,7 +1742,7 @@ LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer)
#endif // DETOURS_ARM #endif // DETOURS_ARM
#ifdef DETOURS_ARM64 #ifdef DETOURS_ARM64
PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, NULL, o->pTrampoline->pbDetour); PBYTE pbCode = detour_gen_jmp_indirect(o->pbTarget, (ULONG64*)&(o->pTrampoline->pbDetour));
pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain); pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain);
*o->ppbPointer = o->pTrampoline->rbCode; *o->ppbPointer = o->pTrampoline->rbCode;
UNREFERENCED_PARAMETER(pbCode); UNREFERENCED_PARAMETER(pbCode);

View file

@ -16,6 +16,34 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
#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
#include <windows.h>
#if (_MSC_VER < 1310)
#else
#pragma warning(push)
#if _MSC_VER > 1400
#pragma warning(disable:6102 6103) // /analyze warnings
#endif
#include <strsafe.h>
#pragma warning(pop)
#endif
#endif // DETOURS_INTERNAL
//////////////////////////////////////////////////////////////////////////////
//
#undef DETOURS_X64 #undef DETOURS_X64
#undef DETOURS_X86 #undef DETOURS_X86
#undef DETOURS_IA64 #undef DETOURS_IA64
@ -61,7 +89,12 @@
//#define DETOURS_OPTION_BITS 32 //#define DETOURS_OPTION_BITS 32
#endif #endif
#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) /////////////////////////////////////////////////////////////// Helper Macros.
//
#define DETOURS_STRINGIFY_(x) #x
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
#define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -387,7 +420,6 @@ typedef struct _DETOUR_EXE_RESTORE
#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this #ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this
BYTE raw[sizeof(IMAGE_NT_HEADERS64) + BYTE raw[sizeof(IMAGE_NT_HEADERS64) +
sizeof(IMAGE_SECTION_HEADER) * 32]; sizeof(IMAGE_SECTION_HEADER) * 32];
C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == 0x108);
#else #else
BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32]; BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32];
#endif #endif
@ -396,6 +428,10 @@ typedef struct _DETOUR_EXE_RESTORE
} DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; } 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. // The size can change, but assert for clarity due to the muddying #ifdefs.
#ifdef _WIN64 #ifdef _WIN64
C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x688); C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x688);
@ -431,11 +467,6 @@ typedef struct _DETOUR_EXE_HELPER
0,\ 0,\
} }
/////////////////////////////////////////////////////////////// Helper Macros.
//
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
#define DETOURS_STRINGIFY_(x) #x
///////////////////////////////////////////////////////////// Binary Typedefs. ///////////////////////////////////////////////////////////// Binary Typedefs.
// //
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(
@ -523,6 +554,8 @@ PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
_Out_opt_ LONG *plExtra); _Out_opt_ LONG *plExtra);
BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
_In_ BOOL fLimitReferencesToModule); _In_ BOOL fLimitReferencesToModule);
PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
_Out_ PDWORD pcbAllocatedSize);
///////////////////////////////////////////////////// Loaded Binary Functions. ///////////////////////////////////////////////////// Loaded Binary Functions.
// //

View file

@ -14,8 +14,8 @@
#include <detours.h> #include <detours.h>
#else #else
#ifndef DETOURS_STRINGIFY #ifndef DETOURS_STRINGIFY
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
#define DETOURS_STRINGIFY_(x) #x #define DETOURS_STRINGIFY_(x) #x
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
#endif #endif
#define VER_FILEFLAGSMASK 0x3fL #define VER_FILEFLAGSMASK 0x3fL
@ -24,4 +24,4 @@
#define VER_FILETYPE 0x00000002L #define VER_FILETYPE 0x00000002L
#define VER_FILESUBTYPE 0x00000000L #define VER_FILESUBTYPE 0x00000000L
#endif #endif
#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) #define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS)

View file

@ -7,28 +7,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// //
#if _MSC_VER >= 1900
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#include <limits.h>
// #define DETOUR_DEBUG 1 // #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL #define DETOURS_INTERNAL
#include "detours.h" #include "detours.h"
#include <limits.h>
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch #error detours.h version mismatch
#endif #endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
#undef ASSERT #undef ASSERT
#define ASSERT(x) #define ASSERT(x)
@ -260,6 +247,11 @@ class CDetourDis
#define ENTRY_CopyFF ENTRY_DataIgnored &CDetourDis::CopyFF #define ENTRY_CopyFF ENTRY_DataIgnored &CDetourDis::CopyFF
#define ENTRY_CopyVex2 ENTRY_DataIgnored &CDetourDis::CopyVex2 #define ENTRY_CopyVex2 ENTRY_DataIgnored &CDetourDis::CopyVex2
#define ENTRY_CopyVex3 ENTRY_DataIgnored &CDetourDis::CopyVex3 #define ENTRY_CopyVex3 ENTRY_DataIgnored &CDetourDis::CopyVex3
#define ENTRY_CopyEvex ENTRY_DataIgnored &CDetourDis::CopyEvex // 62, 3 byte payload, then normal with implied prefixes like vex
#define ENTRY_CopyXop ENTRY_DataIgnored &CDetourDis::CopyXop // 0x8F ... POP /0 or AMD XOP
#define ENTRY_CopyBytesXop 5, 5, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm
#define ENTRY_CopyBytesXop1 6, 6, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm8
#define ENTRY_CopyBytesXop4 9, 9, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm32
#define ENTRY_Invalid ENTRY_DataIgnored &CDetourDis::Invalid #define ENTRY_Invalid ENTRY_DataIgnored &CDetourDis::Invalid
#define ENTRY_End ENTRY_DataIgnored NULL #define ENTRY_End ENTRY_DataIgnored NULL
@ -289,6 +281,9 @@ class CDetourDis
PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc); PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p);
PBYTE CopyEvex(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
protected: protected:
static const COPYENTRY s_rceCopyTable[257]; static const COPYENTRY s_rceCopyTable[257];
@ -303,6 +298,7 @@ class CDetourDis
BOOL m_bAddressOverride; BOOL m_bAddressOverride;
BOOL m_bRaxOverride; // AMD64 only BOOL m_bRaxOverride; // AMD64 only
BOOL m_bVex; BOOL m_bVex;
BOOL m_bEvex;
BOOL m_bF2; BOOL m_bF2;
BOOL m_bF3; // x86 only BOOL m_bF3; // x86 only
BYTE m_nSegmentOverride; BYTE m_nSegmentOverride;
@ -337,6 +333,7 @@ CDetourDis::CDetourDis(_Out_opt_ PBYTE *ppbTarget, _Out_opt_ LONG *plExtra)
m_bF2 = FALSE; m_bF2 = FALSE;
m_bF3 = FALSE; m_bF3 = FALSE;
m_bVex = FALSE; m_bVex = FALSE;
m_bEvex = FALSE;
m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget; m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
m_plExtra = plExtra ? plExtra : &m_lScratchExtra; m_plExtra = plExtra ? plExtra : &m_lScratchExtra;
@ -368,8 +365,11 @@ PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
{ {
UINT nBytesFixed; UINT nBytesFixed;
ASSERT(!m_bVex || pEntry->nFlagBits == 0); if (m_bVex || m_bEvex)
ASSERT(!m_bVex || pEntry->nFixedSize == pEntry->nFixedSize16); {
ASSERT(pEntry->nFlagBits == 0);
ASSERT(pEntry->nFixedSize == pEntry->nFixedSize16);
}
UINT const nModOffset = pEntry->nModOffset; UINT const nModOffset = pEntry->nModOffset;
UINT const nFlagBits = pEntry->nFlagBits; UINT const nFlagBits = pEntry->nFlagBits;
@ -748,33 +748,42 @@ PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
return pbOut; return pbOut;
} }
PBYTE CDetourDis::CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc) PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p)
// m is first instead of last in the hopes of pbDst/pbSrc being // m is first instead of last in the hopes of pbDst/pbSrc being
// passed along efficiently in the registers they were already in. // passed along efficiently in the registers they were already in.
{ {
static const COPYENTRY ceF38 = { 0x38, ENTRY_CopyBytes2Mod }; static const COPYENTRY ceF38 = { 0x38, ENTRY_CopyBytes2Mod };
static const COPYENTRY ceF3A = { 0x3A, ENTRY_CopyBytes2Mod1 }; static const COPYENTRY ceF3A = { 0x3A, ENTRY_CopyBytes2Mod1 };
static const COPYENTRY Invalid = { 0xC4, ENTRY_Invalid }; static const COPYENTRY ceInvalid = { 0xC4, ENTRY_Invalid };
m_bVex = TRUE; switch (p & 3) {
REFCOPYENTRY pEntry;
switch (m) {
default: pEntry = &Invalid; break;
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]]; break;
case 2: pEntry = &ceF38; break;
case 3: pEntry = &ceF3A; break;
}
switch (pbSrc[-1] & 3) { // p in last byte
case 0: break; case 0: break;
case 1: m_bOperandOverride = TRUE; break; case 1: m_bOperandOverride = TRUE; break;
case 2: m_bF3 = TRUE; break; case 2: m_bF3 = TRUE; break;
case 3: m_bF2 = TRUE; break; case 3: m_bF2 = TRUE; break;
} }
REFCOPYENTRY pEntry;
switch (m) {
default: return Invalid(&ceInvalid, pbDst, pbSrc);
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]];
return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
case 2: return CopyBytes(&ceF38, pbDst, pbSrc);
case 3: return CopyBytes(&ceF3A, pbDst, pbSrc);
}
} }
PBYTE CDetourDis::CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc)
// m is first instead of last in the hopes of pbDst/pbSrc being
// passed along efficiently in the registers they were already in.
{
m_bVex = TRUE;
BYTE const p = (BYTE)(pbSrc[-1] & 3); // p in last byte
return CopyVexEvexCommon(m, pbDst, pbSrc, p);
}
PBYTE CDetourDis::CopyVex3(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) PBYTE CDetourDis::CopyVex3(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
// 3 byte VEX prefix 0xC4 // 3 byte VEX prefix 0xC4
{ {
@ -835,6 +844,78 @@ PBYTE CDetourDis::CopyVex2(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
return CopyVexCommon(1, pbDst + 2, pbSrc + 2); return CopyVexCommon(1, pbDst + 2, pbSrc + 2);
} }
PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
// 62, 3 byte payload, x86 with implied prefixes like Vex
// for 32bit, mode 0xC0 else fallback to bound /r
{
// NOTE: Intel and Wikipedia number these differently.
// Intel says 0-2, Wikipedia says 1-3.
BYTE const p0 = pbSrc[1];
#ifdef DETOURS_X86
const static COPYENTRY ceBound = { 0x62, ENTRY_CopyBytes2Mod };
if ((p0 & 0xC0) != 0xC0) {
return CopyBytes(&ceBound, pbDst, pbSrc);
}
#endif
static const COPYENTRY ceInvalid = { 0x62, ENTRY_Invalid };
if ((p0 & 0x0C) != 0)
return Invalid(&ceInvalid, pbDst, pbSrc);
BYTE const p1 = pbSrc[2];
if ((p1 & 0x04) != 0x04)
return Invalid(&ceInvalid, pbDst, pbSrc);
// Copy 4 byte prefix.
*(UNALIGNED ULONG *)pbDst = *(UNALIGNED ULONG*)pbSrc;
m_bEvex = TRUE;
#ifdef DETOURS_X64
m_bRaxOverride |= !!(p1 & 0x80); // w
#endif
return CopyVexEvexCommon(p0 & 3u, pbDst + 4, pbSrc + 4, p1 & 3u);
}
PBYTE CDetourDis::CopyXop(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
/* 3 byte AMD XOP prefix 0x8F
byte0: 0x8F
byte1: RXBmmmmm
byte2: WvvvvLpp
byte3: opcode
mmmmm >= 8, else pop
mmmmm only otherwise defined for 8, 9, A.
pp is like VEX but only instructions with 0 are defined
*/
{
const static COPYENTRY cePop = { 0x8F, ENTRY_CopyBytes2Mod };
const static COPYENTRY ceXop = { 0x8F, ENTRY_CopyBytesXop };
const static COPYENTRY ceXop1 = { 0x8F, ENTRY_CopyBytesXop1 };
const static COPYENTRY ceXop4 = { 0x8F, ENTRY_CopyBytesXop4 };
BYTE const m = (BYTE)(pbSrc[1] & 0x1F);
ASSERT(m <= 10);
switch (m)
{
default:
return CopyBytes(&cePop, pbDst, pbSrc);
case 8: // modrm with 8bit immediate
return CopyBytes(&ceXop1, pbDst, pbSrc);
case 9: // modrm with no immediate
return CopyBytes(&ceXop, pbDst, pbSrc);
case 10: // modrm with 32bit immediate
return CopyBytes(&ceXop4, pbDst, pbSrc);
}
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
PBYTE CDetourDis::s_pbModuleBeg = NULL; PBYTE CDetourDis::s_pbModuleBeg = NULL;
@ -1030,11 +1111,11 @@ const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
#ifdef DETOURS_X64 #ifdef DETOURS_X64
{ 0x60, ENTRY_Invalid }, // Invalid { 0x60, ENTRY_Invalid }, // Invalid
{ 0x61, ENTRY_Invalid }, // Invalid { 0x61, ENTRY_Invalid }, // Invalid
{ 0x62, ENTRY_Invalid }, // Invalid (not yet implemented Intel EVEX support) { 0x62, ENTRY_CopyEvex }, // EVEX / AVX512
#else #else
{ 0x60, ENTRY_CopyBytes1 }, // PUSHAD { 0x60, ENTRY_CopyBytes1 }, // PUSHAD
{ 0x61, ENTRY_CopyBytes1 }, // POPAD { 0x61, ENTRY_CopyBytes1 }, // POPAD
{ 0x62, ENTRY_CopyBytes2Mod }, // BOUND /r { 0x62, ENTRY_CopyEvex }, // BOUND /r and EVEX / AVX512
#endif #endif
{ 0x63, ENTRY_CopyBytes2Mod }, // 32bit ARPL /r, 64bit MOVSXD { 0x63, ENTRY_CopyBytes2Mod }, // 32bit ARPL /r, 64bit MOVSXD
{ 0x64, ENTRY_CopyBytesSegment }, // FS prefix { 0x64, ENTRY_CopyBytesSegment }, // FS prefix
@ -1084,7 +1165,7 @@ const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
{ 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r { 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r
{ 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r { 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r
{ 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r { 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r
{ 0x8F, ENTRY_CopyBytes2Mod }, // POP /0 { 0x8F, ENTRY_CopyXop }, // POP /0 or AMD XOP
{ 0x90, ENTRY_CopyBytes1 }, // NOP { 0x90, ENTRY_CopyBytes1 }, // NOP
{ 0x91, ENTRY_CopyBytes1 }, // XCHG { 0x91, ENTRY_CopyBytes1 }, // XCHG
{ 0x92, ENTRY_CopyBytes1 }, // XCHG { 0x92, ENTRY_CopyBytes1 }, // XCHG

View file

@ -9,39 +9,18 @@
// Used for for payloads, byways, and imports. // Used for for payloads, byways, and imports.
// //
#if _MSC_VER >= 1900 #if _MSC_VER < 1299
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#if _MSC_VER >= 1310
#pragma warning(push)
#if _MSC_VER > 1400
#pragma warning(disable:6102 6103) // /analyze warnings
#endif
#include <strsafe.h>
#pragma warning(pop)
#endif
#if (_MSC_VER < 1299)
#pragma warning(disable: 4710) #pragma warning(disable: 4710)
#endif #endif
// #define DETOUR_DEBUG 1 // #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL #define DETOURS_INTERNAL
#include "detours.h" #include "detours.h"
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch #error detours.h version mismatch
#endif #endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
namespace Detour namespace Detour
{ {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1714,17 +1693,13 @@ BOOL CImage::Write(HANDLE hFile)
m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData + m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData +
m_SectionHeaders[n].SizeOfRawData, m_SectionHeaders[n].SizeOfRawData,
m_nNextFileAddr); m_nNextFileAddr);
#if 0 // Old images have VirtualSize == 0 as a matter of course, e.g. NT 3.1.
m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress + // In which case, use SizeOfRawData instead.
m_SectionHeaders[n].Misc.VirtualSize,
m_nNextVirtAddr);
#else
m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress + m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress +
(m_SectionHeaders[n].Misc.VirtualSize (m_SectionHeaders[n].Misc.VirtualSize
? m_SectionHeaders[n].Misc.VirtualSize ? m_SectionHeaders[n].Misc.VirtualSize
: SectionAlign(m_SectionHeaders[n].SizeOfRawData)), : SectionAlign(m_SectionHeaders[n].SizeOfRawData)),
m_nNextVirtAddr); m_nNextVirtAddr);
#endif
m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset); m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset);
@ -1857,7 +1832,7 @@ BOOL CImage::Write(HANDLE hFile)
for (CImageImportFile *pImportFile = m_pImportFiles; for (CImageImportFile *pImportFile = m_pImportFiles;
pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) { pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {
ZeroMemory(piidDst, sizeof(piidDst)); ZeroMemory(piidDst, sizeof(*piidDst));
nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name); nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name);
piidDst->TimeDateStamp = 0; piidDst->TimeDateStamp = 0;
piidDst->ForwarderChain = pImportFile->m_nForwarderChain; piidDst->ForwarderChain = pImportFile->m_nForwarderChain;
@ -1899,7 +1874,7 @@ BOOL CImage::Write(HANDLE hFile)
} }
piidDst++; piidDst++;
} }
ZeroMemory(piidDst, sizeof(piidDst)); ZeroMemory(piidDst, sizeof(*piidDst));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //

View file

@ -9,27 +9,6 @@
// Module enumeration functions. // Module enumeration functions.
// //
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
#pragma warning(disable:4068) // unknown pragma (suppress)
#if _MSC_VER >= 1900
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#if (_MSC_VER < 1310)
#else
#pragma warning(push)
#if _MSC_VER > 1400
#pragma warning(disable:6102 6103) // /analyze warnings
#endif
#include <strsafe.h>
#pragma warning(pop)
#endif
// #define DETOUR_DEBUG 1 // #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL #define DETOURS_INTERNAL
#include "detours.h" #include "detours.h"
@ -38,10 +17,6 @@
#error detours.h version mismatch #error detours.h version mismatch
#endif #endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] #define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
@ -164,8 +139,8 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
return pSymInfo; return pSymInfo;
} }
PVOID WINAPI DetourFindFunction(_In_ PCSTR pszModule, PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
_In_ PCSTR pszFunction) _In_ LPCSTR pszFunction)
{ {
/////////////////////////////////////////////// First, try GetProcAddress. /////////////////////////////////////////////// First, try GetProcAddress.
// //