Skip to content

Commit

Permalink
next
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuelTulach committed Sep 1, 2022
1 parent b8d6027 commit 1d74f8b
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,6 @@ MigrationBackup/

# Fody - auto-generated XML schema
FodyWeavers.xsd

# Linux builds
build
10 changes: 10 additions & 0 deletions Examples/LinuxUsermode/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.8)

project(LinuxUsermode)

file(GLOB_RECURSE sourcefiles
"src/*.h"
"src/*.c"
)

add_executable(LinuxUsermode ${sourcefiles})
6 changes: 6 additions & 0 deletions Examples/LinuxUsermode/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rm -rf ./build
mkdir build
cd build
cmake ..
make
./LinuxUsermode
47 changes: 47 additions & 0 deletions Examples/LinuxUsermode/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "../../../Source/LightHook.h"
#include <stdio.h>

static HookInformation testHook;
typedef int(*TestFunction_t)(int param1, int param2);

int __attribute__ ((noinline))TestFunction(int param1, int param2)
{
param2 -= param1;
param1 += param2;
for (int i = 0; i < 10; i++)
param1 += param2 * param2;

param2 *= param1;
param1 *= param2;
for (int i = 0; i < 5; i++)
param1 += param2 * param2;

printf("in func: %i\n", param1);
return param1;
}

int __attribute__ ((noinline)) HookedTestFunction()
{
printf("hook called\n");

TestFunction_t original = (TestFunction_t)testHook.Trampoline;
return original(0, 2);
//return 0;
}

int main()
{
int output = TestFunction(0, 1);
printf("before hook: %u\n", output);

testHook = CreateHook((void*)&TestFunction, (void*)&HookedTestFunction);
printf("size: %u\n", testHook.BytesToCopy);

int status = EnableHook(&testHook);
printf("status: %u\n", status);
printf("trampoline: 0x%p\n", testHook.Trampoline);

output = TestFunction(0, 1);
printf("after hook: %u\n", output);
return 0;
}
19 changes: 19 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2022 Samuel Tulach

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
46 changes: 37 additions & 9 deletions Source/LightHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static const unsigned char OP2_MODRM[] = { 0x0D, 0xA3, 0xA4, 0xA5, 0xAB, 0xAC, 0
* \param value Single byte value to search for
* \return Non-null if found, null of not
*/
inline int FindByte(const unsigned char* buffer, const unsigned long long maxLength, const unsigned char value)
static int FindByte(const unsigned char* buffer, const unsigned long long maxLength, const unsigned char value)
{
for (unsigned long long i = 0; i < maxLength; i++)
{
Expand All @@ -39,7 +39,7 @@ inline int FindByte(const unsigned char* buffer, const unsigned long long maxLen
* \param buffer Pointer to the current buffer address
* \param addressPrefix Instruction has legacy address size overwrite prefix
*/
inline void ParseModRM(unsigned char** buffer, const int addressPrefix)
static void ParseModRM(unsigned char** buffer, const int addressPrefix)
{
const unsigned char modRm = *++ * buffer;

Expand All @@ -65,7 +65,7 @@ inline void ParseModRM(unsigned char** buffer, const int addressPrefix)
* \param address Address of instruction to get length of
* \return Size in bytes of instruction
*/
inline int GetInstructionSize(const void* address)
static int GetInstructionSize(const void* address)
{
/*
* Based on length-disassembler by @Nomade040
Expand Down Expand Up @@ -135,7 +135,7 @@ inline int GetInstructionSize(const void* address)
* \param source Source address to copy data from
* \param size Amount of bytes to copy
*/
inline void CopyMemory(void* destination, void* source, unsigned long long size)
static void CopyMemory(void* destination, void* source, unsigned long long size)
{
unsigned char* dst = (unsigned char*)destination;
unsigned char* src = (unsigned char*)source;
Expand All @@ -161,7 +161,7 @@ static const unsigned char JUMP_CODE[] = { 0x49, 0xBF, 0xED, 0xFE, 0xED, 0xFE, 0
* \param targetFunction Function that will be called
* \return Hook information structure
*/
inline HookInformation CreateHook(void* originalFunction, void* targetFunction)
static HookInformation CreateHook(void* originalFunction, void* targetFunction)
{
HookInformation information;
information.Enabled = 0;
Expand Down Expand Up @@ -190,13 +190,19 @@ inline HookInformation CreateHook(void* originalFunction, void* targetFunction)
#undef CopyMemory
#endif
#endif
#ifdef __linux__
#include <stdio.h>
#include <sys/mman.h>
#include <assert.h>
#include <errno.h>
#endif

/**
* \brief Allocate RWX memory
* \param size Size in bytes
* \return Pointer to allocated memory region
*/
inline void* PlatformAllocate(const unsigned long long size)
static void* PlatformAllocate(const unsigned long long size)
{
#ifdef _WIN64
#ifdef _KERNEL_MODE
Expand All @@ -205,6 +211,9 @@ inline void* PlatformAllocate(const unsigned long long size)
return VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#endif
#else
#ifdef __linux__
return mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
#endif
(void)size;
return 0;
#endif
Expand All @@ -215,7 +224,7 @@ inline void* PlatformAllocate(const unsigned long long size)
* \param address Pointer to memory region
* \param size Size in bytes
*/
inline void PlatformFree(void* address, const unsigned long long size)
static void PlatformFree(void* address, const unsigned long long size)
{
#ifdef _WIN64
#ifdef _KERNEL_MODE
Expand All @@ -224,6 +233,9 @@ inline void PlatformFree(void* address, const unsigned long long size)
#else
VirtualFree(address, size, MEM_RELEASE);
#endif
#ifdef __linux__
munmap(address, size);
#endif
#endif
}

Expand All @@ -236,7 +248,7 @@ inline void PlatformFree(void* address, const unsigned long long size)
* \param protection Use PROTECTION_READ_WRITE_EXECUTE to make region RWX, otherwise platform specific
* \return Original protection value
*/
inline unsigned long long PlatformProtect(void* address, unsigned long long size, unsigned long long protection)
static unsigned long long PlatformProtect(void* address, unsigned long long size, unsigned long long protection)
{
#ifdef _WIN64
#ifdef _KERNEL_MODE
Expand Down Expand Up @@ -268,6 +280,22 @@ inline unsigned long long PlatformProtect(void* address, unsigned long long size
return original;
#endif
#endif
#ifdef __linux__
(void)size;
if (protection == PROTECTION_READ_WRITE_EXECUTE)
protection = PROT_READ | PROT_WRITE | PROT_EXEC;
else
protection = PROT_READ | PROT_EXEC; // unfortunately no way to read the original without parsing /proc/self/maps

int pageSize = getpagesize();
unsigned long long pageOffset = (unsigned long long)address % pageSize;
address -= pageOffset;

int status = mprotect(address, pageSize, protection);
assert(status == 0);

return protection;
#endif
}

#define CREATE_JUMP(name, targetAddress) \
Expand All @@ -280,7 +308,7 @@ inline unsigned long long PlatformProtect(void* address, unsigned long long size
* \param information Information structure created with CreateHook
* \return Non-zero when successful, zero when fail
*/
inline int EnableHook(HookInformation* information)
static int EnableHook(HookInformation* information)
{
if (information->Enabled)
return 1;
Expand Down

0 comments on commit 1d74f8b

Please sign in to comment.