Created
March 1, 2021 00:00
-
-
Save ItsJustMeChris/1aeff828b43e6aa00a477b5c79da164c to your computer and use it in GitHub Desktop.
Code to perform a mid function hook using inline assembly on a unix / macos x86-64 system. GIST includes dummy program to test, offsets in main program should be valid when built.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <iostream> | |
#include <sys/mman.h> | |
#include <mach/i386/kern_return.h> | |
#include <mach/mach_init.h> | |
#include <mach/mach_vm.h> | |
#include <mach/vm_region.h> | |
#include <mach/vm_types.h> | |
#include <unistd.h> | |
#include <mach/host_info.h> | |
#include <mach/mach_host.h> | |
#include <mach/shared_region.h> | |
#include <mach/mach.h> | |
#include <mach-o/dyld.h> | |
#include <errno.h> | |
bool ApplyJump(uintptr_t* toHook, void* ourFunct, int len) { | |
std::cout << "Hook Location: " << std::hex << toHook << std::endl; | |
std::cout << "Hook Function: " << std::hex << ourFunct << std::endl; | |
std::cout << "Hook Length: " << std::hex << len << std::endl; | |
mach_vm_protect(mach_task_self(), (mach_vm_address_t)toHook, (mach_vm_size_t)len, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE | VM_PROT_COPY); | |
memset(toHook, 0x90, len); | |
uintptr_t relativeAddress = ((uintptr_t)ourFunct - (uintptr_t)toHook) - 5; | |
*(uintptr_t*)toHook = 0xE9; | |
*(uintptr_t*)((uintptr_t)toHook + 1) = relativeAddress; | |
mach_vm_protect(mach_task_self(), (mach_vm_address_t)toHook, (mach_vm_size_t)len, FALSE, VM_PROT_READ | VM_PROT_EXECUTE); | |
return true; | |
} | |
vm_address_t getBaseAddress(mach_port_t task) | |
{ | |
kern_return_t kret; | |
vm_region_basic_info_data_t info; | |
mach_vm_size_t size; | |
mach_port_t object_name; | |
mach_msg_type_number_t count; | |
vm_address_t firstRegionBegin; | |
vm_address_t lastRegionEnd; | |
vm_size_t fullSize = 0; | |
count = VM_REGION_BASIC_INFO_COUNT_64; | |
mach_vm_address_t address = 1; | |
int regionCount = 0; | |
int flag = 0; | |
while (flag == 0) { | |
//Attempts to get the region info for given task | |
kret = mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object_name); | |
if (kret == KERN_SUCCESS) { | |
if (regionCount == 0) { | |
firstRegionBegin = address; | |
regionCount += 1; | |
} | |
fullSize += size; | |
address += size; | |
} | |
else | |
flag = 1; | |
} | |
lastRegionEnd = address; | |
return firstRegionBegin; | |
} | |
mach_port_t getTaskForPID(pid_t pid) | |
{ | |
kern_return_t kern_return; | |
mach_port_t task; | |
kern_return = task_for_pid(mach_task_self(), pid, &task); | |
if (kern_return != KERN_SUCCESS) { | |
return 0; | |
} | |
return task; | |
} | |
uintptr_t hookAddr; | |
void doStuff() { | |
asm volatile ( | |
"mov %%eax, %0\n" | |
: | |
:"a"(69) | |
); | |
((void (*)(void)) hookAddr)(); | |
} | |
__attribute__((constructor)) void ctor(void) { | |
std::cout << ">>> DYLIB LOADED <<<" << std::endl; | |
pid_t pid = getpid(); | |
mach_port_t task = getTaskForPID(pid); | |
vm_address_t base = getBaseAddress(task); | |
std::cout << "Base found 0x" << std::hex << base << std::endl; | |
hookAddr = (base + 0x3CE6) + 0x9; | |
std::cout << "JMP [addr]: " << std::hex << hookAddr << std::endl; | |
ApplyJump((uintptr_t*)(base + 0x3CE6), (void*)doStuff, 0x5); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gcc main.cpp -o inline.bin -lstdc++ | |
gcc -dynamiclib dylib.cpp -o inline.dylib -lstdc++ | |
sudo DYLD_INSERT_LIBRARIES=inline.dylib ./inline.bin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <unistd.h> | |
int A = 50; | |
int main() { | |
while (1) { | |
A += 50; | |
std::cout << A << std::endl; | |
usleep(500); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for the example and explanation