键盘间谍(二)

阻止键盘间谍
 
 不被偷窥的Edit控件

 不被偷窥的Edit控件在每次用户敲键以后都会产生一些随机键盘事件。键盘间谍将会捕捉到用户的键盘事件和控件创建的虚假事件,从而很难判断真实敲键的内容。另一方面,用户的输入是被保存在控件的成员变量中的,应用程序不会受到影响。虚假键盘事件是利用SendInput API函数产生的。我分别实现了MFC和C#可用的控件。
 
 不被偷窥的Edit控件假定SendInput产生键盘事件的速度远快于用户本身的输入,但这可能导致在一些较慢的机器上, 控件会返回错误的用户输入,尤其是C#的实现中。
 
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;
}

删除间谍类库(SpyRemover)

基于钩子的间谍程序都是依赖于存放钩子程序的DLL文件的,因此应用程序的进程中通过调用FreeLibrary API移除掉钩子DLL,将会使键盘间谍钩子失效。SpyRemover的构造函数中创建一个授权模块的列表,然后通过枚举进程所有已加载的模块来检测未授权的模块,键盘间谍的钩子DLL也在其中。

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;
   
  //Take a snapshot of all modules in the process.
  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
  if( hModuleSnap == INVALID_HANDLE_VALUE )
    return;
 
  me32.dwSize = sizeof( MODULEENTRY32 );
 
  //Retrieve information about the first module (application.exe)
  if( !Module32First( hModuleSnap, &me32 ) )
  {
      CloseHandle( hModuleSnap );    
      return;
  }
 
  //Walk the module list of the process
  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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值