3
3
// Default
4
4
#include <tchar.h>
5
5
6
+ // STL
7
+ #include <unordered_map>
8
+ #include <deque>
9
+
6
10
#ifndef MAX
7
11
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
8
12
#endif
@@ -7507,30 +7511,100 @@ namespace Detours {
7507
7511
}
7508
7512
break;
7509
7513
#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;
7510
7521
default:
7511
7522
break;
7512
7523
}
7513
7524
}
7514
7525
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
+
7515
7545
static void FixMemoryHookAddress(const PCONTEXT pCTX, const void* pExceptionAddress, MEMORY_HOOK_OPERATION unOperation, const void* pAddress, void* pNewAddress) {
7516
7546
if (!pCTX || !pAddress || !pNewAddress) {
7517
7547
return;
7518
7548
}
7519
7549
7520
7550
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
+
7522
7591
#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))) {
7524
7593
#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))) {
7526
7595
#endif
7527
- return;
7596
+ return;
7597
+ }
7598
+
7599
+ pInsn = pInstruction.get();
7600
+ g_CachedInstructions.insert(it, std::make_pair(pExceptionAddress, std::move(pInstruction)));
7601
+ }
7528
7602
}
7529
7603
7530
7604
switch (unOperation) {
7531
7605
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];
7534
7608
if (!ReadOperand.Access.Read) {
7535
7609
return;
7536
7610
}
@@ -7541,6 +7615,8 @@ namespace Detours {
7541
7615
ULONG_PTR unValue = GetRegisterValue(pCTX, ReadOperand.Info.Register.Reg, ReadOperand.Info.Register.Size);
7542
7616
if (reinterpret_cast<ULONG_PTR>(pAddress) == unValue) {
7543
7617
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;
7544
7620
}
7545
7621
} else if (ReadOperand.Type == RD_OP_MEM) {
7546
7622
#ifdef _M_X64
@@ -7568,16 +7644,20 @@ namespace Detours {
7568
7644
if (unBase) {
7569
7645
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unBase;
7570
7646
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);
7571
7650
return;
7572
7651
}
7573
7652
7574
7653
if (unIndex) {
7575
7654
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unIndex;
7576
7655
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);
7577
7659
return;
7578
7660
}
7579
-
7580
- return;
7581
7661
}
7582
7662
} else if (ReadOperand.Type == RD_OP_IMM) {
7583
7663
__debugbreak(); // TODO: Implement.
@@ -7594,11 +7674,11 @@ namespace Detours {
7594
7674
}
7595
7675
7596
7676
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];
7599
7679
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];
7602
7682
}
7603
7683
7604
7684
if (!WriteOperand.Access.Write) {
@@ -7612,6 +7692,8 @@ namespace Detours {
7612
7692
ULONG_PTR unValue = GetRegisterValue(pCTX, WriteOperand.Info.Register.Reg, WriteOperand.Info.Register.Size);
7613
7693
if (reinterpret_cast<ULONG_PTR>(pAddress) == unValue) {
7614
7694
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;
7615
7697
}
7616
7698
} else if (WriteOperand.Type == RD_OP_MEM) {
7617
7699
#ifdef _M_X64
@@ -7639,16 +7721,20 @@ namespace Detours {
7639
7721
if (unBase) {
7640
7722
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unBase;
7641
7723
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);
7642
7727
return;
7643
7728
}
7644
7729
7645
7730
if (unIndex) {
7646
7731
const size_t unOffset = reinterpret_cast<size_t>(pAddress) - unIndex;
7647
7732
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);
7648
7736
return;
7649
7737
}
7650
-
7651
- return;
7652
7738
}
7653
7739
} else if (WriteOperand.Type == RD_OP_IMM) {
7654
7740
__debugbreak(); // TODO: Implement.
@@ -7826,7 +7912,7 @@ namespace Detours {
7826
7912
}
7827
7913
}
7828
7914
7829
- const bool bResult = pRecord->m_pCallBack(pCTX, unOperation, pAddress, &pNewAddress);
7915
+ const bool bResult = pRecord->m_pCallBack(pCTX, pExceptionAddress, unOperation, pAddress, &pNewAddress);
7830
7916
if (bResult) {
7831
7917
FixMemoryHookAddress(pCTX, pExceptionAddress, unOperation, pAddress, pNewAddress);
7832
7918
}
0 commit comments