Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ItsJustMeChris/1aeff828b43e6aa00a477b5c79da164c to your computer and use it in GitHub Desktop.
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.
#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);
}
gcc main.cpp -o inline.bin -lstdc++
gcc -dynamiclib dylib.cpp -o inline.dylib -lstdc++
sudo DYLD_INSERT_LIBRARIES=inline.dylib ./inline.bin
#include <iostream>
#include <unistd.h>
int A = 50;
int main() {
while (1) {
A += 50;
std::cout << A << std::endl;
usleep(500);
}
}
@ItsJustMeChris
Copy link
Author

This code injects a code cave and assigns a value to the registrar of our choice and then jumps back to normal program execution and the continued execution maintains our overwritten value, proving the proof of concept. It can further be validated by observing the value of the global pointer.

Program execution intention (without our hook) would be to print

50
100
150
200
...

After our hook is applied the assembly is prove to have changed the registrar and affected programmatic outcome by writing 69 instead of incrementing the global pointer.

It can further be proven by observing the global pointer at processBase + 0x8058

Credits to @benphelps for https://gist.github.com/ItsJustMeChris/1aeff828b43e6aa00a477b5c79da164c#file-inline-assembly-mid-function-hooking-macos-unix-cpp-L36

@Jamonek
Copy link

Jamonek commented Mar 8, 2021

Thank you for the example and explanation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment