Skip to content

Commit

Permalink
Add detour reHook()
Browse files Browse the repository at this point in the history
  • Loading branch information
stevemk14ebr committed Sep 21, 2020
1 parent b3c0baf commit 6b418e0
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 13 deletions.
13 changes: 13 additions & 0 deletions UnitTests/TestDetourx64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ TEMPLATE_TEST_CASE("Testing 64 detours", "[x64Detour],[ADetour]", PLH::CapstoneD
REQUIRE(detour.unHook() == true);
}

SECTION("Normal function rehook")
{
PLH::StackCanary canary;
PLH::x64Detour detour((char*)&hookMe1, (char*)h_hookMe1, &hookMe1Tramp, dis);
REQUIRE(detour.hook() == true);

effects.PushEffect();
REQUIRE(detour.reHook() == true); // can only really test this doesn't cause memory corruption easily
hookMe1();
REQUIRE(effects.PopEffect().didExecute());
REQUIRE(detour.unHook() == true);
}

// In release mode win apis usually go through two levels of jmps
/*
0xe9 ... jmp iat_thunk
Expand Down
12 changes: 12 additions & 0 deletions UnitTests/TestDetourx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ TEMPLATE_TEST_CASE("Testing x86 detours", "[x86Detour],[ADetour]", PLH::Capstone
REQUIRE(detour.unHook() == true);
}

SECTION("Normal function rehook") {
PLH::x86Detour detour((char*)&hookMe1, (char*)h_hookMe1, &hookMe1Tramp, dis);
REQUIRE(detour.hook() == true);

effects.PushEffect();
REQUIRE(detour.reHook() == true); // can only really test this doesn't cause memory corruption easily
volatile auto result = hookMe1();
PH_UNUSED(result);
REQUIRE(effects.PopEffect().didExecute());
REQUIRE(detour.unHook() == true);
}

SECTION("Jmp into prologue w/ src in range") {
PLH::x86Detour detour((char*)&hookMe2, (char*)&h_nullstub, &nullTramp, dis);

Expand Down
2 changes: 1 addition & 1 deletion asmjit
Submodule asmjit updated 87 files
+45 −30 CMakeLists.txt
+8 −3 README.md
+3 −3 src/asmjit/core.h
+9 −13 src/asmjit/core/api-config.h
+0 −59 src/asmjit/core/arch.cpp
+0 −64 src/asmjit/core/arch.h
+164 −0 src/asmjit/core/archcommons.h
+155 −0 src/asmjit/core/archtraits.cpp
+174 −0 src/asmjit/core/archtraits.h
+17 −14 src/asmjit/core/assembler.cpp
+4 −4 src/asmjit/core/assembler.h
+2 −9 src/asmjit/core/builder.cpp
+10 −10 src/asmjit/core/builder.h
+0 −59 src/asmjit/core/callconv.cpp
+0 −374 src/asmjit/core/callconv.h
+80 −40 src/asmjit/core/codeholder.cpp
+293 −161 src/asmjit/core/codeholder.h
+151 −0 src/asmjit/core/codewriter.cpp
+23 −4 src/asmjit/core/codewriter_p.h
+11 −28 src/asmjit/core/compiler.cpp
+126 −179 src/asmjit/core/compiler.h
+170 −0 src/asmjit/core/compilerdefs.h
+2 −2 src/asmjit/core/constpool.cpp
+1 −1 src/asmjit/core/cpuinfo.h
+351 −0 src/asmjit/core/emithelper.cpp
+83 −0 src/asmjit/core/emithelper_p.h
+32 −30 src/asmjit/core/emitter.cpp
+21 −16 src/asmjit/core/emitter.h
+30 −9 src/asmjit/core/environment.h
+40 −28 src/asmjit/core/formatter.cpp
+210 −43 src/asmjit/core/func.cpp
+549 −99 src/asmjit/core/func.h
+315 −0 src/asmjit/core/funcargscontext.cpp
+224 −0 src/asmjit/core/funcargscontext_p.h
+4 −3 src/asmjit/core/globals.cpp
+31 −25 src/asmjit/core/globals.h
+12 −12 src/asmjit/core/inst.cpp
+1 −1 src/asmjit/core/jitallocator.cpp
+10 −2 src/asmjit/core/jitruntime.cpp
+3 −1 src/asmjit/core/misc_p.h
+8 −1 src/asmjit/core/operand.cpp
+233 −121 src/asmjit/core/operand.h
+30 −21 src/asmjit/core/raassignment_p.h
+16 −26 src/asmjit/core/rabuilders_p.h
+81 −95 src/asmjit/core/radefs_p.h
+54 −47 src/asmjit/core/ralocal.cpp
+8 −8 src/asmjit/core/ralocal_p.h
+90 −116 src/asmjit/core/rapass.cpp
+79 −100 src/asmjit/core/rapass_p.h
+136 −102 src/asmjit/core/support.h
+1 −1 src/asmjit/core/target.h
+2 −2 src/asmjit/core/type.cpp
+2 −0 src/asmjit/core/zonevector.cpp
+31 −27 src/asmjit/core/zonevector.h
+2 −1 src/asmjit/x86.h
+0 −137 src/asmjit/x86/x86archdata.cpp
+150 −0 src/asmjit/x86/x86archtraits_p.h
+50 −62 src/asmjit/x86/x86assembler.cpp
+1 −4 src/asmjit/x86/x86builder.cpp
+0 −238 src/asmjit/x86/x86callconv.cpp
+2 −5 src/asmjit/x86/x86compiler.cpp
+603 −0 src/asmjit/x86/x86emithelper.cpp
+36 −9 src/asmjit/x86/x86emithelper_p.h
+185 −217 src/asmjit/x86/x86emitter.h
+1 −1 src/asmjit/x86/x86features.cpp
+1 −0 src/asmjit/x86/x86features.h
+55 −55 src/asmjit/x86/x86formatter.cpp
+531 −0 src/asmjit/x86/x86func.cpp
+11 −8 src/asmjit/x86/x86func_p.h
+6 −6 src/asmjit/x86/x86globals.h
+55 −55 src/asmjit/x86/x86instapi.cpp
+8 −8 src/asmjit/x86/x86instdb.h
+0 −1,733 src/asmjit/x86/x86internal.cpp
+0 −87 src/asmjit/x86/x86internal_p.h
+1 −24 src/asmjit/x86/x86operand.cpp
+181 −152 src/asmjit/x86/x86operand.h
+126 −119 src/asmjit/x86/x86rapass.cpp
+17 −14 src/asmjit/x86/x86rapass_p.h
+247 −0 test/asmjit_test_compiler.cpp
+103 −0 test/asmjit_test_compiler.h
+332 −436 test/asmjit_test_compiler_x86.cpp
+1 −1 test/asmjit_test_opcode.cpp
+1 −1 test/asmjit_test_unit.cpp
+35 −0 test/asmjit_test_x86_instinfo.cpp
+2 −2 test/asmjit_test_x86_sections.cpp
+83 −0 test/cmdline.h
+2 −2 tools/ci-run.sh
15 changes: 15 additions & 0 deletions polyhook2/Detour/ADetour.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ class Detour : public PLH::IHook {

virtual bool unHook() override;

/**
This is for restoring hook bytes if a 3rd party uninstalled them.
DO NOT call this after unHook(). This may only be called after hook()
but before unHook()
**/
virtual bool reHook();

