This is “AFX LeakTest” written by Aphex. Delphi source contains a lot of useful material, but the most interesting part of the source is “unhook” unit, which gives you a simplest way for removing user and kernel hooks. Probably, you can build your own SSDT restoring utils.
Features:
- Scanning for user mode hooks
- Scanning for kernel mode hooks
- Removing User Hooks
- Removing Kernel Hooks
What inside:
- Delphi Hooking Library
- Access Control API interface
- NT Status Codes API interface
- Windows Types API interface
- Windows Base Types API interface
Code example:
Code://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.e_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.e_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, '...'); WriteLn(''); CodeLen := SizeOfProc(LoadedAddress); VirtualProtect(ExportedAddress, CodeLen, PAGE_EXECUTE_READWRITE, @OldProtection); CopyMemory(ExportedAddress, LoadedAddress, CodeLen); VirtualProtect(ExportedAddress, CodeLen, OldProtection, @OldProtection); 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')); ImageDosHeader := PImageDosHeader(ImageBase); ImageNtHeaders := PImageNtHeaders(cardinal(ImageDosHeader.e_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;
Please register or login to download attachments.