Skip to content

Commit

Permalink
Trampoline and Transaction progress and bugfixes
Browse files Browse the repository at this point in the history
related to #4
  • Loading branch information
flobernd committed Feb 6, 2020
1 parent 5732a79 commit 176e2c9
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 143 deletions.
99 changes: 57 additions & 42 deletions examples/InlineHook.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,23 @@
* @brief Demonstrates the inline-hook.
*/

#include <Zycore/Defines.h>
#include <Zyrex/Zyrex.h>
#include <Zyrex/Internal/InlineHook.h>
#include <Zyrex/Internal/Trampoline.h>
#include <stdio.h>
#include <Windows.h>
#include "Zyrex/Transaction.h"
#include <stdint.h>

#include <Windows.h>

/* ============================================================================================== */
/* Entry point */
/* ============================================================================================== */

typedef DWORD (__stdcall *functype)(void* lpThreadParameter);
typedef DWORD (__stdcall functype)(void* param);

const void* original = NULL;
static functype* volatile original = NULL;

DWORD __stdcall xxx2(void* param)
{
Expand All @@ -65,56 +67,69 @@ DWORD __stdcall callback(void* param)

puts("hello from callback\n");

return ((functype)original)(NULL) + 1;
return (*original)(NULL) + 1;
}

typedef BOOL (WINAPI FuncCopyFileW)(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName,
_In_ BOOL bFailIfExists);

static FuncCopyFileW* volatile CopyFileWOriginal = ZYAN_NULL;

BOOL WINAPI CopyFileWCallback(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName,
_In_ BOOL bFailIfExists)
{
ZYAN_UNUSED(lpExistingFileName);
ZYAN_UNUSED(lpNewFileName);
ZYAN_UNUSED(bFailIfExists);

puts("CopyFileW callback");

const BOOL result = CopyFileWOriginal(lpExistingFileName, lpNewFileName, bFailIfExists);
const DWORD error = GetLastError();
ZYAN_UNUSED(error);

return result;
}

int main()
{

ZyrexInitialize();

ZyrexTransactionBegin();
ZyrexInstallInlineHook((void*)&xxx2, (const void*)&callback, &original);
int x = xxx2(0);
printf("%x\n", x);
ZyrexInstallInlineHook((void*)&xxx2, (const void*)&callback, (ZyanConstVoidPointer*)&original);
/*ZyrexInstallInlineHook((void*)&CopyFileW, (const void*)&CopyFileWCallback,
(ZyanConstVoidPointer*)&CopyFileWOriginal);*/
ZyrexTransactionCommit();

printf("%x\n", (unsigned int)xxx2(0));

ZyrexTransactionBegin();
ZyrexRemoveInlineHook((void*)&xxx2, &original);
int z = xxx2(0);
printf("%x\n", z);
ZyrexRemoveInlineHook((ZyanConstVoidPointer*)&original);
ZyrexTransactionCommit();


//ZyrexTransactionAbort();

// ZyanU8 buffer[] =
// { // E1, E2
// 0xEB, 0xFE, 0x75, 0x02, 0xeb, 0xfb, 0x67, 0xE3, 0xf8, 0x48, 0x8B, 0x05, 0xF5, 0xFF, 0xFF, 0xFF, 0x90, 0x90, 0x90, 0xC3
// };
// void* const buf = VirtualAlloc(NULL, sizeof(buffer), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// memcpy(buf, buffer, sizeof(buffer));
//
// const functype xxx = xxx2;// (functype)buf;
//
//
// ZyrexTrampolineChunk* trampoline;
// const ZyanStatus status =
// ZyrexTrampolineCreate((const void*)xxx, (const void*)&callback, 5, &trampoline);
// if (ZYAN_SUCCESS(status))
// {
// original = &trampoline->code_buffer;
//
//#ifdef ZYAN_X64
// ZyrexAttachInlineHook((void*)xxx, &trampoline->callback_jump);
//#else
// ZyrexAttachInlineHook(xxx, &callback);
//#endif
//
// printf("%.8X", ((functype)xxx)(NULL));
//
// ZyrexTrampolineFree(trampoline);
// }
printf("%x\n", (unsigned int)xxx2(0));


//ZyanU8 buffer[] =
//{ // E1, E2
// /*0xEB, 0xFE, */0x75, 0x02, 0xeb, 0xfb, 0x67, 0xE3, 0xf8, 0x48, 0x8B, 0x05, 0xF5, 0xFF, 0xFF, 0xFF, 0x90, 0x90, 0x90, 0xC3
//};
//void* const buf = VirtualAlloc(NULL, sizeof(buffer), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//memcpy(buf, buffer, sizeof(buffer));

//functype* const xxx = (functype*)buf;


//ZyrexTrampolineChunk* trampoline;
//const ZyanStatus status =
// ZyrexTrampolineCreate((const void*)xxx, (const void*)&callback, 5, &trampoline);
//if (ZYAN_SUCCESS(status))
//{
// original = (functype*)&trampoline->code_buffer;

// printf("%.8X", ((functype*)original)(NULL));

// ZyrexTrampolineFree(trampoline);
//}

return 0;
}
Expand Down
9 changes: 7 additions & 2 deletions include/Zyrex/Internal/InlineHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#ifndef ZYREX_INLINE_HOOK_H
#define ZYREX_INLINE_HOOK_H

