Update
This commit is contained in:
@@ -6,7 +6,14 @@ file(GLOB_RECURSE HEADERS "include/*.h")
|
|||||||
|
|
||||||
#TODO more architectures.
|
#TODO more architectures.
|
||||||
if (UNIX AND NOT APPLE)
|
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})
|
add_library(FunctionHook SHARED ${SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace FunctionHooking {
|
namespace FunctionHooking {
|
||||||
class Detour {
|
class Detour {
|
||||||
private:
|
private:
|
||||||
void* source = nullptr; //The function to be hooked.
|
void* source = nullptr; //The function to be hooked.
|
||||||
void* destination = nullptr; //The function we are redirecting execution to.
|
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<uint8_t> overwritten_bytes{};
|
||||||
|
std::vector<uint8_t> hook_bytes{};
|
||||||
void createHook(void* source_address, void* destination_address);
|
void createHook(void* source_address, void* destination_address);
|
||||||
public:
|
public:
|
||||||
void removeHook();
|
void removeHook();
|
||||||
|
@@ -7,8 +7,11 @@ void FunctionHooking::Detour::createHook(void* source_address, void* destination
|
|||||||
source = source_address;
|
source = source_address;
|
||||||
destination = destination_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.
|
//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.
|
//Put the destination address into the jump.
|
||||||
memcpy(&hook_bytes[2], &destination_address, sizeof(void*));
|
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);
|
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.
|
//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.
|
//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);
|
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);
|
|
||||||
}
|
|
20
src/linuxCommon/Hook.cpp
Normal file
20
src/linuxCommon/Hook.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <FunctionHook/Hook.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
40
src/linuxRV64/Hook.cpp
Normal file
40
src/linuxRV64/Hook.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <FunctionHook/Hook.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
Reference in New Issue
Block a user