You can find more on this subject on the web, so nothing new. The project is just a working example of a function un-hook, tested on a VM with Windows 10 x64 and BitDefender AV.
What makes AV Function Unhook different is the use of my own project, MCA, an x86/x86-64 instruction disassembler.
You can see an execution example clicking here: Unhook example
The entire source code was released for study purposes only
It search the desired function into the Export Table and after found performs a conversion from VA to the file offset. The address at witch VA is pointint to, will be then overwritten by the machine code found on disk skipping the amount of bytes got in the previous step.
You can find an example looking at the screenshots below:
Code with function hook | Code after un-hook |
---|---|
The unhook process is performed by this function:
void UnhookFunction(PINFO pInfo, struct instruction* on_disk_bytes, int dwNumberInstructions)
{
DWORD totalInstrLengths = 0;
for (int i = 0; i < dwNumberInstructions; i++)
{
totalInstrLengths += on_disk_bytes[i].length;
}
DWORD dwOldProtect;
VirtualProtect(pInfo->pInMemoryFunction, totalInstrLengths, PAGE_EXECUTE_READWRITE, &dwOldProtect);
DWORD dwLenPreviousIntr = 0;
for (int i = 0; i < dwNumberInstructions; i++)
{
memcpy((pInfo->pInMemoryFunction + dwLenPreviousIntr), on_disk_bytes[i].instr, on_disk_bytes[i].length);
dwLenPreviousIntr += on_disk_bytes[i].length;
}
VirtualProtect(pInfo->pInMemoryFunction, totalInstrLengths, dwOldProtect, &dwOldProtect);
}
Because MCA decode the instruction length (and its fields), you can specify the number of instructions from the function entry point.
av_hook.c
is the file (program, in a real case scenario) that set all that things up: call disasm, store references to memory, parse PE header & get the code, and patch the function. Furthermore compare memory before and after the unhook (its code is just to do the unhook on a simple "program").