Skip to content

Commit

Permalink
Fill the original pointer before the hook is applied
Browse files Browse the repository at this point in the history
  • Loading branch information
HoShiMin committed Oct 10, 2023
1 parent d2400ce commit ac14522
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 94 deletions.
130 changes: 69 additions & 61 deletions HookLib/HookLib/HookLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1809,13 +1809,15 @@ static void writeJumpToContinuation(const Arch arch, void* const from, const voi
}
}

static bool applyHook(const Arch arch, HookData* const hook, void* const fn, const void* const handler)
static bool applyHook(const Arch arch, HookData* const hook, void* const fn, const void* const handler, void** original)
{
if (!hook || !fn)
if (!hook || !fn || !original)
{
return false;
}

hook->fn = fn;

const bool needLongJump = k_forceLongJumps || !relativeJumpable(fn, handler);
const bool intermediateJumpAppliable = k_enableIntermediateJumps && needLongJump && relativeJumpable(fn, &hook->intermediate);

Expand All @@ -1832,17 +1834,21 @@ static bool applyHook(const Arch arch, HookData* const hook, void* const fn, con

memcpy(hook->original, fn, relocatedBytes);

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(x64, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;

*original = hook->beginning;
_mm_sfence();

const LongJump64 jump = makeLongJump64(handler);
const bool status = writeToReadonly(fn, &jump, sizeof(jump));
if (!status)
{
*original = nullptr;
return false;
}

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(x64, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;
}
else
{
Expand All @@ -1854,17 +1860,21 @@ static bool applyHook(const Arch arch, HookData* const hook, void* const fn, con

memcpy(hook->original, fn, relocatedBytes);

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(x32, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;

*original = hook->beginning;
_mm_sfence();

const LongJump32 jump = makeLongJump32(fn, handler);
const bool status = writeToReadonly(fn, &jump, sizeof(jump));
if (!status)
{
*original = nullptr;
return false;
}

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(x32, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;
}
}
else
Expand All @@ -1889,17 +1899,21 @@ static bool applyHook(const Arch arch, HookData* const hook, void* const fn, con

memcpy(hook->original, fn, relocatedBytes);

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(arch, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;

*original = hook->beginning;
_mm_sfence();

const RelJump jump = makeRelJump(fn, &hook->intermediate);
const bool status = writeToReadonly(fn, &jump, sizeof(jump));
if (!status)
{
*original = nullptr;
return false;
}

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(arch, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;
}
else
{
Expand All @@ -1911,109 +1925,105 @@ static bool applyHook(const Arch arch, HookData* const hook, void* const fn, con

memcpy(hook->original, fn, relocatedBytes);

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(arch, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;

*original = hook->beginning;
_mm_sfence();

const RelJump jump = makeRelJump(fn, handler);
const bool status = writeToReadonly(fn, &jump, sizeof(jump));
if (!status)
{
return false;
}

const void* const beginningContinuation = (const unsigned char*)fn + relocatedBytes;
writeJumpToContinuation(arch, &hook->beginning[relocatedBytes], beginningContinuation);

hook->affectedBytes = relocatedBytes;
}
}

hook->fn = fn;
return true;
}


#if _USER_MODE
static void* setHook(Arch arch, void* fn, const void* handler)
static void setHook(Arch arch, void* fn, const void* handler, void** original)
{
HookPage* const existingPage = findHookPage(fn);
if (existingPage)
{
HookData* const freeHookCell = claimHookCell(existingPage);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler, original);
if (hookStatus)
{
return freeHookCell->beginning;
return;
}

releaseHookCell(freeHookCell);
return nullptr;
}

void* const nearestFreePage = findPageForRelativeJump(fn); // Nullable
HookPage* const newPage = allocHookPage(nearestFreePage);
if (!newPage)
{
return nullptr;
return;
}

HookData* const freeHookCell = claimHookCell(newPage);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler, original);
if (!hookStatus)
{
releaseHookCell(freeHookCell);
freeHookPage(newPage);
return nullptr;
return;
}

insertHookPage(newPage);

return freeHookCell->beginning;
}
#else
static void* setHook(Arch arch, void* fn, const void* handler)
static void setHook(Arch arch, void* fn, const void* handler, void** original)
{
if (isUserAddress(fn))
{
HookPage* const existingPage = findHookPage(fn);
if (existingPage)
{
HookData* const freeHookCell = claimHookCell(existingPage);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler, original);
if (hookStatus)
{
return freeHookCell->beginning;
return;
}

releaseHookCell(freeHookCell);
}

void* const nearestFreePage = findPageForRelativeJump(fn); // Nullable
HookPage* const newPage = allocHookPage(nearestFreePage);
if (!newPage)
{
return nullptr;
return;
}

HookData* const freeHookCell = claimHookCell(newPage);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler);
const bool hookStatus = applyHook(arch, freeHookCell, fn, handler, original);
if (!hookStatus)
{
releaseHookCell(freeHookCell);
freeHookPage(newPage);
return nullptr;
return;
}

insertHookPage(newPage);

return freeHookCell->beginning;
}
else
{
HookData* const hookData = (HookData*)allocKernel(sizeof(HookData));
const bool hookStatus = applyHook(arch, hookData, fn, handler);
const bool hookStatus = applyHook(arch, hookData, fn, handler, original);
if (!hookStatus)
{
freeKernel(hookData);
return nullptr;
}

return hookData->beginning;
}
}
#endif
Expand All @@ -2026,7 +2036,7 @@ typedef enum

typedef union
{
Hook* hooks;
const Hook* hooks;
Unhook* unhooks;
} HooksUnhooks;

Expand All @@ -2044,7 +2054,7 @@ static size_t calcNewInstructionPointer(const HooksUnhooks hooksUnhooks, const s
continue;
}

const HookData* const hookData = (HookData*)((unsigned char*)hook->original - offsetof(HookData, beginning));
const HookData* const hookData = (HookData*)((unsigned char*)*hook->original - offsetof(HookData, beginning));
if ((ip >= (size_t)hookData->fn) && (ip < ((size_t)hookData->fn + hookData->affectedBytes)))
{
needToFix = true;
Expand Down Expand Up @@ -2366,15 +2376,15 @@ static void fixupContexts(const ProcInfo* const proc, const HooksUnhooks hooksUn



static size_t applyHooks(Arch arch, Hook* hooks, size_t count)
static size_t applyHooks(Arch arch, const Hook* hooks, size_t count)
{
size_t hookedCount = 0;

for (size_t i = 0; i < count; ++i)
{
Hook* const hook = &hooks[i];
hook->original = setHook(arch, hook->fn, hook->handler);
if (hook->original)
const Hook* const hook = &hooks[i];
setHook(arch, hook->fn, hook->handler, hook->original);
if (*hook->original)
{
#if _KERNEL_MODE
_mm_clflush(hook->fn);
Expand All @@ -2389,7 +2399,7 @@ static size_t applyHooks(Arch arch, Hook* hooks, size_t count)
}

#if _USER_MODE
size_t multihook(Hook* hooks, size_t count)
size_t multihook(const Hook* hooks, size_t count)
{
if (!hooks || !count)
{
Expand All @@ -2398,7 +2408,7 @@ size_t multihook(Hook* hooks, size_t count)

for (size_t i = 0; i < count; ++i)
{
hooks[i].original = nullptr;
*hooks[i].original = nullptr;
}

ProcInfo* const snapshot = makeProcSnapshot();
Expand Down Expand Up @@ -2432,7 +2442,7 @@ size_t multihook(Hook* hooks, size_t count)
return hookedCount;
}
#else
size_t multihook(Hook* hooks, size_t count)
size_t multihook(const Hook* hooks, size_t count)
{
if (!hooks || !count)
{
Expand All @@ -2443,7 +2453,7 @@ size_t multihook(Hook* hooks, size_t count)
for (size_t i = 0; i < count; ++i)
{
hasUserHooks |= isUserAddress(hooks[i].fn);
hooks[i].original = nullptr;
*hooks[i].original = nullptr;
}

if (hasUserHooks)
Expand Down Expand Up @@ -2501,23 +2511,21 @@ size_t multihook(Hook* hooks, size_t count)
}
#endif

void* hook(void* fn, const void* handler)
void hook(void* fn, const void* handler, void** original)
{
if (!fn)
if (!fn || !original)
{
return nullptr;
return;
}

Hook hook =
const Hook hook =
{
.fn = fn,
.handler = handler,
.original = nullptr
.original = original
};

multihook(&hook, 1);

return hook.original;
}

static bool performUnhook(HookData* hook)
Expand Down
8 changes: 4 additions & 4 deletions HookLib/HookLib/HookLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ typedef struct
{
void* fn;
const void* handler;
void* original; // hook() makes it valid callable pointer after successful hook and sets as nullptr otherwise
void** original; // hook() makes it valid callable pointer after successful hook and sets as nullptr otherwise
} Hook;

typedef struct
{
void* original; // unhook() makes it nullptr after successful unhook and keeps unchanged otherwise
} Unhook;

hooklib_export void* hook(void* fn, const void* handler);
hooklib_export size_t multihook(Hook* hooks, size_t count);
hooklib_export void hook(void* fn, const void* handler, void** original);
hooklib_export size_t multihook(const Hook* hooks, size_t count);

hooklib_export size_t multiunhook(Unhook* originals, size_t count);
hooklib_export size_t unhook(void* original);
Expand Down Expand Up @@ -116,7 +116,7 @@ class HookHolder
return true;
}

m_orig = static_cast<Fn>(hook(m_fn, m_handler));
hook(m_fn, m_handler, reinterpret_cast<void**>(&m_orig));

return m_orig != nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion HookLib/Zydis
Submodule Zydis updated 44 files
+6 −18 .github/workflows/main.yml
+47 −4 CMakeLists.txt
+2 −3 Makefile
+70 −33 README.md
+2 −4 assets/amalgamate.py
+ assets/screenshots/ZydisDisasm.png
+ assets/screenshots/ZydisInfo.png
+1 −1 dependencies/zycore
+1 −1 examples/Disassemble.c
+1 −1 examples/DisassembleSimple.c
+1 −1 examples/EncodeFromScratch.c
+1 −1 examples/EncodeMov.c
+2 −2 include/Zydis/Decoder.h
+20 −18 include/Zydis/Formatter.h
+6 −0 include/Zydis/Generated/EnumISAExt.h
+6 −0 include/Zydis/Generated/EnumISASet.h
+3 −0 include/Zydis/Generated/EnumInstructionCategory.h
+16 −0 include/Zydis/Generated/EnumMnemonic.h
+2 −0 include/Zydis/Internal/SharedData.h
+1 −1 include/Zydis/Register.h
+2 −0 msvc/tools/ZydisDisasm.vcxproj
+6 −0 msvc/tools/ZydisDisasm.vcxproj.filters
+2 −0 msvc/tools/ZydisInfo.vcxproj
+6 −0 msvc/tools/ZydisInfo.vcxproj.filters
+31 −32 src/Decoder.c
+1 −1 src/Encoder.c
+7 −2 src/Formatter.c
+1,276 −1,198 src/Generated/DecoderTables.inc
+2,433 −2,374 src/Generated/EncoderTables.inc
+6 −0 src/Generated/EnumISAExt.inc
+6 −0 src/Generated/EnumISASet.inc
+3 −0 src/Generated/EnumInstructionCategory.inc
+16 −0 src/Generated/EnumMnemonic.inc
+5,757 −5,714 src/Generated/InstructionDefinitions.inc
+55 −1 src/Generated/OperandDefinitions.inc
+53 −17 src/Register.c
+2 −0 src/SharedData.c
+5 −5 src/String.c
+94 −20 tools/ZydisDisasm.c
+12 −1 tools/ZydisFuzzShared.c
+39 −208 tools/ZydisInfo.c
+2 −2 tools/ZydisTestEncoderAbsolute.c
+221 −0 tools/ZydisToolsShared.c
+134 −0 tools/ZydisToolsShared.h
Loading

0 comments on commit ac14522

Please sign in to comment.