終于搞定DLL HOOK的問題,注意變量的問題
- 發布于:2024-02-12
- 共 186 人圍觀
begin
if (Code = HC_ACTION) then
begin
if PMsg(Msg)^.Message = WM_LBUTTONDBLCLK then
PMsg(Msg)^.Message := 0;
if PMsg(Msg)^.Message = WM_LBUTTONUP then
begin
WM_USER_LButtonDown := RegisterWindowMessage('Tsinghua Tongfang Carputer Mouse Hook LButtonDown');
postMessage(DLLData^.Hook,WM_USER_LButtonDown,0,0);
end;
end;
Result :=CallNextHookEx(HookHandle, Code, WParam, Longint(@Msg));
end;
問題全部出在紅色部分,由于全局DLL的實例很多,導致“任何”DLL的內部變量離開了當時的函數都是不可信的,原來我在DLL的init里面注冊了該自定義消息,結果在真實的DLL里面(非調用進程HOOK情況下)消息全部都變成了0,所以沒有消息發給我的主程序。
這種變量可以現用現取,或者干脆就用定死的WM_USER+1000這種方式。但是如果是那種需要外部傳入的參數,必須使用系統提供的共享內存段來保存。
DLL初始化函數里面創建該共享內存段
procedure MyDLLHandler(Reason: Integer);
var
FHandle: LongWORD;
begin
case Reason of
DLL_PROCESS_ATTACH:
begin //建立文件映射,以實現DLL中的全局變量
FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,sizeof(TData), 'THTFMMI_DLLDATA');
if FHandle = 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'THTFMMI_DLLDATA');
if FHandle = 0 then Exit;
end else Exit;
DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if DLLData = nil then
begin
windows.Beep(8000,50);
CloseHandle(FHandle);
end;
end;
DLL_PROCESS_DETACH:
begin
if Assigned(DLLData) then
begin
UnmapViewOfFile(DLLData);
DLLData := nil;
h:=0;
end;
end;
end;
end;
調用者需要映射該共享內存段并設定參數,直接傳遞參數過來是不行的,除非接受傳參的函數里面立刻映射共享內存段并設定。
function TDataModule1.enableHook : boolean;
var
FHandle: LongWORD;
DLLData : PData;
begin
result := false;
FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'THTFMMI_DLLDATA');
if Fhandle = 0 then Exception.Create('Cannot open memory map in exe');
if FHandle > 0 then
begin
DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if DLLData <> nil then
begin
DLLData^.Hook := Application.MainForm.Handle;
result := EnableMsgHook;
end
else
begin
Exception.Create('Cannot map memory in exe');
closehandle(Fhandle);
end;
end;
end;
標簽: