发现很久没写日志了,也发现自己以前写的东西真的没点技术含量!主要是因为底子薄,不敢出来露怯,怕广大同志们所为不齿。这次的东西稍微有点技术,因为涉及了钩子,因为涉及了一些底层的API。程序的主要功能如下:
- 获取鼠标所在位置窗口的句柄以及类名
- 激活一些应用程序的灰化按钮
拦取鼠标信息,钩子名称是WH_MOUSE,不同的钩子涉及到不同的钩子信息:
WH_MOUSE :
- nCode 为HC_ACTION 或 HC_NOREMOVE
- wParam 包含鼠标的事件消息
- lParam 指向MOUSEHOOKSTRUCT型结构体变量的指针
- return value: 如果不处理返回0,否则返回非0值
MHook.asm源代码如下,我们的任务是将它封装成DLL,并且将.bss段编译成共享
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .386 .model flat, stdcall option casemap :none ;------------------------------------------------------------------ include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include macro.asm ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< WM_MOUSEHOOK equ WM_USER + 4 .data? hHook dd ? hWnd dd ? .data hInstance dd ? ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .code DLLEntry proc hInstDLL, dwReason, dwReserved mov eax,dwReason .if eax == DLL_PROCESS_ATTACH push hInstDLL pop hInstance .endif mov eax,TRUE ret DLLEntry endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HookProc proc _nCode, _wParam, _lParam invoke CallNextHookEx,hHook,_nCode,_wParam,_lParam mov edx,_lParam assume edx:ptr MOUSEHOOKSTRUCT invoke WindowFromPoint,[edx].pt.x,[edx].pt.y invoke PostMessage,hWnd,WM_MOUSEHOOK,eax,0 assume edx:nothing xor eax,eax ret HookProc endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< InstallHook proc _hWnd push _hWnd pop hWnd invoke SetWindowsHookEx,WH_MOUSE,offset HookProc,hInstance,NULL mov hHook,eax ret InstallHook endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< UninstallHook proc invoke UnhookWindowsHookEx,hHook ret UninstallHook endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end DLLEntry
主函数内容主要是处理WM_MOUSEHOOK消息,这是我们自定义的消息,值为WM_USER + 4,Spy--.asm代码如下:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .386 .model flat, stdcall option casemap :none ;------------------------------------------------------------------ include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include shell32.inc includelib shell32.lib include mhook.inc includelib mhook.lib include macro.asm ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ICO_MAIN equ 1000 DLG_MAIN equ 100 IDC_ENABLEWINDOW equ 101 IDC_FGHandle equ 102 IDC_CLASSNAME equ 103 IDC_HANDLE equ 104 IDC_WNDPROC equ 105 IDC_CURSORPOS equ 106 IDC_ABOUT equ 107 IDC_HOOK equ 108 IDC_EXIT equ 109 IDC_HELPER equ 110 DLG_HELP equ 200 WM_MOUSEHOOK equ WM_USER + 4 ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .data? hInstance dd ? hMutex dd ? .data HookFlag dd FALSE EnableFlag dd FALSE ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .code ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _ProcDlgHelp proc uses ebx edi esi _hWnd, _wMsg, _wParam, _lParam mov eax,_wMsg .if eax == WM_COMMAND mov eax,_wParam .if ax == IDOK invoke EndDialog,_hWnd,NULL .endif .elseif eax == WM_CLOSE invoke EndDialog,_hWnd,NULL .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgHelp endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _EnableButton proc _hWnd, _lParam invoke IsWindowEnabled,_hWnd .if ! eax invoke EnableWindow,_hWnd,TRUE .endif mov eax,TRUE ret _EnableButton endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _ProcDlgMain proc uses ebx edi esi hWnd, wMsg, wParam, lParam local @szBuffer[128]:BYTE local @szBufferNew[128]:BYTE local @stPos:POINT mov eax,wMsg .if eax == WM_MOUSEHOOK invoke GetDlgItemText,hWnd,IDC_HANDLE,addr @szBuffer,128 invoke wsprintf,addr @szBufferNew,CTXT("%lX"),wParam invoke lstrcmpi,addr @szBuffer,addr @szBufferNew .if eax invoke SetDlgItemText,hWnd,IDC_HANDLE,addr @szBufferNew .endif invoke GetDlgItemText,hWnd,IDC_CLASSNAME,addr @szBuffer,128 invoke GetClassName,wParam,addr @szBufferNew,128 invoke lstrcmpi,addr @szBuffer,addr @szBufferNew .if eax invoke SetDlgItemText,hWnd,IDC_CLASSNAME,addr @szBufferNew .endif invoke GetDlgItemText,hWnd,IDC_WNDPROC,addr @szBuffer,128 invoke GetClassLong,wParam,GCL_WNDPROC invoke wsprintf,addr @szBufferNew,CTXT("%lX"),eax invoke lstrcmpi,addr @szBuffer,addr @szBufferNew .if eax invoke SetDlgItemText,hWnd,IDC_WNDPROC,addr @szBufferNew .endif invoke GetCursorPos,addr @stPos invoke wsprintf,addr @szBuffer,CTXT("%ld, %ld"),@stPos.x,@stPos.y invoke SetDlgItemText,hWnd,IDC_CURSORPOS,addr @szBuffer ;---------------------------------- ; 根据标志位来判断是否执行激活按钮选项 ;---------------------------------- .if EnableFlag invoke GetForegroundWindow push eax invoke wsprintf,addr @szBuffer,CTXT("%lX"),eax invoke SetDlgItemText,hWnd,IDC_FGHandle,addr @szBuffer pop eax invoke EnumChildWindows,eax,offset _EnableButton,NULL .endif .elseif eax == WM_COMMAND mov eax,wParam .if ax == IDC_ENABLEWINDOW invoke IsDlgButtonChecked,hWnd,IDC_ENABLEWINDOW .if eax == BST_CHECKED mov EnableFlag,TRUE .else mov EnableFlag,FALSE invoke SetDlgItemText,hWnd,IDC_FGHandle,NULL .endif .elseif ax == IDC_HOOK .if HookFlag == FALSE invoke InstallHook,hWnd .if eax mov HookFlag,TRUE invoke SetDlgItemText,hWnd,IDC_HOOK,CTXT("&UnHook") .endif .else invoke UninstallHook mov HookFlag,FALSE invoke SetDlgItemText,hWnd,IDC_HOOK,CTXT("&Hook") invoke SetDlgItemText,hWnd,IDC_CLASSNAME,NULL invoke SetDlgItemText,hWnd,IDC_HANDLE,NULL invoke SetDlgItemText,hWnd,IDC_WNDPROC,NULL invoke SetDlgItemText,hWnd,IDC_CURSORPOS,NULL invoke SetDlgItemText,hWnd,IDC_FGHandle,NULL .endif .elseif ax == IDC_ABOUT invoke ShellExecute,hWnd,CTXT("open"),CTXT("http://blog.csdn.net/sunweiqq"),NULL,NULL,SW_SHOW .elseif ax == IDC_HELPER invoke DialogBoxParam,hInstance,DLG_HELP,hWnd,offset _ProcDlgHelp,NULL .elseif ax == IDC_EXIT invoke SendMessage,hWnd,WM_CLOSE,0,0 .endif .elseif eax == WM_INITDIALOG invoke LoadIcon,hInstance,ICO_MAIN invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE .elseif eax == WM_CLOSE .if HookFlag == TRUE invoke UninstallHook .endif invoke EndDialog,hWnd,NULL .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< start: invoke CreateMutex,0,FALSE,CTXT("ONLY_ONE") mov hMutex,eax invoke GetLastError .if eax == ERROR_ALREADY_EXISTS invoke MessageBox,NULL,CTXT("程序已经有个实例在运行!"),NULL,MB_ICONWARNING jmp GoEnd .endif invoke LoadLibrary,CTXT("Splash.dll") .if eax invoke FreeLibrary,eax .else invoke MessageBox,NULL,CTXT("Splash.dll 丢失或装载失败"),NULL,MB_OK or MB_ICONERROR jmp @F .endif invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL @@: invoke CloseHandle,hMutex GoEnd: invoke ExitProcess,NULL ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end start
当然程序中也用到了另外一个Splash.dll,启动画面的功能组件,没什么技术,就不拿出来露怯了。另外还想完成的功能是:
- 像Jeffrey的SPY++一样有截取消息的功能
- 有个探取按钮,当鼠标点在上面的时候,光标形状变成一个小圆,并且光标所到之处能显示出来控件的形状,我想主要涉及到一些绘图函数,很容易解决
如下图:
本程序截图如下: