这次利用Win32编程写一个发送"Win32 Assembly,My First SendMessage Program !"
每个程序要发送消息至另一个程序的时候,通常使用SendMessage函数或PostMessage函数
两个函数的原型如下:
函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
和
函数原型:PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零。
观看原型就会发现,程序发送时,需要指定函数的参数HWND hWnd。
也就是获取发送窗口的句柄(这里的句柄是指接受程序的窗口的句柄)。
利用spy++获取程序句柄
spy++是一款非常好用的工具,可以帮助程序员查看获取各种窗口的句柄以及类等。
打开之后,我们点击搜索->查找窗口->拖动查找工具到目标程序的窗口上
就会返回当前窗口的属性了
我们点击确定
找到后鼠标右键点击属性
找到类
这里的类名,就是我们等会要搜索句柄的参数。
利用类名查找窗口句柄
我们已经知道了窗口的类名
现在就利用FindWindow函数查看窗口的句柄
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);
lpClassName参数指向类名,lpWindowName指向窗口名,如果有指定的类名和窗口的名字则表示成功返回一个窗口的句柄。否则返回零。 invoke FindWindow,addr szNotepad,NULL
invoke FindWindow,addr szNotepad,NULL
现在有了句柄之后,就要查看程序的窗口客户区在哪(总不能让我发送到菜单栏吧~)。
这里为了方便,使用ChildWindowFromPoint函数做定位查找
函数原型:HWND ChildWindowFromPoint (HWND hWnd, LONG xPoint, LONG yPoint); 函数功能:返回父窗口中包含了指定点的第一个子窗口的句柄。 函数参数:hWnd 父窗口的句柄 xPoint 点的X坐标,以像素为单位 yPoint 点的Y坐标,以像素为单位 其中坐标参数指屏幕坐标 返回值:发现包含了指定点的第一个子窗口的句柄。如未发现任何窗口,则返回hWnd(父窗口的句柄)。如指定点位于父窗口外部,则返回零。
代码如下
invoke ChildWindowFromPoint,ecx,55,55
其中ecx为父窗口句柄
然后我们一个个字节的读入到累加器,再利用WM_CHAR消息发送。
当然,这得做个循环。
mov esi,_lpsz @@: lodsb or al,al jz @F movzx eax,al invoke PostMessage,@Notepad,WM_CHAR,eax,1 jmp @B @@:
lodsb指令的作用是把ESI指向的存储单元读入到AL中去
其中,jz指令是为0则跳转
由于发送的字符串是以0结尾的,所以当字符串读完的时候,or al,al正好返回0
@F是向下一个@@标号跳转,@B则向上一个@@标号跳转。
整个程序代码如下:
;>>>>>>>>>>>>>>> .386 .model flat,stdcall option casemap:none ;>>>>>>>包含文件>>>>>>>> include windows.inc include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;>>>>>>>数据段>>>>>>>> .data? .const szText db 'Win32 Assembly,My First SendMessage Program !',0 szNotFound db 'Notepad Process Not Start !',0 szSendOk db 'Send Message Successful !',0 szNotepad db 'Notepad++',0 szSendBox db 'System MessageBox',0 ;>>>>>>>代码段>>>>>>>> .code ;>>>>>>>发送到记事本>>>>>>>> _SendMessage proc _lpsz local @Notepad pushad xor eax,eax invoke FindWindow,addr szNotepad,NULL .if eax mov ecx,eax invoke ChildWindowFromPoint,ecx,55,55 .else invoke MessageBox,NULL,offset szNotFound,offset szSendBox,MB_OK .endif .if eax mov @Notepad,eax mov esi,_lpsz @@: lodsb or al,al jz @F movzx eax,al invoke PostMessage,@Notepad,WM_CHAR,eax,1 jmp @B @@: invoke MessageBox,NULL,addr szSendOk,addr szSendBox,MB_OK .endif popad ret _SendMessage endp ;>>>>>>>主函数>>>>>>>> start: invoke _SendMessage,addr szText invoke ExitProcess,NULL ;>>>>>>>程序结束>>>>>>>> end start
代码中调用了MessageBox函数以验证是否发送成功。