分享
 
 
 

用跨进程子类化技术实现对其它进程消息的拦载

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

大家都知道每个窗口都有默认的窗口函数来进行对窗口消息的处理.

而子类化技术就是替换窗口的窗口函数为自己定义的函数的技术.例如下面的代码:

var

Form1: TForm1;

OldWndProc: Pointer;

implementation

{$R *.dfm}

function NewWndProc(hHwnd, Msg, wParam, lParam: LongWORD): Longint; stdcall;

begin

if Msg=WM_CLOSE then

exit;

Result := CallWindowProc(OldWndProc, hHwnd, Msg, wParam, lParam);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

{保存旧的窗口函数地址}

OldWndProc := Pointer(GetWindowLong(Self.Handle, GWL_WNDPROC));

{设置新的窗口函数为自定义函数}

SetWindowLong(Self.Handle, GWL_WNDPROC, Longint(@NewWndProc));

end;

这样在窗口建立时就对窗口实现了子类化,这时按下窗口的关闭按钮就会发现关不了窗口,因为新的窗口处理函数把WM_CLOSE消息过滤掉了,要取消子类化,只需要简单的把以前的窗口函数恢复过来就可以了.SetWindowLong(Self.Handle, GWL_WNDPROC, Longint(OldWndProc));

现在看来似乎很简单,只要对其它进程中的目标窗口进行子类化就可以实现对其消息的拦载监视了.但是在WIN32下,每一个进程都有自己独立的内存空间,新的窗口函数必须和目标窗口在同一个进程内,直接使用SetWindowLong(其它进程中窗口的句柄, GWL_WNDPROC, 新窗口函数)就会失败,所以就要想办法把我们的窗口函数代码放到目标进程内,这儿有二个办法,一是使用CreateRemoteThread在目标进程内建立线程,但这函数只在NT及以上操作系统实现,而且还要涉及到API地址重定位等问题,很麻烦(请参考http://www.csdn.net/develop/Read_Article.asp?Id=21079).另一个方法就是使用HOOK技术(SetWindowsHookEx,如果不知道,请先参考HOOK技术方面的文章),大家都知道,对其它进程进行HOOK时,此进程会自动加载HOOK过程所在的DLL,如果我们把窗口函数也放在DLL中,那窗口函数就相当于加载到了目标进程的地址空间中了,这方法简单易行.在这里我们就采用HOOK技术来实现跨进程子类化.

最后一个问题是如何在DLL中实现全局变量,因为DLL中的变量在每个进程加载这个DLL时都申请新的空间来存放变量,所以DLL中的变量在各个进程内不一样,可以利用内存文件映射,WM_COPYDATA等方法来实现全局变量.这儿采用内存文件映射.

现在需要的知识都已了解了,就让我们来看具体的代码吧(这儿是把所有函数放在一个DLL中):

library Hook;

uses

SysUtils,windows, Messages;

const

WM_UNSUBCLASS = WM_USER + 1001; {卸载子类化消息}

WM_NEWMESSAGE = WM_USER + 1002; {通知监视窗口拦到了新消息}

HOOK_EVENT_NAME = 'MyHook';

type

PMyDLLVar = ^TMyDLLVar;

TMyDLLVar = record

SubClass: Boolean; {是否已经子类化}

HookWindow, SpyWindow: LongWORD; {要安装HOOK的窗口及用于接收消息的窗口}

hHook: LongWORD; {HOOK句柄}

OldWndProc: pointer; {旧的窗口过程}

MsgHwnd: LongWORD;

Msg: TMessage;

end;

var

DLLData: PMyDLLVar;

{---------------------------------------}

{函数名:NewWndProc

{函数功能:新的窗口过程

{函数参数:hHwnd:窗口句柄 Msg:消息ID

{ wParam, lParam:消息参数

{函数返回值:下一个窗口过程的返回值

{---------------------------------------}

function NewWndProc(hHwnd, Msg, wParam, lParam: LongWORD): Longint; stdcall;

begin

if Msg = WM_UNSUBCLASS then {如果收到卸载子类化消息就恢复以前的WndProc}

begin

SetWindowLong(DLLData^.HookWindow, GWL_WNDPROC, longint(DLLData^.OldWndProc));

exit;

end;

{这儿是把收到的消息放在映射的内存中,我们自己的程序可以通过读这个内存来得到监视到的消息.}

DLLData^.Msg.Msg := Msg;

DLLData^.Msg.WParam := wParam;

DLLData^.Msg.LParam := lParam;

DLLData^.MsgHwnd := hHwnd;

{给监视窗口发送拦载新消息的消息}

SendMessage(DLLData^.SpyWindow, WM_NEWMESSAGE, 0, 0);

{这儿可以添加自己对目标进程消息处理的代码,因为己经是在目标进程的地址空间内,现在可以为所

欲为 ^_^)

Result := CallWindowProc(DLLData^.OldWndProc, hHwnd, Msg, wParam, lParam);

end;

{------------------------------------}

{过程名:HookProc

{过程功能:HOOK过程

{过程参数:nCode, wParam, lParam消息的相

{ 关参数

{------------------------------------}

procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;

var

hEvent: THandle;

begin

if not DllData^.SubClass then {如果此窗口未子类化}

begin {保存窗口过程地址并子类化}

if hEvent <> 0 then

begin

WaitForSingleObject(hEvent, INFINITE);

CloseHandle(hEvent);

end;

DLLData^.OldWndProc := pointer(GetWindowLong(DLLData^.HookWindow, GWL_WNDPROC));

SetWindowLong(DLLData^.HookWindow, GWL_WNDPROC, integer(@NewWndProc));

DLLData^.SubClass := True;

hEvent := OpenEvent(Synchronize, False, HOOK_EVENT_NAME);

end;

{调用下一个Hook}

CallNextHookEx(DLLData^.hHook, nCode, wParam, lParam);

end;

{------------------------------------}

{函数名:InstallHook

{函数功能:在指定窗口上安装HOOK

{函数参数:HWindow:要安装HOOK的窗口

{ SWindow:用于接收消息的窗口

{返回值:成功返回TRUE,失败返回FALSE

{------------------------------------}

function InstallHook(HWindow, SWindow: LongWORD):Boolean;stdcall;

var

ThreadID: LongWORD;

hEvent: THandle;

begin

Result := False;

DLLData^.hHook := 0;

DLLData^.HookWindow := HWindow;

DLLData^.SpyWindow := SWindow;

{得到指定窗口的线程ID}

ThreadID := GetWindowThreadProcessId(HWindow, nil);

{给指定窗口挂上钩子}

hEvent := CreateEvent(nil, True, False, HOOK_EVENT_NAME);

DLLData^.hHook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, ThreadID);

SetEvent(hEvent);

CloseHandle(hEvent);

if DLLData^.hHook > 0 then Result := True; {是否成功HOOK}

end;

{------------------------------------}

{过程名:UnHook

{过程功能:卸载HOOK

{过程参数:无

{------------------------------------}

procedure UnHook;stdcall;

begin

{发送卸载子类化消息给指定窗口}

SendMessage(DLLData^.HookWindow, WM_UNSUBCLASS, 0, 0);

DLLData^.SubClass := False;

{卸载Hook}

UnhookWindowsHookEx(DLLData^.hHook);

end;

{------------------------------------}

{过程名:DLL入口函数

{过程功能:进行DLL初始化,释放等

{过程参数:DLL状态

{------------------------------------}

procedure MyDLLHandler(Reason: Integer);

var

FHandle: LongWORD;

begin

case Reason of

DLL_PROCESS_ATTACH:

begin {建立文件映射,以实现DLL中的全局变量}

FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ff, 'MYDLLDATA');

if FHandle = 0 then

if GetLastError = ERROR_ALREADY_EXISTS then

begin

FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA');

if FHandle = 0 then Exit;

end else Exit;

DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

if DLLData = nil then

CloseHandle(FHandle);

end;

DLL_PROCESS_DETACH:

if Assigned(DLLData) then

begin

UnmapViewOfFile(DLLData);

DLLData := nil;

end;

DLL_THREAD_ATTACH:;

DLL_THREAD_DETACH:;

end;

end;

{$R *.res}

exports

InstallHook, UnHook, HookProc;

begin

DLLProc := @MyDLLHandler;

MyDLLhandler(DLL_PROCESS_ATTACH);

end.

编译这个DLL,然后在我们的程序中加载这个DLL,并调用InstallHook(目标窗口句柄, 自己窗口句柄)就可 以实现对目标窗口消息的监视了(在接收到WM_NEWMESSAGE消息时读映射的内存),调用UnHook则可以卸载掉子类化和HOOK.具休的代码还请读者自行编写.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有