virtual HookType getType() const override {
return HookType::Detour;
}
Expand All @@ -90,6 +97,14 @@ class Detour : public PLH::IHook {

PLH::insts_t m_originalInsts;

/*Save the instructions used for the hook so that we can re-write in rehook()
Note: There's a nop range we store too so that it doesn't need to be re-calculated
*/
PLH::insts_t m_hookInsts;
uint16_t m_nopProlOffset;
uint16_t m_nopSize;
uint32_t m_hookSize;

/**Walks the given vector of instructions and sets roundedSz to the lowest size possible that doesn't split any instructions and is greater than minSz.
If end of function is encountered before this condition an empty optional is returned. Returns instructions in the range start to adjusted end**/
std::optional<insts_t> calcNearestSz(const insts_t& functionInsts, const uint64_t minSz,
Expand Down
11 changes: 11 additions & 0 deletions sources/ADetour.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,14 @@ bool PLH::Detour::unHook() {
m_hooked = false;
return true;
}

bool PLH::Detour::reHook()
{
MemoryProtector prot(m_fnAddress, m_hookSize, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this);
m_disasm.writeEncoding(m_hookInsts, *this);

// Nop the space between jmp and end of prologue
assert(m_hookSize >= m_nopProlOffset);
writeNop(m_fnAddress + m_nopProlOffset, m_nopSize);
return true;
}
14 changes: 8 additions & 6 deletions sources/x64Detour.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,10 @@ bool PLH::x64Detour::hook() {
}

*m_userTrampVar = m_trampoline;
m_hookSize = (uint32_t)roundProlSz;
m_nopProlOffset = (uint16_t)minProlSz;

MemoryProtector prot(m_fnAddress, roundProlSz, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this);
MemoryProtector prot(m_fnAddress, m_hookSize, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this);
// we're really space constrained, try to do some stupid hacks like checking for 0xCC's near us
auto cave = findNearestCodeCave<8>(m_fnAddress);
if (!cave) {
Expand All @@ -248,13 +250,13 @@ bool PLH::x64Detour::hook() {
}

MemoryProtector holderProt(*cave, 8, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this, false);
const auto prolJmp = makex64MinimumJump(m_fnAddress, m_fnCallback, *cave);
m_disasm.writeEncoding(prolJmp, *this);
m_hookInsts = makex64MinimumJump(m_fnAddress, m_fnCallback, *cave);
m_disasm.writeEncoding(m_hookInsts, *this);

// Nop the space between jmp and end of prologue
assert(roundProlSz >= minProlSz);
const uint8_t nopSz = (uint8_t)(roundProlSz - minProlSz);
writeNop(m_fnAddress + minProlSz, nopSz);
assert(m_hookSize >= m_nopProlOffset);
m_nopSize = (uint16_t)(m_hookSize - m_nopProlOffset);
writeNop(m_fnAddress + m_nopProlOffset, m_nopSize);

m_hooked = true;
return true;
Expand Down
14 changes: 8 additions & 6 deletions sources/x86Detour.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,17 @@ bool PLH::x86Detour::hook() {
}

*m_userTrampVar = m_trampoline;
m_hookSize = (uint32_t)roundProlSz;
m_nopProlOffset = (uint16_t)minProlSz;

MemoryProtector prot(m_fnAddress, roundProlSz, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this);
const auto prolJmp = makex86Jmp(m_fnAddress, m_fnCallback);
m_disasm.writeEncoding(prolJmp, *this);
MemoryProtector prot(m_fnAddress, m_hookSize, ProtFlag::R | ProtFlag::W | ProtFlag::X, *this);
m_hookInsts = makex86Jmp(m_fnAddress, m_fnCallback);
m_disasm.writeEncoding(m_hookInsts, *this);

// Nop the space between jmp and end of prologue
assert(roundProlSz >= minProlSz);
const uint8_t nopSz = (uint8_t)(roundProlSz - minProlSz);
writeNop(m_fnAddress + minProlSz, nopSz);
assert(m_hookSize >= m_nopProlOffset);
m_nopSize = (uint16_t)(m_hookSize - m_nopProlOffset);
writeNop(m_fnAddress + m_nopProlOffset, m_nopSize);

m_hooked = true;
return true;
Expand Down

0 comments on commit 6b418e0

Please sign in to comment.