/* Terminology:
*
* fish = function to patch
* hook = patch to apply
* coolbox = overwritten bytes and stack fixer
* scales = memory security flags
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <windows.h>
#include "hooks.h"
#include "ollydisasm/disasm.h"
/*register int *stackp asm ("esp");
register int *basep asm ("ebp");*/
unsigned long CleanBiteOff(const uint8_t *ptr, size_t amount); // how many bytes should i overwrite to fit a jump and not leave garbage behind
int attachRawHook(uintptr_t fish, uintptr_t hook)
{
#define JMP_SIZE 5
unsigned long safeSize = CleanBiteOff((uint8_t*)fish, JMP_SIZE);
uint8_t *overwrite = malloc(safeSize);
overwrite[0] = 0xE9;//call e8 -- jmp e9
for (int i = JMP_SIZE; i < safeSize; i++)
overwrite[i] = 0x90;
DWORD oldScales, newScales;
//__asm("int $3");
uint8_t* coolbox;
#define XCHG_SIZE 13
#define FOOTER_SIZE 2*JMP_SIZE+XCHG_SIZE
if ((coolbox = VirtualAlloc(NULL, safeSize + FOOTER_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
return __HOOK_VIRTUALALLOC_COOLBOX;
uintptr_t relative = (uintptr_t)coolbox + safeSize - fish;
memcpy(&overwrite[1], &relative, JMP_SIZE-1);
memcpy(coolbox, (void*)(fish), safeSize);
relative = -relative;
/*
push ecx
mov ecx, %coolbox
xchg dword [esp+4], ecx
xchg dword[esp], ecx
{0x51,0xB9,0,0,0,0,0x87,0x4C,0xE4,0x04,0x87,0x0C,0xE4}
*/
#define FOUR_BYTES 0,0,0,0
uint8_t coolboxfooter[FOOTER_SIZE] = {0xE9,FOUR_BYTES,0x51,0xB9,FOUR_BYTES,0x87,0x4C,0xE4,0x04,0x87,0x0C,0xE4, 0xE9/*,FOUR_BYTES*/};
memcpy(&coolboxfooter[1], &relative, JMP_SIZE-1);
memcpy(&coolboxfooter[JMP_SIZE+2], &coolbox, JMP_SIZE-1);
relative = hook - ((uintptr_t)coolbox + safeSize + FOOTER_SIZE);
memcpy(&coolboxfooter[JMP_SIZE+XCHG_SIZE+1], &relative, JMP_SIZE-1);
memcpy(coolbox+safeSize, coolboxfooter, FOOTER_SIZE);
if (VirtualProtect((LPVOID) fish, safeSize, PAGE_READWRITE, &oldScales) == 0)
return __HOOK_PROTECTION_DISABLE;
memcpy((void*)fish, overwrite, safeSize);
if (VirtualProtect((LPVOID)fish, safeSize, oldScales, &newScales) == 0)
return __HOOK_PROTECTION_ENABLE;
return __HOOK_ALL_OK;
}
unsigned long CleanBiteOff(const uint8_t *ptr, size_t amount)
{
static t_disasm disasm;
unsigned long size = 0;
do {size += Disasm(ptr+size, 16, 0x00401AAC, &disasm, DISASM_SIZE);} while(size < amount);
return size;
}