Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions src/detours.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,22 @@ inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal)
return pbCode;
}

inline BOOL detour_decode_jmp_indirect(PBYTE pbCode, PBYTE *ppbTarget)
{
ULONG cbPrefix = 0;

if ((pbCode[0] & 0xf0) == 0x40) {
cbPrefix = 1;
}

if (pbCode[cbPrefix] != 0xff || pbCode[cbPrefix + 1] != 0x25) {
return FALSE;
}

*ppbTarget = pbCode + cbPrefix + 6 + *(UNALIGNED INT32 *)&pbCode[cbPrefix + 2];
return TRUE;
}

inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit)
{
while (pbCode < pbLimit) {
Expand All @@ -390,6 +406,7 @@ inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit)
inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
{
PBYTE pbCodeOriginal;
PBYTE pbTarget;

if (pbCode == NULL) {
return NULL;
Expand All @@ -399,9 +416,8 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
}

// First, skip over the import vector if there is one.
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
if (detour_decode_jmp_indirect(pbCode, &pbTarget)) { // 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));
Expand All @@ -417,9 +433,8 @@ inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
pbCodeOriginal = pbCode;

// First, skip over the import vector if there is one.
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
if (detour_decode_jmp_indirect(pbCode, &pbTarget)) { // 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));
Expand Down Expand Up @@ -458,17 +473,16 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
// 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);
PBYTE pbJmpTarget;
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);
if (detour_decode_jmp_indirect(pbCode, &pbJmpTarget)) { // jmp [+imm32]
if (pbJmpTarget < pbCode) {
hi = detour_2gb_above((ULONG_PTR)pbJmpTarget);
}
else {
lo = detour_2gb_below((ULONG_PTR)pbNew);
lo = detour_2gb_below((ULONG_PTR)pbJmpTarget);
}
DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", (PVOID)lo, pbCode, (PVOID)hi));
}
Expand All @@ -491,6 +505,8 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,

inline BOOL detour_does_code_end_function(PBYTE pbCode)
{
PBYTE pbTarget;

if (pbCode[0] == 0xeb || // jmp +imm8
pbCode[0] == 0xe9 || // jmp +imm32
pbCode[0] == 0xe0 || // jmp eax
Expand All @@ -502,7 +518,7 @@ inline BOOL detour_does_code_end_function(PBYTE pbCode)
else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret
return TRUE;
}
else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
else if (detour_decode_jmp_indirect(pbCode, &pbTarget)) { // jmp [+imm32]
return TRUE;
}
else if ((pbCode[0] == 0x26 || // jmp es:
Expand Down