[標題]:簡易Windows密碼查看器
[時間]:2009-10-09
[摘要]:通過全局鉤子獲取當前鼠標處的窗口控件句柄,然後直接調用GetWindowText()獲取密碼文本。
[關鍵字]:密碼、查看、星號、全局鉤子、Hook、WM_COPYDATA、DLL、XP樣式
[環境]:Visual Studio 2008、Visual C++ 6.0
[作者]:天堂露珠 ([email protected])
[正文]:
[時間]:2009-10-09
[摘要]:通過全局鉤子獲取當前鼠標處的窗口控件句柄,然後直接調用GetWindowText()獲取密碼文本。
[關鍵字]:密碼、查看、星號、全局鉤子、Hook、WM_COPYDATA、DLL、XP樣式
[環境]:Visual Studio 2008、Visual C++ 6.0
[作者]:天堂露珠 ([email protected])
[正文]:
此密碼查看器原理:通過全局鉤子獲取當前鼠標處的窗口控件句柄,然後直接調用GetWindowText()獲取密碼文本。工程在VC++6.0和VS2008中編譯通過。
1、查看密碼的DLL工程 因爲查看密碼功能要用到全局鼠標Hook,所以要把功能放到一個DLL中。
PasswordViewerMouseHookDLL.h:
#pragma once
#ifdef PSWMOUSEHOOKDLL_API_EXPORTS
#define PSWMOUSEHOOKDLL_API __declspec(dllexport)
#else
#define PSWMOUSEHOOKDLL_API __declspec(dllimport)
#endif
#define PSWMOUSEHOOKDLL_API __declspec(dllexport)
#else
#define PSWMOUSEHOOKDLL_API __declspec(dllimport)
#endif
/*
Winty:2009-09-29
調用SetHook()設置Hook,但無需卸載Hook,DLLMain中有清理。
*/
//My Declaration================================
#define MAXCOUNT 200 //密碼最大長度
#define DWDATA_PSW_NOTIFY 1 //COPYDATASTRUCT的dwData自定義值
Winty:2009-09-29
調用SetHook()設置Hook,但無需卸載Hook,DLLMain中有清理。
*/
//My Declaration================================
#define MAXCOUNT 200 //密碼最大長度
#define DWDATA_PSW_NOTIFY 1 //COPYDATASTRUCT的dwData自定義值
//密碼信息結構體,用於發送
typedef struct tagPswNotify
{
char psw[MAXCOUNT];//password/text
POINT pt;//鼠標位置
HWND hWnd;//控件句柄
} PSWNOTIFY , *PPSWNOTIFY;
typedef struct tagPswNotify
{
char psw[MAXCOUNT];//password/text
POINT pt;//鼠標位置
HWND hWnd;//控件句柄
} PSWNOTIFY , *PPSWNOTIFY;
/*extern表示這裏只是變量聲明,變量定義在cpp文件中*/
extern PSWMOUSEHOOKDLL_API BOOL g_bReadySend;//WM_COPYDATA互斥的標誌,因爲WM_COPYDATA不能重疊
extern PSWMOUSEHOOKDLL_API HWND g_hWnd; //接收消息的窗體句柄
extern PSWMOUSEHOOKDLL_API HHOOK g_hhk; //鉤子句柄
extern PSWMOUSEHOOKDLL_API BOOL g_bView;//是否需要查看密碼
extern PSWMOUSEHOOKDLL_API BOOL g_bReadySend;//WM_COPYDATA互斥的標誌,因爲WM_COPYDATA不能重疊
extern PSWMOUSEHOOKDLL_API HWND g_hWnd; //接收消息的窗體句柄
extern PSWMOUSEHOOKDLL_API HHOOK g_hhk; //鉤子句柄
extern PSWMOUSEHOOKDLL_API BOOL g_bView;//是否需要查看密碼
//鼠標鉤子過程
PSWMOUSEHOOKDLL_API LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam );
//設置鉤子(可在窗口的OnInitDialog()中調用)
PSWMOUSEHOOKDLL_API void SetHook(HWND hWnd);
PSWMOUSEHOOKDLL_API LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam );
//設置鉤子(可在窗口的OnInitDialog()中調用)
PSWMOUSEHOOKDLL_API void SetHook(HWND hWnd);
PasswordViewerMouseHookDLL.cpp:
#include "stdafx.h"
#define PSWMOUSEHOOKDLL_API_EXPORTS
#include "PasswordViewerMouseHookDLL.h"
#include "PasswordViewerMouseHookDLL.h"
#include <stdio.h>
//進程間共享數據,還要在鏈接器選項裏添加:"/SECTION:.MyShare,RWS"
//或: #pragma comment(linker,"/SECTION:.MyShare,RWS")
//查看結果:dumpbin /headers *.DLL
#pragma data_seg(".MyShare")
HHOOK g_hhk = NULL;/*Hook句柄*/
HWND g_hWnd = NULL;/*接收消息的窗口句柄*/
BOOL g_bReadySend = TRUE;/*用於同步COPYDATA消息*/
#pragma data_seg()
#pragma comment(linker,"/SECTION:.MyShare,RWS")
//或: #pragma comment(linker,"/SECTION:.MyShare,RWS")
//查看結果:dumpbin /headers *.DLL
#pragma data_seg(".MyShare")
HHOOK g_hhk = NULL;/*Hook句柄*/
HWND g_hWnd = NULL;/*接收消息的窗口句柄*/
BOOL g_bReadySend = TRUE;/*用於同步COPYDATA消息*/
#pragma data_seg()
#pragma comment(linker,"/SECTION:.MyShare,RWS")
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
if(g_hhk != NULL)
{
UnhookWindowsHookEx(g_hhk);
g_hhk = NULL;
g_hWnd = NULL;
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
if(g_hhk != NULL)
{
UnhookWindowsHookEx(g_hhk);
g_hhk = NULL;
g_hWnd = NULL;
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
return TRUE;
}
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
if(nCode == HC_ACTION)
{
PMOUSEHOOKSTRUCT pMouseHookStruct
= reinterpret_cast<PMOUSEHOOKSTRUCT>(lParam);
LONG x = pMouseHookStruct->pt.x;
LONG y = pMouseHookStruct->pt.y;
HWND hWnd = pMouseHookStruct->hwnd;
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
if(nCode == HC_ACTION)
{
PMOUSEHOOKSTRUCT pMouseHookStruct
= reinterpret_cast<PMOUSEHOOKSTRUCT>(lParam);
LONG x = pMouseHookStruct->pt.x;
LONG y = pMouseHookStruct->pt.y;
HWND hWnd = pMouseHookStruct->hwnd;
HWND hWndFromPoint = ::WindowFromPoint(pMouseHookStruct->pt);
if(hWndFromPoint != g_hWnd && g_bReadySend)//不能獲取顯示密碼的文本框的內容
{
g_bReadySend = FALSE;
char psw[MAXCOUNT];
::GetWindowText(hWndFromPoint , psw , MAXCOUNT);
PSWNOTIFY pswNotify;
strcpy(pswNotify.psw , psw);
pswNotify.pt.x = x;
pswNotify.pt.y = y;
pswNotify.hWnd = hWndFromPoint;
{
g_bReadySend = FALSE;
char psw[MAXCOUNT];
::GetWindowText(hWndFromPoint , psw , MAXCOUNT);
PSWNOTIFY pswNotify;
strcpy(pswNotify.psw , psw);
pswNotify.pt.x = x;
pswNotify.pt.y = y;
pswNotify.hWnd = hWndFromPoint;
COPYDATASTRUCT cd;
cd.lpData = &pswNotify;
cd.cbData = sizeof(PSWNOTIFY);
cd.dwData = DWDATA_PSW_NOTIFY;
::SendMessage(g_hWnd, WM_COPYDATA, NULL , (LPARAM)(LPVOID)&cd);
}
}
cd.lpData = &pswNotify;
cd.cbData = sizeof(PSWNOTIFY);
cd.dwData = DWDATA_PSW_NOTIFY;
::SendMessage(g_hWnd, WM_COPYDATA, NULL , (LPARAM)(LPVOID)&cd);
}
}
return CallNextHookEx(g_hhk , nCode , wParam ,lParam);
}
}
void SetHook(HWND hWnd)
{
g_hWnd = hWnd;
g_hhk = SetWindowsHookEx(WH_MOUSE ,
MouseProc ,
GetModuleHandle("PasswordViewerMouseHookDLL") ,
NULL);
}
{
g_hWnd = hWnd;
g_hhk = SetWindowsHookEx(WH_MOUSE ,
MouseProc ,
GetModuleHandle("PasswordViewerMouseHookDLL") ,
NULL);
}
DLL要想將密碼消息發送到主窗口顯示,要用WM_COPYDATA消息(或其它進程間通信方式),否則會發送失敗。如果用WM_SETTEXT,因爲全局Hook發送的消息所帶的字符串指針lParam可能不能被主窗口訪問,從而造成訪問異常。
g_bReadySend的設置是因爲WM_COPYDATA消息不能連續發送,必須等前一條消息取走之後才能發送下一條消息。
2、顯示密碼的工程PasswordViewer 創建一個對話框工程PasswordViewer。
使用DLL步驟:
- 把PasswordViewerMouseHookDLL工程生成的PasswordViewerMouseHookDLL.dll、PasswordViewerMouseHookDLL.lib,以及PasswordViewerMouseHookDLL.h複製到PasswordViewer工程。
[參考資料]:
[附件]: - 在PasswordViewerDlg.cpp 中加入#include "PasswordViewerMouseHookDLL.h"和#pragma comment(lib , "PasswordViewerMouseHookDLL.lib")
如果要設置最後生成XP樣式的窗口,得在PasswordViewerDlg.cpp 中加入
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
PasswordViewerDlg.cpp主要代碼爲響應WM_COPYDATA消息,把消息內容顯示到窗口上:
BOOL CPasswordViewerDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
if(pCopyDataStruct->dwData == DWDATA_PSW_NOTIFY && !g_bReadySend)
{
PPSWNOTIFY pPswNotify = (PPSWNOTIFY)pCopyDataStruct->lpData;
{
if(pCopyDataStruct->dwData == DWDATA_PSW_NOTIFY && !g_bReadySend)
{
PPSWNOTIFY pPswNotify = (PPSWNOTIFY)pCopyDataStruct->lpData;
CString strMousePosition;
strMousePosition.Format("(%3d,%3d)" , pPswNotify->pt.x ,pPswNotify->pt.y);
m_strMousePosition = strMousePosition;
CString strPsw;
strPsw.Format("%s" , pPswNotify->psw);
m_strPsw = strPsw;
CString strHWnd;
strHWnd.Format("%p" , pPswNotify->hWnd);
m_strHWnd = strHWnd;
UpdateData(FALSE);
strMousePosition.Format("(%3d,%3d)" , pPswNotify->pt.x ,pPswNotify->pt.y);
m_strMousePosition = strMousePosition;
CString strPsw;
strPsw.Format("%s" , pPswNotify->psw);
m_strPsw = strPsw;
CString strHWnd;
strHWnd.Format("%p" , pPswNotify->hWnd);
m_strHWnd = strHWnd;
UpdateData(FALSE);
g_bReadySend = TRUE;
return TRUE;
}
else
{
CString str(_T("未發現窗口"));
m_strPsw = str;
}
else
{
CString str(_T("未發現窗口"));
m_strPsw = str;
UpdateData(FALSE);
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
}
}
}
別忘了要在CPasswordViewerDlg::OnInitDialog()中調用DLL的SetHook(m_hWnd),初始化全局鉤子。
3、運行 運行結果如圖:
【cpp_PasswordViewer.jpg】
[附件]:
PasswordViewer.zip:
PasswordViewer.exe、PasswordViewerMouseHookDLL.dll、工程源代碼