终于搞定DLL HOOK的问题,注意变量的问题
- 发布于:2024-02-12
- 共 138 人围观
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;