Skip to content

Commit dcb0e0d

Browse files
authored
Add files via upload
1 parent 53d9d3e commit dcb0e0d

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

Detours.cpp

Lines changed: 101 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// Default
44
#include <tchar.h>
55

6+
// STL
7+
#include <unordered_map>
8+
#include <deque>
9+
610
#ifndef MAX
711
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
812
#endif
@@ -7507,30 +7511,100 @@ namespace Detours {
75077511
}
75087512
break;
75097513
#endif
7514+
case RD_REG_RIP:
7515+
#ifdef _M_X64
7516+
pCTX->Rip = unValue;
7517+
#elif _M_IX86
7518+
pCTX->Eip = unValue;
7519+
#endif
7520+
break;
75107521
default:
75117522
break;
75127523
}
75137524
}
75147525

7526+
typedef struct _CACHED_OPERATION {
7527+
_CACHED_OPERATION(void* pExceptionAddress, MEMORY_HOOK_OPERATION unOperation, void* pAddress, RD_OPERAND& Operand, void* pNewAddress) {
7528+
m_pExceptionAddress = pExceptionAddress;
7529+
m_unOperation = unOperation;
7530+
m_pAddress = pAddress;
7531+
m_Operand = Operand;
7532+
m_pNewAddress = pNewAddress;
7533+
}
7534+
7535+
void* m_pExceptionAddress;
7536+
MEMORY_HOOK_OPERATION m_unOperation;
7537+
void* m_pAddress;
7538+
RD_OPERAND m_Operand;
7539+
void* m_pNewAddress;
7540+
} CACHED_OPERATION, *PCACHED_OPERATION;
7541+
7542+
static std::deque<CACHED_OPERATION> g_CachedOperations;
7543+
static std::unordered_map<const void*, std::unique_ptr<INSTRUCTION>> g_CachedInstructions;
7544+
75157545
static void FixMemoryHookAddress(const PCONTEXT pCTX, const void* pExceptionAddress, MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void* pNewAddress) {
75167546
if (!pCTX || !pAddress || !pNewAddress) {
75177547
return;
75187548
}
75197549

75207550
if (pExceptionAddress) {
7521-
INSTRUCTION ins;
7551+
for (auto& CachedOperation : g_CachedOperations) {
7552+
if ((CachedOperation.m_pExceptionAddress == pExceptionAddress) && (CachedOperation.m_unOperation == unOperation) && (CachedOperation.m_pAddress == pAddress)) {
7553+
auto& Operand = CachedOperation.m_Operand;
7554+
7555+
if (Operand.Type == RD_OP_REG) {
7556+
SetRegisterValue(pCTX, Operand.Info.Register.Reg, Operand.Info.Register.Size, reinterpret_cast<ULONG_PTR>(CachedOperation.m_pNewAddress));
7557+
return;
7558+
} else if (Operand.Type == RD_OP_MEM) {
7559+
if (Operand.Info.Memory.HasIndex) {
7560+
SetRegisterValue(pCTX, Operand.Info.Memory.Index, Operand.Info.Memory.IndexSize, reinterpret_cast<ULONG_PTR>(CachedOperation.m_pNewAddress));
7561+
return;
7562+
}
7563+
7564+
if (Operand.Info.Memory.HasBase) {
7565+
SetRegisterValue(pCTX, Operand.Info.Memory.Base, Operand.Info.Memory.BaseSize, reinterpret_cast<ULONG_PTR>(CachedOperation.m_pNewAddress));
7566+
return;
7567+
}
7568+
}
7569+
7570+
break;
7571+
}
7572+
}
7573+
7574+
PINSTRUCTION pInsn = nullptr;
7575+
7576+
{
7577+
bool bIsCachedInstruction = false;
7578+
7579+
auto it = g_CachedInstructions.find(pExceptionAddress);
7580+
if (it != g_CachedInstructions.end()) {
7581+
pInsn = it->second.get();
7582+
bIsCachedInstruction = true;
7583+
}
7584+
7585+
if (!bIsCachedInstruction) {
7586+
auto pInstruction = std::make_unique<INSTRUCTION>();
7587+
if (!pInstruction) {
7588+
return;
7589+
}
7590+
75227591
#ifdef _M_X64
7523-
if (!RD_SUCCESS(RdDecode(&ins, reinterpret_cast<unsigned char*>(const_cast<void*>(pExceptionAddress)), RD_CODE_64, RD_DATA_64))) {
7592+
if (!RD_SUCCESS(RdDecode(pInstruction.get(), reinterpret_cast<unsigned char*>(const_cast<void*>(pExceptionAddress)), RD_CODE_64, RD_DATA_64))) {
75247593
#elif _M_IX86
7525-
if (!RD_SUCCESS(RdDecode(&ins, reinterpret_cast<unsigned char*>(const_cast<void*>(pExceptionAddress)), RD_CODE_32, RD_DATA_32))) {
7594+
if (!RD_SUCCESS(RdDecode(pInstruction.get(), reinterpret_cast<unsigned char*>(const_cast<void*>(pExceptionAddress)), RD_CODE_32, RD_DATA_32))) {
75267595
#endif
7527-
return;
7596+
return;
7597+
}
7598+
7599+
pInsn = pInstruction.get();
7600+
g_CachedInstructions.insert(it, std::make_pair(pExceptionAddress, std::move(pInstruction)));
7601+
}
75287602
}
75297603

75307604
switch (unOperation) {
75317605
case MEMORY_HOOK_OPERATION::MEMORY_READ: {
7532-
if (ins.OperandsCount) {
7533-
auto& ReadOperand = ins.Operands[ins.OperandsCount - 1];
7606+
if (pInsn->OperandsCount) {
7607+
auto& ReadOperand = pInsn->Operands[pInsn->OperandsCount - 1];
75347608
if (!ReadOperand.Access.Read) {
75357609
return;
75367610
}
@@ -7541,6 +7615,8 @@ namespace Detours {
75417615
ULONG_PTR unValue = GetRegisterValue(pCTX, ReadOperand.Info.Register.Reg, ReadOperand.Info.Register.Size);
75427616
if (reinterpret_cast<ULONG_PTR>(pAddress) == unValue) {
75437617
SetRegisterValue(pCTX, ReadOperand.Info.Register.Reg, ReadOperand.Info.Register.Size, reinterpret_cast<size_t>(pNewAddress));
7618+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), ReadOperand, pNewAddress);
7619+
return;
75447620
}
75457621
} else if (ReadOperand.Type == RD_OP_MEM) {
75467622
#ifdef _M_X64
@@ -7568,16 +7644,20 @@ namespace Detours {
75687644
if (unBase) {
75697645
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unBase;
75707646
SetRegisterValue(pCTX, ReadOperand.Info.Memory.Base, ReadOperand.Info.Memory.BaseSize, reinterpret_cast<size_t>(pNewAddress) - unOffset);
7647+
auto OperandCopy = ReadOperand;
7648+
OperandCopy.Info.Memory.HasIndex = false;
7649+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), OperandCopy, static_cast<char*>(pNewAddress) - unOffset);
75717650
return;
75727651
}
75737652

75747653
if (unIndex) {
75757654
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unIndex;
75767655
SetRegisterValue(pCTX, ReadOperand.Info.Memory.Index, ReadOperand.Info.Memory.IndexSize, reinterpret_cast<size_t>(pNewAddress) - unOffset);
7656+
auto OperandCopy = ReadOperand;
7657+
OperandCopy.Info.Memory.HasBase = false;
7658+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), OperandCopy, static_cast<char*>(pNewAddress) - unOffset);
75777659
return;
75787660
}
7579-
7580-
return;
75817661
}
75827662
} else if (ReadOperand.Type == RD_OP_IMM) {
75837663
__debugbreak(); // TODO: Implement.
@@ -7594,11 +7674,11 @@ namespace Detours {
75947674
}
75957675

75967676
case MEMORY_HOOK_OPERATION::MEMORY_WRITE: {
7597-
if (ins.OperandsCount) {
7598-
auto& WriteOperand = ins.Operands[ins.OperandsCount - 1];
7677+
if (pInsn->OperandsCount) {
7678+
auto& WriteOperand = pInsn->Operands[pInsn->OperandsCount - 1];
75997679
if (!WriteOperand.Access.Write) {
7600-
if (ins.OperandsCount > 1) {
7601-
WriteOperand = ins.Operands[ins.OperandsCount - 2];
7680+
if (pInsn->OperandsCount > 1) {
7681+
WriteOperand = pInsn->Operands[pInsn->OperandsCount - 2];
76027682
}
76037683

76047684
if (!WriteOperand.Access.Write) {
@@ -7612,6 +7692,8 @@ namespace Detours {
76127692
ULONG_PTR unValue = GetRegisterValue(pCTX, WriteOperand.Info.Register.Reg, WriteOperand.Info.Register.Size);
76137693
if (reinterpret_cast<ULONG_PTR>(pAddress) == unValue) {
76147694
SetRegisterValue(pCTX, WriteOperand.Info.Register.Reg, WriteOperand.Info.Register.Size, reinterpret_cast<size_t>(pNewAddress));
7695+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), WriteOperand, pNewAddress);
7696+
return;
76157697
}
76167698
} else if (WriteOperand.Type == RD_OP_MEM) {
76177699
#ifdef _M_X64
@@ -7639,16 +7721,20 @@ namespace Detours {
76397721
if (unBase) {
76407722
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unBase;
76417723
SetRegisterValue(pCTX, WriteOperand.Info.Memory.Base, WriteOperand.Info.Memory.BaseSize, reinterpret_cast<size_t>(pNewAddress) - unOffset);
7724+
auto OperandCopy = WriteOperand;
7725+
OperandCopy.Info.Memory.HasIndex = false;
7726+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), OperandCopy, static_cast<char*>(pNewAddress) - unOffset);
76427727
return;
76437728
}
76447729

76457730
if (unIndex) {
76467731
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unIndex;
76477732
SetRegisterValue(pCTX, WriteOperand.Info.Memory.Index, WriteOperand.Info.Memory.IndexSize, reinterpret_cast<size_t>(pNewAddress) - unOffset);
7733+
auto OperandCopy = WriteOperand;
7734+
OperandCopy.Info.Memory.HasBase = false;
7735+
g_CachedOperations.emplace_back(const_cast<void*>(pExceptionAddress), unOperation, const_cast<void*>(pAddress), OperandCopy, static_cast<char*>(pNewAddress) - unOffset);
76487736
return;
76497737
}
7650-
7651-
return;
76527738
}
76537739
} else if (WriteOperand.Type == RD_OP_IMM) {
76547740
__debugbreak(); // TODO: Implement.
@@ -7826,7 +7912,7 @@ namespace Detours {
78267912
}
78277913
}
78287914

7829-
const bool bResult = pRecord->m_pCallBack(pCTX, unOperation, pAddress, &pNewAddress);
7915+
const bool bResult = pRecord->m_pCallBack(pCTX, pExceptionAddress, unOperation, pAddress, &pNewAddress);
78307916
if (bResult) {
78317917
FixMemoryHookAddress(pCTX, pExceptionAddress, unOperation, pAddress, pNewAddress);
78327918
}

Detours.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5545,7 +5545,7 @@ namespace Detours {
55455545
// Memory Hook CallBack
55465546
// ----------------------------------------------------------------
55475547

5548-
using fnMemoryHookCallBack = bool(*)(const PCONTEXT pCTX, MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void** pNewAddress);
5548+
using fnMemoryHookCallBack = bool(*)(const PCONTEXT pCTX, const void* pExceptionAddress, MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void** pNewAddress);
55495549

55505550
// ----------------------------------------------------------------
55515551
// Memory Hook

main.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,8 +1556,9 @@ TEST_SUITE("Detours::Hook") {
15561556
typedef bool(__fastcall* fnFooOriginal)(void* pThis, void* /* unused */);
15571557
typedef bool(__fastcall* fnBooOriginal)(void* pThis, void* /* unused */);
15581558

1559-
bool MemoryHook(const PCONTEXT pCTX, Detours::Hook::MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void** pNewAddress) {
1559+
bool MemoryHook(const PCONTEXT pCTX, const void* pExceptionAddress, Detours::Hook::MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void** pNewAddress) {
15601560
UNREFERENCED_PARAMETER(pCTX);
1561+
UNREFERENCED_PARAMETER(pExceptionAddress);
15611562
UNREFERENCED_PARAMETER(unOperation);
15621563
UNREFERENCED_PARAMETER(pAddress);
15631564
UNREFERENCED_PARAMETER(pNewAddress);
@@ -1765,13 +1766,13 @@ TEST_SUITE("Detours::Hook") {
17651766
srand(time(nullptr) & 0xffffffff);
17661767
ULONG unBegin = Detours::KUserSharedData.SystemTime.LowPart;
17671768
for (size_t i = 0; i < 1'000'000; ++i) {
1768-
reinterpret_cast<unsigned char*>(pAddress)[rand() % (0x800000 - 1)] = 1;
1769+
reinterpret_cast<unsigned char*>(pAddress)[0] = 1;
17691770
}
17701771
MESSAGE("Benckmark with 1 000 000 iterations (without hook): ", (Detours::KUserSharedData.SystemTime.LowPart - unBegin) / 10000, " ms");
17711772
CHECK(Detours::Hook::HookMemory(MemoryHook, Region.GetRegionAddress(), Region.GetRegionCapacity()) == true);
17721773
unBegin = Detours::KUserSharedData.SystemTime.LowPart;
17731774
for (size_t i = 0; i < 1'000'000; ++i) {
1774-
reinterpret_cast<unsigned char*>(pAddress)[rand() % (0x800000 - 1)] = 2;
1775+
reinterpret_cast<unsigned char*>(pAddress)[0] = 2;
17751776
}
17761777
MESSAGE("Benckmark with 1 000 000 iterations (with hook): ", (Detours::KUserSharedData.SystemTime.LowPart - unBegin) / 10000, " ms");
17771778
CHECK(Detours::Hook::UnHookMemory(MemoryHook) == true);

0 commit comments

Comments
 (0)