#include <Zycore/Defines.h>
#ifdef ZYAN_WINDOWS
# include <windows.h>
#endif
#include <Zycore/Types.h>
#include <Zyrex/Internal/Trampoline.h>

Expand All @@ -42,13 +46,14 @@ extern "C" {
/* Attaching and detaching */
/* ---------------------------------------------------------------------------------------------- */


#include <Windows.h>
#ifdef ZYAN_WINDOWS

ZyanStatus ZyrexMigrateThread(DWORD thread_id, const void* source, ZyanUSize source_length,
const void* destination, ZyanUSize destination_length,
const ZyrexInstructionTranslationMap* translation_map);

#endif

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
Expand Down
27 changes: 26 additions & 1 deletion include/Zyrex/Internal/Trampoline.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ extern "C" {
/**
* @brief Defines the trampoline region signature.
*/
#define ZYREX_TRAMPOLINE_REGION_SIGNATURE 'zrex'
#define ZYREX_TRAMPOLINE_REGION_SIGNATURE 0x7A726578

/* ============================================================================================== */
/* Enums and types */
Expand Down Expand Up @@ -127,6 +127,10 @@ typedef struct ZyrexInstructionTranslationItem_
* buffer.
*/
ZyanU8 offset_destination;
/**
* @brief An absolute target address outside the destination buffer.
*/
ZyanUPointer target_address;
} ZyrexInstructionTranslationItem;

/**
Expand Down Expand Up @@ -206,6 +210,10 @@ typedef struct ZyrexTrampolineChunk_
/* Functions */
/* ============================================================================================== */

/* ---------------------------------------------------------------------------------------------- */
/* Creation and destruction */
/* ---------------------------------------------------------------------------------------------- */

/**
* @brief Creates a new trampoline.
*
Expand All @@ -232,6 +240,23 @@ ZyanStatus ZyrexTrampolineCreate(const void* address, const void* callback,
*/
ZyanStatus ZyrexTrampolineFree(ZyrexTrampolineChunk* trampoline);

/* ---------------------------------------------------------------------------------------------- */
/* Searching */
/* ---------------------------------------------------------------------------------------------- */

/**
* @brief Searches for a trampoline chunk using the given `original`-function pointer.
*
* @param original A pointer to the original function.
* @param trampoline Receives the corresponding trampoline chunk, if found.
*
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or an other
* zyan status code if an error occured.
*/
ZyanStatus ZyrexTrampolineFind(const void* original, ZyrexTrampolineChunk** trampoline);

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */

#ifdef __cplusplus
Expand Down
81 changes: 71 additions & 10 deletions include/Zyrex/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,66 @@ extern "C" {
/* Enums and types */
/* ============================================================================================== */

/* ---------------------------------------------------------------------------------------------- */
/* Hook type */
/* ---------------------------------------------------------------------------------------------- */

/**
* @brief Defines the `ZyrexHookType` enum.
*/
typedef enum ZyrexHookType_
{
/**
* @brief Inline hook.
*
* The inline hook uses a `jmp` instruction at the begin of the target function to redirect
* code-fow to the callback function.
*/
ZYREX_HOOK_TYPE_INLINE,
/**
* @brief Exception hook.
*
* The exception hook uses a privileged instruction at the begin of the target function to
* cause an exception which is later catched by an unhandled-exception-handler that redirects
* code-flow to the callback function by modifying the instruction-pointer register of the
* calling thread.
*/
ZYREX_HOOK_TYPE_EXCEPTION,
/**
* @brief Context/HWBP hook.
*
* The context/HWBP hook modifies the x86-64 debug registers to cause an exception which is
* later catched by an unhandled-exception-handler that redirects code-flow to the callback
* function by modifying the instruction-pointer register of the calling thread.
*
* This hook
*/
ZYREX_HOOK_TYPE_CONTEXT
} ZyrexHookType;

/* ---------------------------------------------------------------------------------------------- */
/* Hook */
/* ---------------------------------------------------------------------------------------------- */

/**
* @brief Defines the `ZyrexHook` struct.
*
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
* behavior.
*/
typedef struct ZyrexHook_
{
/**
* @brief The hook type - just for reference.
*/
ZyrexHookType type;
/**
* @brief The address of the hooked function.
*/
void* address;

} ZyrexHook;

/* ---------------------------------------------------------------------------------------------- */
/* Hook operation */
/* ---------------------------------------------------------------------------------------------- */
Expand All @@ -66,8 +126,8 @@ ZYREX_EXPORT ZyanStatus ZyrexTransactionBegin();
/**
* @brief Adds a specific thread to the thread-update list.
*
* The given thread is immediately suspended and resumed after the transaction was either committed
* or canceled.
* The given thread is immediately suspended and later on resumed after the transaction was either
* been committed or canceled.
*
* @param thread_id The id of the thread to add to the update list.
*
Expand All @@ -78,8 +138,8 @@ ZYREX_EXPORT ZyanStatus ZyrexUpdateThread(DWORD thread_id);
/**
* @brief Adds all threads (except the calling one) to the update list.
*
* All threads are immediately suspended and resumed after the transaction was either committed
* or canceled.
* All threads are immediately suspended and later on resumed after the transaction was either
* been committed or canceled.
*
* @return A zyan status code.
*/
Expand All @@ -88,7 +148,7 @@ ZYREX_EXPORT ZyanStatus ZyrexUpdateAllThreads();
/**
* @brief Commits the current transaction.
*
* This function performs all pending hook attach/remove operations and updates all threads in the
* This function performs the pending hook attach/remove operations and updates all threads in the
* thread-update list.
*
* @return A zyan status code.
Expand Down Expand Up @@ -120,12 +180,13 @@ ZYREX_EXPORT ZyanStatus ZyrexTransactionAbort();
*
* @param address The address to hook.
* @param callback The callback address.
* @param original Receives the address of the original function, if the operation succeeded.
* @param trampoline Receives the address of the trampoline to the original function, if the
* operation succeeded.
*
* @return A zyan status code.
*/
ZYREX_EXPORT ZyanStatus ZyrexInstallInlineHook(void* address, const void* callback,
ZyanConstVoidPointer* original);
ZyanConstVoidPointer* trampoline);

///**
// * @brief Attaches an exception hook.
Expand Down Expand Up @@ -158,12 +219,12 @@ ZYREX_EXPORT ZyanStatus ZyrexInstallInlineHook(void* address, const void* callba
/**
* @brief Removes an inline hook at the given `address`.
*
* @param address The address to unhook.
* @param original Receives the address of the original function, if the operation succeeded.
* @param trampoline A pointer to the trampoline address received during the hook attaching.
* Receives the address of the original function after removing the hook.
*
* @return A zyan status code.
*/
ZYREX_EXPORT ZyanStatus ZyrexRemoveInlineHook(void* address, ZyanConstVoidPointer* original);
ZYREX_EXPORT ZyanStatus ZyrexRemoveInlineHook(ZyanConstVoidPointer* trampoline);

/* ---------------------------------------------------------------------------------------------- */

Expand Down
8 changes: 4 additions & 4 deletions src/Barrier.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef struct ZyrexBarrierContext_
/* ---------------------------------------------------------------------------------------------- */

/**
* @brief This function is invoked everytime a thread exists.
* @brief This function is invoked every time a thread exists.
*
* @param data The data currently stored in the TLS slot.
*/
Expand All @@ -97,7 +97,7 @@ ZYAN_THREAD_DECLARE_TLS_CALLBACK(ZyrexBarrierTlsCleanup, ZyanVector, data)
* @brief Defines a comparison function for the `ZyrexBarrierContext` struct that uses the `id`
* field to create an absolute order.
*/
ZYAN_DECLARE_COMPARISON_FOR_FIELD(ZyrexBarrierCompareContext, ZyrexBarrierContext, id);
ZYAN_DECLARE_COMPARISON_FOR_FIELD(ZyrexBarrierCompareContext, ZyrexBarrierContext, id)

/* ---------------------------------------------------------------------------------------------- */

Expand Down Expand Up @@ -190,7 +190,7 @@ ZyanStatus ZyrexBarrierLeave(ZyrexBarrierHandle handle)
ZyanUSize found_index;
const ZyanStatus status =
ZyanVectorBinarySearch(vector, &context_element, &found_index,
(ZyanComparison)&ZyrexBarrierCompareContext);
(ZyanComparison)&ZyrexBarrierCompareContext);
ZYAN_CHECK(status);

if (status != ZYAN_STATUS_TRUE)
Expand Down Expand Up @@ -234,7 +234,7 @@ ZyanStatus ZyrexBarrierGetRecursionDepth(ZyrexBarrierHandle handle, ZyanU32* cur
ZyanUSize found_index;
const ZyanStatus status =
ZyanVectorBinarySearch(vector, &context_element, &found_index,
(ZyanComparison)&ZyrexBarrierCompareContext);
(ZyanComparison)&ZyrexBarrierCompareContext);
ZYAN_CHECK(status);

if (status == ZYAN_STATUS_TRUE)
Expand Down
Loading

0 comments on commit 176e2c9

Please sign in to comment.