unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); function GetExplorId:Cardinal; private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
var AsmBuf:Array [0..20] of Byte = ($B8,$00,$00,$00,$00,$68,$00,$00,$00,$00,$FF,$D0,$B8,$00,$00,$00,00,$6A,$00,$FF,$D0);
function EnabledDebugPrivilege(const bEnabled: Boolean):Boolean;var hToken: THandle; tp: TOKEN_PRIVILEGES; a: DWORD;const SE_DEBUG_NAME = 'SeDebugPrivilege';begin Result:=False; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken)) then begin tp.PrivilegeCount :=1; LookupPrivilegeValue(nil,SE_DEBUG_NAME ,tp.Privileges[0].Luid); if bEnabled then tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED else tp.Privileges[0].Attributes := 0; a:=0; AdjustTokenPrivileges(hToken,False,tp,SizeOf(tp),nil,a); Result:= GetLastError = ERROR_SUCCESS; CloseHandle(hToken); end;end;
function InjectDll(pid:cardinal;Dll:string):Cardinal;var hProc:Cardinal; wDllPath:PwideChar; pRemote:Pointer; cbSize:cardinal; TempVar:Cardinal;begin result:=0; if pid=0 then exit; EnabledDebugPrivilege(true); cbSize:= length(Dll)*2+21; GetMem(wDllPath,cbSize); StringToWideChar(Dll,wDllPath,cbSize); hProc:=OpenProcess(PROCESS_ALL_ACCESS,false,pid); try pRemote:=VirtualAllocEx( hProc, nil, cbSize, MEM_COMMIT, PAGE_READWRITE); if WriteProcessMemory(hProc,pRemote, wDllPath, cbSize, TempVar) then begin TempVar:=0; Result := CreateRemoteThread(hProc, nil, 0, GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW'), pRemote, 0, TempVar); end; finally CloseHandle(hProc); FreeMem(wDllPath); end;end;
function EjectDll(pid:cardinal;Dll:string):Cardinal;type PDebugModule = ^TDebugModule; TDebugModule = packed record Reserved: array [0..1] of Cardinal; Base: Cardinal; Size: Cardinal; Flags: Cardinal; Index: Word; Unknown: Word; LoadCount: Word; ModuleNameOffset: Word; ImageName: array [0..$FF] of Char; end; type PDebugModuleInformation = ^TDebugModuleInformation; TDebugModuleInformation = record Count: Cardinal; Modules: array [0..0] of TDebugModule; end; type PDebugBuffer = ^TDebugBuffer; TDebugBuffer = record SectionHandle: THandle; SectionBase: Pointer; RemoteSectionBase: Pointer; SectionBaseDelta: Cardinal; EventPairHandle: THandle; Unknown: array [0..1] of Cardinal; RemoteThreadHandle: THandle; InfoClassMask: Cardinal; SizeOfInfo: Cardinal; AllocatedSize: Cardinal; SectionSize: Cardinal; ModuleInformation: PDebugModuleInformation; BackTraceInformation: Pointer; HeapInformation: Pointer; LockInformation: Pointer; Reserved: array [0..7] of Pointer; end;const PDI_MODULES = $01; ntdll = 'ntdll.dll';var HNtDll: HMODULE;type TFNRtlCreateQueryDebugBuffer = function(Size: Cardinal;EventPair: Boolean): PDebugBuffer;stdcall; TFNRtlQueryProcessDebugInformation = function(ProcessId, DebugInfoClassMask: Cardinal; var DebugBuffer: TDebugBuffer): Integer;stdcall; TFNRtlDestroyQueryDebugBuffer = function(DebugBuffer: PDebugBuffer): Integer;stdcall;var RtlCreateQueryDebugBuffer: TFNRtlCreateQueryDebugBuffer; RtlQueryProcessDebugInformation: TFNRtlQueryProcessDebugInformation; RtlDestroyQueryDebugBuffer: TFNRtlDestroyQueryDebugBuffer;
function LoadRtlQueryDebug: LongBool; begin HNtDll := LoadLibrary(ntdll); if HNtDll <> 0 then begin RtlCreateQueryDebugBuffer := GetProcAddress(HNtDll, 'RtlCreateQueryDebugBuffer'); RtlQueryProcessDebugInformation := GetProcAddress(HNtDll, 'RtlQueryProcessDebugInformation'); RtlDestroyQueryDebugBuffer := GetProcAddress(HNtDll, 'RtlDestroyQueryDebugBuffer'); end; Result := Assigned(RtlCreateQueryDebugBuffer) and Assigned(RtlQueryProcessDebugInformation) and Assigned(RtlQueryProcessDebugInformation); end;
function ReleaseRtlQueryDebug: LongBool; begin result:=FreeLibrary(HNtDll); end;
var hProc:Cardinal; hMod:cardinal; TempVar:Cardinal; DbgBuffer: PDebugBuffer; i,j:integer; pd:PDWORD; pRemoteFunc:pointer;begin result:=0; if pid=0 then exit; EnabledDebugPrivilege(true); LoadRtlQueryDebug; DbgBuffer := RtlCreateQueryDebugBuffer(0, False); if Assigned(DbgBuffer) then try if RtlQueryProcessDebugInformation(pid, PDI_MODULES, DbgBuffer^) >= 0 then for i:=0 to DbgBuffer.ModuleInformation.Count-1 do if UpperCase(DbgBuffer.ModuleInformation.Modules[i].ImageName)= UpperCase(Dll) then begin hMod:=DbgBuffer.ModuleInformation.Modules[i].Base; j:=DbgBuffer.ModuleInformation.Modules[i].LoadCount; Break; end; finally RtlDestroyQueryDebugBuffer(DbgBuffer); ReleaseRtlQueryDebug; end; hProc:=OpenProcess(PROCESS_ALL_ACCESS,false,pid); try TempVar:=DWORD(GetProcAddress(GetModuleHandle('Kernel32'),'FreeLibrary')); pd:=@AsmBuf[1]; pd^:=TempVar; pd:=@AsmBuf[6]; pd^:=hMod; TempVar:=DWORD(GetProcAddress(GetModuleHandle('Kernel32'),'ExitThread')); pd:=@AsmBuf[13]; pd^:=TempVar; pRemoteFunc:=VirtualAllocEx( hProc, nil, 21, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if WriteProcessMemory(hProc, pRemoteFunc, @AsmBuf[0], 21, TempVar) then for i:=0 to j-1 do begin TempVar:=0; Result := CreateRemoteThread(hProc, nil, 0, pRemoteFunc, nil, 0, TempVar); end; finally CloseHandle(hProc); end;end; function TForm1.GetExplorId:Cardinal;begin GetWindowThreadProcessId(GetWindow(Handle,GW_HWNDLAST),@result);end;
procedure TForm1.Button1Click(Sender: TObject);begin InjectDll(GetExplorId,'c:/ExHook.Dll');end;
procedure TForm1.Button2Click(Sender: TObject);begin EjectDll(GetExplorId,'c:/ExHook.Dll');end;
end.