diff --git a/CMakeLists.txt b/CMakeLists.txt index 88f22c1..a367891 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,14 @@ file(GLOB_RECURSE HEADERS "include/*.h") #TODO more architectures. if (UNIX AND NOT APPLE) - file(GLOB_RECURSE SOURCES "src/linux64/*.cpp") + if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + file(GLOB_RECURSE SOURCES "src/linux64/*.cpp" "src/linuxCommon/*.cpp") + endif() + + if (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64") + file(GLOB_RECURSE SOURCES "src/linuxRV64/*.cpp" "src/linuxCommon/*.cpp") + endif() + add_library(FunctionHook SHARED ${SOURCES}) endif() diff --git a/include/FunctionHook/Hook.h b/include/FunctionHook/Hook.h index 785c69c..2b3cfeb 100644 --- a/include/FunctionHook/Hook.h +++ b/include/FunctionHook/Hook.h @@ -1,14 +1,16 @@ #pragma once #include #include +#include namespace FunctionHooking { class Detour { private: void* source = nullptr; //The function to be hooked. void* destination = nullptr; //The function we are redirecting execution to. - uint8_t overwritten_bytes[13] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t hook_bytes[13] = {0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x41, 0xFF, 0xE2}; + + std::vector overwritten_bytes{}; + std::vector hook_bytes{}; void createHook(void* source_address, void* destination_address); public: void removeHook(); diff --git a/src/linux64/Hook.cpp b/src/linux64/Hook.cpp index 27298ea..ef63518 100644 --- a/src/linux64/Hook.cpp +++ b/src/linux64/Hook.cpp @@ -7,8 +7,11 @@ void FunctionHooking::Detour::createHook(void* source_address, void* destination source = source_address; destination = destination_address; + hook_bytes.insert(hook_bytes.begin(), {0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x41, 0xFF, 0xE2}); + overwritten_bytes.resize(hook_bytes.size()); + //Save the bytes to be overwritten from the function prelude. - memcpy(&overwritten_bytes, source_address, 13); + memcpy(overwritten_bytes.data(), source_address, hook_bytes.size()); //Put the destination address into the jump. memcpy(&hook_bytes[2], &destination_address, sizeof(void*)); @@ -17,24 +20,8 @@ void FunctionHooking::Detour::createHook(void* source_address, void* destination mprotect((void*)((uintptr_t)source_address & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_WRITE|PROT_EXEC); //Write the jmp to the beginning of the function prelude. - memcpy(source_address, hook_bytes, sizeof(hook_bytes)); + memcpy(source_address, hook_bytes.data(), hook_bytes.size()); //Make the memory page non-writable again. mprotect((void*)((uintptr_t)source_address & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_EXEC); -} - -void FunctionHooking::Detour::removeHook() { - - //Make the target memory page writable. - mprotect((void*)((uintptr_t)source & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_WRITE|PROT_EXEC); - - //Replace our hook with the bytes that were originally there. - memcpy(source, &overwritten_bytes, 13); - - //Make the memory page non-writable again. - mprotect((void*)((uintptr_t)source & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_EXEC); -} - -FunctionHooking::Detour::Detour(void *source_address, void *destination_address) { - createHook(source_address, destination_address); -} +} \ No newline at end of file diff --git a/src/linuxCommon/Hook.cpp b/src/linuxCommon/Hook.cpp new file mode 100644 index 0000000..5cc9b37 --- /dev/null +++ b/src/linuxCommon/Hook.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +void FunctionHooking::Detour::removeHook() { + + //Make the target memory page writable. + mprotect((void*)((uintptr_t)source & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_WRITE|PROT_EXEC); + + //Replace our hook with the bytes that were originally there. + memcpy(source, overwritten_bytes.data(), overwritten_bytes.size()); + + //Make the memory page non-writable again. + mprotect((void*)((uintptr_t)source & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_EXEC); +} + +FunctionHooking::Detour::Detour(void *source_address, void *destination_address) { + createHook(source_address, destination_address); +} \ No newline at end of file diff --git a/src/linuxRV64/Hook.cpp b/src/linuxRV64/Hook.cpp new file mode 100644 index 0000000..b13cc75 --- /dev/null +++ b/src/linuxRV64/Hook.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +void FunctionHooking::Detour::createHook(void* source_address, void* destination_address) { + source = source_address; + destination = destination_address; + + hook_bytes.insert(hook_bytes.begin(), { 0x17, 0x05, 0x00, 0x00, 0x03, 0x25, 0x05, 0x00, 0x67, 0x00, 0x0a, 0x00} ); + + overwritten_bytes.resize(hook_bytes.size() + 8); + + //Save the bytes to be overwritten from the function prelude + memcpy(overwritten_bytes.data(), source_address, hook_bytes.size()); + + //Calculate the offset. + intptr_t offset = (intptr_t)destination_address - (intptr_t)source_address; + + //Place the offset into the auipc instruction + memcpy(&hook_bytes[1], &offset, sizeof(uint32_t)); + + //Append the destination address after the instructions + hook_bytes.insert(hook_bytes.end(), (uint8_t*)&destination_address, (uint8_t*)&destination_address + sizeof(void*)); + + //Save the bytes to be overwritten from the function prelude. + memcpy(overwritten_bytes.data(), source_address, hook_bytes.size()); + + //Put the destination address into the jump. + memcpy(&hook_bytes[2], &destination_address, sizeof(void*)); + + //Make the target memory page writable. + mprotect((void*)((uintptr_t)source_address & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_WRITE|PROT_EXEC); + + //Write the jmp to the beginning of the function prelude. + memcpy(source_address, hook_bytes.data(), hook_bytes.size()); + + //Make the memory page non-writable again. + mprotect((void*)((uintptr_t)source_address & ~(sysconf(_SC_PAGE_SIZE)-1)), sysconf(_SC_PAGE_SIZE), PROT_READ|PROT_EXEC); +}