We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Sep 2, 2010 12:21:22 AM
This example details how to remove hooks on usermode apis to ensure the free-running of your application in the presence of lowgrade security utilities.
Coder: Aphex
Operating System: Windows XP
Compiled: Delphi 2007
unit UsermodeUnhook;
interface
uses
Windows,
procedure RemoveUserHooks;
type
TSections = array [0..0] of TImageSectionHeader;
TStringArray = array [0..1024] of string;
implementation
//USER MODE UNHOOKING
function UnhookExport(hModule: HMODULE; FunctionName: pchar): boolean;
type
TSections = array [0..0] of TImageSectionHeader;
var
ModuleName: pchar;
ImageBase, LoadedImage, pImageBase, pSectionBase: pointer;
Module: THandle;
ModuleSize, BytesRead: dword;
ImageDosHeader: PImageDosHeader;
ImageNtHeaders: PImageNtHeaders;
ImageExportDirectory: PImageExportDirectory;
ExportLoop: integer;
ExportName: pchar;
ExportFunction: pointer;
PNames: pdword;
PFunctions: pdword;
PSections: ^TSections;
SectionLoop: integer;
SectionBase: pointer;
VirtualSectionSize, RawSectionSize: dword;
LoadedAddress: pbyte;
ExportedAddress: pbyte;
OldProtection: dword;
CodeLen: dword;
begin
Result := False;
GetMem(ModuleName, MAX_PATH + 1);
GetModuleFileName(hModule, ModuleName, MAX_PATH + 1);
ExportedAddress := nil;
LoadedAddress := nil;
Module := CreateFile(ModuleName, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
SetFilePointer(Module, 0, nil, FILE_BEGIN);
ModuleSize := GetFileSize(Module, nil);
GetMem(LoadedImage, ModuleSize);
ReadFile(Module, LoadedImage^, ModuleSize, BytesRead, nil);
CloseHandle(Module);
ImageDosHeader := PImageDosHeader(LoadedImage);
ImageNtHeaders := PImageNtHeaders(cardinal(ImageDosHeader._lfanew) + cardinal(LoadedImage));
ImageBase := VirtualAlloc(nil, ImageNtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_NOACCESS);
pImageBase := ImageBase;
SectionBase := VirtualAlloc(ImageBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
pSectionBase := SectionBase;
Move(LoadedImage^, SectionBase^, ImageNtHeaders.OptionalHeader.SizeOfHeaders);
PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
VirtualSectionSize := PSections[SectionLoop].Misc.VirtualSize;
RawSectionSize := PSections[SectionLoop].SizeOfRawData;
if VirtualSectionSize < RawSectionSize then VirtualSectionSize := RawSectionSize;
SectionBase := VirtualAlloc(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), VirtualSectionSize, MEM_COMMIT, PAGE_READWRITE);
FillChar(SectionBase^, VirtualSectionSize, 0);
Move(pointer(cardinal(LoadedImage) + PSections[SectionLoop].PointerToRawData)^, SectionBase^, RawSectionSize);
VirtualFree(SectionBase, 0, MEM_RELEASE);
end;
ImageExportDirectory := PImageExportDirectory(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + cardinal(ImageBase));
PNames := pointer(cardinal(ImageExportDirectory.AddressOfNames) + cardinal(ImageBase));
PFunctions := pointer(cardinal(ImageExportDirectory.AddressOfFunctions) + cardinal(ImageBase));
for ExportLoop := 0 to ImageExportDirectory.NumberOfNames - 1 do
begin
ExportName := pchar(pdword(PNames)^ + cardinal(ImageBase));
ExportFunction := pointer(pdword(PFunctions)^ + cardinal(ImageBase));
if lstrcmpi(ExportName, FunctionName) = 0 then
begin
LoadedAddress := ExportFunction;
Break;
end;
Inc(PNames);
Inc(PFunctions);
end;
ImageBase := pointer(GetModuleHandle(ModuleName));
ImageDosHeader := PImageDosHeader(ImageBase);
ImageNtHeaders := PImageNtHeaders(cardinal(ImageDosHeader._lfanew) + cardinal(ImageBase));
ImageExportDirectory := PImageExportDirectory(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + cardinal(ImageBase));
PNames := pointer(cardinal(ImageExportDirectory.AddressOfNames) + cardinal(ImageBase));
PFunctions := pointer(cardinal(ImageExportDirectory.AddressOfFunctions) + cardinal(ImageBase));
for ExportLoop := 0 to ImageExportDirectory.NumberOfNames - 1 do
begin
ExportName := pchar(pdword(PNames)^ + cardinal(ImageBase));
ExportFunction := pointer(pdword(PFunctions)^ + cardinal(ImageBase));
if lstrcmpi(ExportName, FunctionName) = 0 then
begin
ExportedAddress := ExportFunction;
Break;
end;
Inc(PNames);
Inc(PFunctions);
end;
if ((LoadedAddress <> nil) and (ExportedAddress <> nil)) then
begin
if ((ExportedAddress^ <> 0) and (LoadedAddress^ <> 0) and (ExportedAddress^ <> LoadedAddress^)) then
begin
Result := True;
// WriteLn('Unhooking ', FunctionName, '...');// readln;
CodeLen := SizeOfProc(LoadedAddress);
if (FunctionName='OpenFile') or (FunctionName='CreateFile')or (FunctionName='CreateProcess')or (FunctionName='CreateProcessEx')or (FunctionName='DeleteFile')or (FunctionName='FreeVirtualMemory')or (FunctionName='WriteVirtualMemory')or (FunctionName='SetInformationProcess')or (FunctionName='GetProcedureAddress')or (FunctionName='CreateProcessW')or (FunctionName='CreateProcessA')or (FunctionName='CopyFileW')or (FunctionName='VirtualProtect')or (FunctionName='GetProcAddress')or (FunctionName='GetModuleHandleW')or (FunctionName='----------LoadLibraryA')or (FunctionName='----------LoadLibraryW')or (FunctionName='GetModuleHandleW')or (FunctionName='CreateFileA')or (FunctionName='WinExec')or (FunctionName='OpenServiceW')or (FunctionName='OpenServiceA')or (FunctionName='ShellExecureW')or (FunctionName='ShellExecureExW')or (FunctionName='ShellExecureEx')or (FunctionName='ShellExecureA')or (FunctionName='AllocateVirtualMemory') then
begin WriteLn('Unhooking ', FunctionName, '...');
VirtualProtect(ExportedAddress, CodeLen, PAGE_EXECUTE_READWRITE, @OldProtection);
CopyMemory(ExportedAddress, LoadedAddress, CodeLen);
VirtualProtect(ExportedAddress, CodeLen, OldProtection, @OldProtection);
end;
end;
end;
FreeMem(ModuleName);
FreeMem(LoadedImage);
VirtualFree(pImageBase, 0, MEM_RELEASE);
VirtualFree(pSectionBase, 0, MEM_RELEASE);
end;
function CheckExports(ImageBase: pointer; ImageExportDirectory: PImageExportDirectory): boolean;
var
ExportLoop: integer;
ExportName: pchar;
PNames: pdword;
HooksFound: boolean;
begin
Result := False;
PNames := pointer(cardinal(ImageExportDirectory.AddressOfNames) + cardinal(ImageBase));
for ExportLoop := 0 to ImageExportDirectory.NumberOfNames - 1 do
begin
ExportName := pchar(pdword(PNames)^ + cardinal(ImageBase));
HooksFound := UnhookExport(HMODULE(ImageBase), ExportName);
if HooksFound = True then Result := True;
Inc(PNames);
end;
end;
procedure RemoveUserHooks;
var
ImageBase: pointer;
ImageDosHeader: PImageDosHeader;
ImageNtHeaders: PImageNtHeaders;
ImageExportDirectory: PImageExportDirectory;
begin
ImageBase := pointer(GetModuleHandle('kernel32.dll'));
ImageDosHeader := PImageDosHeader(ImageBase);
ImageNtHeaders := PImageNtHeaders(cardinal(ImageDosHeader._lfanew) + cardinal(ImageBase));
ImageExportDirectory := PImageExportDirectory(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + cardinal(ImageBase));
if ImageExportDirectory <> ImageBase then
begin
if ImageExportDirectory.NumberOfNames <> 0 then
begin
if not CheckExports(ImageBase, ImageExportDirectory) then WriteLn('No user mode hooks found!');
end;
end;
end;
end.
Only Delphi source code is included in the archive.