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);
}
}
@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