需要一個用來注入的dll(inject.dll)及一個調用程序(caller.exe)
流程:
caller.exe
procedure TestHook;
var pwnd,hChild, hwndInject :hwnd;
msg:tmsg;
begin
//通過窗口標題用FindWindow找到要注入的程序的主窗口句柄pwnd
pwnd := findwindow('Progman',nil);
//用FindwindowEx(hMain,0,nil,nil)找到要處理的子窗口句柄hChild
hChild := findWindowEx(pwnd,0,nil,nil);
//用getwindowThreadProcessid(hChild,nil)找到要注入的線程
dwThreadID := getwindowThreadProcessid(hChild,nil);
//調用 inject.dll的SetInjectHook方法
SetInjectHook(dwThreadID);
//等待消息返回
getmessage(msg,0,0,0);
//找到注入的窗口
hwndInject:= findwindow(nil,'InjectForm');
//發送控制消息,將目標窗體的句柄作為wparam,控制參數以lparam傳入
sendMessage( hwndInject, wm_app,hChild,integer(true));
//關閉注入的窗口
sendMessage( hwndInject,wm_close,0,0);
//等待窗口關閉
sleep(500);
//檢查是否成功關閉
assert(not iswindow( hwndInject));
//去掉掛鉤
setDipsHook(0);
end;
//下面說明 Inject.dll的SetInjectHook的具體操作
在全局定義以下變量
var
g_hhook :Hhook=0;
g_dwThreadidInject :dword=0;
g_hInjectfrm:hwnd;
function SetInjectHook(dwThreadid:DWORD):boolean;
begin
result := false;
//如果線程標志為0則用於去掉鉤子,否則進行動態庫注入
if dwThreadid<>0 then
begin
assert(g_hhook=0);
//保存當前線程的ID到 g_dwThreadidInject
g_dwThreadidInject := getCurrentThreadid;
//下一個GetMessage的鉤子到目標線程
//GetMsgProc是在下面定義的一個函數,在第一次調用時將自定義的form在目標線程中創建出來
//這樣就能通過這個自定義的form對目標線程進行進程內控制了
g_hhook := setWindowsHookEx(wh_getMessage,GetMsgProc,hInstance,dwThreadid);
result := g_hhook <> null;
if result then
//發一個空的信息以便於立即創建這個自定義form
result := postThreadMessage(dwThreadid, wm_Null,0,0);
//等待半秒鐘,以保證調用者可以找到這個剛創建的form
sleep(500);
end else
begin
assert(g_hhook<>0);
//去掉鉤子
result := unHookWindowsHookEx(g_hhook);
g_Hhook := 0;
end;
end;
//定義一個全局的是否第一個消息的標志
var
fFirstTime:boolean = true;
//這個函數用於在收到第一個消息時創建自定義窗體,以便於遠程控制
function GetMsgProc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT; stdcall;
begin
//如果是第一次
if fFirstTime then
begin
fFirstTime := false;
//創建窗體
InjectFrm := TinjectFrm.create(nil);
//保存窗體句柄
g_hInjectfrm := InjectFrm.handle;
end;
//調用默認處理,這一句可不能忘記
result := callNexthookEx(g_hhook,code,wparam,lparam);
end;