Example Code

type PIMAGE_LOAD_NOTIFY_ROUTINE = ^IMAGE_LOAD_NOTIFY_ROUTINE; IMAGE_LOAD_NOTIFY_ROUTINE = procedure(lpImageBase: PVOID; lpImageName: PWChar; bLoaded: BOOL); stdcall; function SetLoadImageCallback(const lpCallback: IMAGE_LOAD_NOTIFY_ROUTINE): BOOL; stdcall; { Registers a callback function to receive load/unload image information. No API hooks are needed for SetLoadImageCallback() to work which is a plus. You are notified early in the image load sequence and before the module has executed its entry point. SetLoadImageCallback() is useful in many situations such as code hooking/unhooking, denying the load of dynamically linked DLLs (filtering), debugging, DLL information logging etc. *Note* Vista+ support only. On XP/2k3 GetLastError() will return ERROR_CALL_NOT_IMPLEMENTED } // Below is an example of how to deny a DLL from loading dynamically while printing out module debug information procedure Callback(lpImageBase: PVOID; lpImageName: LPWSTR; bLoaded: BOOL); stdcall; var dwOP: DWORD; lpOEP: PVOID; const // XOR EAX, EAX // RET Buf: Array [0..2] of Byte = ($33, $C0, $C3); Event: Array [False..True] of String = ('Unloaded', 'Loaded'); begin OutputDebugStringW(PWChar(Format('Event: %s'#13#10'Module: %s'#13#10'Base Address: 0x%x', [Event[bLoaded], lpImageName, HMODULE(lpImageBase)]))); if (bLoaded) then begin if lstrcmpiW(lpImageName, 'c:\deny.dll') = 0 then begin lpOEP := PVOID(ULONG_PTR(lpImageBase) + PImageNtHeaders(ULONG_PTR(PImageDosHeader(lpImageBase)^._lfanew) + ULONG_PTR(lpImageBase))^.OptionalHeader.AddressOfEntryPoint); if VirtualProtect(lpOEP, sizeof(Buf), PAGE_READWRITE, @dwOP) then begin MoveMemory(lpOEP, @Buf, sizeof(Buf)); VirtualProtect(lpOEP, sizeof(Buf), dwOP, @dwOP); FlushInstructionCache(GetCurrentProcess(), nil, 0); end; end; end; end; initialization SetLoadImageCallback(@Callback); finalization RemoveLoadImageCallback(); end.