UsbHook

  UsbHook
字体大小 [大 中 小 ]

UsbHook 看到这个题目,你一定会想 Usb钩子是个什么东西,能干什么,还叫这么怪的名字,那给它起个更好听的名字吧UsbSpy Usb间谍。
  UsbSpy 产生的背景
  在上学的时候,教人工智能的老师有个习惯,就是从来不给别人烤自己上课用的幻灯片。上课的时候,插自己的U盘到教室的机子,然后上放幻灯片,从来不把幻灯片烤到教室的机子上。别的老师不光给学生烤自己的幻灯片,考试前还划重点。这个老师既不烤幻灯片,还不划重点。快到考试了,同学都有些急了,就策划说做一个什么工具当U盘一插就拷U盘上的全部东西到硬盘的预先指定位置。就因为这个原因UsbSpy诞生了,当U盘插入时截获系统消息:WM_DEVICECHANGE.得到U盘盘符。拷贝U盘所有目录下的.ppt文件到D:/ppt下。话不多讲,开始UsbSpy的制作吧。
  要写在前面的话
由于各种原因本文没有给出,UsbSpy全部源代码,本文附加了.Net下全局Hook的实现。留下了没有在.Net下动态加载/卸载一个的AppDomain中动态绑定事件的遗憾。UsbSpy的结局:最后虽然做出了UspSpy但是没人感给老师用的机子安装,最后还是熬夜复习赶考试了,最后还是通过了。

  全局Hook只能定义在Dll中下面是Dll的定义

  定义回调函数
LRESULT CALLBACK CallBackProc(int nCode,WPARAM wParam,LPARAM lParam)
{  
  MSG *pMsg = (MSG *)lParam;
  //HWND hWnd = ::FindWindow("#32770" , NULL);//"MfcHookApp"
  if ((pMsg->message == WM_DEVICECHANGE) && (!bInsert))
  {
    bInsert=true;
    MessageBox(NULL, "UsbOK!", "Hook Message", MB_OK);
    ::PostMessage(hWndMain, WM_INST, wParam, lParam);
  }
  return (CallNextHookEx(hHook, nCode, wParam, lParam));
}

  安装钩子
BOOL HOOKAPIFUNC InstallHook(HWND hWndm)
{
  //只针对 我的电脑这个进程
  //HWND hWnd = ::FindWindow("CabinetWClass", NULL);
  Get The handle.
  //DWORD dwThreadId = 0;
  Set the Thread number.
  //if (hWnd != NULL)
  //{
  //  dwThreadId = ::GetWindowThreadProcessId(hWnd, &dwThreadId);
  //}
  //if (dwThreadId != 0)
  //{
  //  hWndMain=hWndm;
  //  hHook = SetWindowsHookEx(WH_GETMESSAGE, CallBackProc, hInstance, dwThreadId);
  //  if (hHook == NULL||hWndMain == NULL)
  //  {
  //    MessageBox(NULL,"Hook Failed!", "Hook Message",MB_OK);
  //    return false;
  //  }
  //    MessageBox(NULL,"Hook Succeed!", "Hook Message",MB_OK);
  //    return true;
  //}

  //针对 所有进程 全局的
  hWndMain=hWndm;
  hHook = SetWindowsHookEx(WH_GETMESSAGE, CallBackProc, hInstance, 0);
  if (hHook == NULL||hWndMain == NULL)
  {
    MessageBox(NULL,"Hook Failed!", "Hook Message",MB_OK);
    return false;
  }
  MessageBox(NULL,"Hook Succeed!", "Hook Message",MB_OK);
  return true;
}
  卸载钩子
BOOL HOOKAPIFUNC UninstallHook()
{   
  return (BOOL)UnhookWindowsHookEx(hHook);
}

CMfcHookDllApp::CMfcHookDllApp()
{
  // TODO: add construction code here,
  // Place all significant initialization in InitInstance
}


// The one and only CMfcHookDllApp object


#pragma data_seg(".SHARED")
static HHOOK hHook = NULL; //定义全局钩子
#pragma data_seg()

#define HOOKAPIFUNC extern "C" __declspec(dllexport)
#define WM_INST (WM_USER+200) //定义用户自定义消息

  HoolApp部分

  安装钩子
void CMfcHookAppDlg::InstallHook(void)
{
  HINSTANCE hInstDLL = NULL;

  typedef BOOL (*insHookFunc)(HWND hWnd); //();表示不带参数这里表示带参数

  insHookFunc insHook = NULL;

  if ((hInstDLL = LoadLibrary((LPCTSTR)"MfcHookDll.dll")) != NULL)
  {
    //insHook = (insHookFunc)GetProcAddress(hInstDLL, "InstallHook");
    insHook = (insHookFunc)GetProcAddress(hInstDLL,MAKEINTRESOURCE(1));//使用函数名和用MAKEINTRESOURCE用名字编码也可以做到
    if (insHook != NULL)
    {
      insHook(m_hWnd);
    }
  }
}

  卸载钩子
void CMfcHookAppDlg::UninstallHook(void)
{
  HINSTANCE hInstDLL = NULL;
  typedef BOOL (*uninsHookFunc)();
  uninsHookFunc uninsHook = NULL;

  if ((hInstDLL = LoadLibrary((LPCTSTR)"MfcHookDll.dll")) != NULL)
  {
    uninsHook = (uninsHookFunc)GetProcAddress(hInstDLL,MAKEINTRESOURCE(2));
    //uninsHook = (uninsHookFunc)GetProcAddress(hInstDLL, "UninstallHook");
    if (uninsHook != NULL)
    {
      uninsHook();
    }
    FreeLibrary(hInstDLL);
  }
}

  定义用户回调函数
LRESULT CMfcHookAppDlg::OnInst(WPARAM wParam, LPARAM lParam)
{
  // TODO: 处理用户自定义消息
  MessageBox("OK","Hook");
  return 0;
}

BEGIN_MESSAGE_MAP(CMfcHookAppDlg, CDialog)
  ON_WM_PAINT()
  ON_WM_QUERYDRAGICON()
  //}}AFX_MSG_MAP
  ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnBnClickedButtonClose)
  ON_BN_CLICKED(IDC_BUTTON_INSTALL, OnBnClickedButtonInstall)
  ON_BN_CLICKED(IDC_BUTTON_UNINSTALL, OnBnClickedButtonUninstall)
  ON_MESSAGE(WM_INST, OnInst) //注意这个消息映射 是自己添加的不是系统生成的
  ON_WM_CLOSE()
END_MESSAGE_MAP()

  .Net下的全局钩子的定义 完全参考 http://www.codeproject.com/csharp/globalhook.asp 自己包装了Dll,Exe用工程引入了Dll
  Exe部分
void MainFormLoad(object sender, System.EventArgs e)
    {
      actHook= new DotNetHookDll(); // crate an instance
      // hang on events
      actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);
      actHook.KeyDown+=new KeyEventHandler(MyKeyDown);
      actHook.KeyPress+=new KeyPressEventHandler(MyKeyPress);
      actHook.KeyUp+=new KeyEventHandler(MyKeyUp);
    }
    
    public void MouseMoved(object sender, MouseEventArgs e)
    {
      labelMousePosition.Text=String.Format("x={0} y={1}", e.X, e.Y);
      if (e.Clicks>0) LogWrite("MouseButton   - " + e.Button.ToString());
    }
    
    public void MyKeyDown(object sender, KeyEventArgs e)
    {
      LogWrite("KeyDown   - " + e.KeyData.ToString());
    }
    
    public void MyKeyPress(object sender, KeyPressEventArgs e)
    {
      LogWrite("KeyPress   - " + e.KeyChar);
    }
    
    public void MyKeyUp(object sender, KeyEventArgs e)
    {
      LogWrite("KeyUp     - " + e.KeyData.ToString());
    }
    
    private void LogWrite(string txt)
    {
      textBox.AppendText(txt + Environment.NewLine);
      textBox.SelectionStart = textBox.Text.Length;
    }

  部分Dll
public event MouseEventHandler OnMouseActivity; //定义事件
    public event KeyEventHandler KeyDown;
    public event KeyPressEventHandler KeyPress;
    public event KeyEventHandler KeyUp;

    public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);//定义代理
  static int hMouseHook = 0; //Declare mouse hook handle as int.
    static int hKeyboardHook = 0; //Declare keyboard hook handle as int.

    //values from Winuser.h in Microsoft SDK.
    public const int WH_MOUSE_LL   = 14;  //mouse hook constant
    public const int WH_KEYBOARD_LL = 13;  //keyboard hook constant  

    HookProc MouseHookProcedure; //Declare MouseHookProcedure as HookProc type.
    HookProc KeyboardHookProcedure; //Declare KeyboardHookProcedure as HookProc type.

    //Declare wrapper managed POINT class.
    [StructLayout(LayoutKind.Sequential)]
      public class POINT
    {
      public int x;
      public int y;
    }

    //Declare wrapper managed MouseHookStruct class.
    [StructLayout(LayoutKind.Sequential)]
      public class MouseHookStruct
    {
      public POINT pt;
      public int hwnd;
      public int wHitTestCode;
      public int dwExtraInfo;
    }

    //Declare wrapper managed KeyboardHookStruct class.
    [StructLayout(LayoutKind.Sequential)]
      public class KeyboardHookStruct
    {
      public int vkCode;  //Specifies a virtual-key code. The code must be a value in the range 1 to 254.
      public int scanCode; // Specifies a hardware scan code for the key.
      public int flags; // Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
      public int time; // Specifies the time stamp for this message.
      public int dwExtraInfo; // Specifies extra information associated with the message.
    }


    private const int WM_MOUSEMOVE = 0x200;
    private const int WM_LBUTTONDOWN = 0x201;
    private const int WM_RBUTTONDOWN = 0x204;
    private const int WM_MBUTTONDOWN = 0x207;
    private const int WM_LBUTTONUP = 0x202;
    private const int WM_RBUTTONUP = 0x205;
    private const int WM_MBUTTONUP = 0x208;
    private const int WM_LBUTTONDBLCLK = 0x203;
    private const int WM_RBUTTONDBLCLK = 0x206;
    private const int WM_MBUTTONDBLCLK = 0x209;

    private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
    {
      // if ok and someone listens to our events
      if ((nCode >= 0) && (OnMouseActivity!=null))
      {
        
        MouseButtons button=MouseButtons.None;
        switch (wParam)
        {
          case WM_LBUTTONDOWN:
            //case WM_LBUTTONUP:
            //case WM_LBUTTONDBLCLK:
            button=MouseButtons.Left;
            break;
          case WM_RBUTTONDOWN:
            //case WM_RBUTTONUP:
            //case WM_RBUTTONDBLCLK:
            button=MouseButtons.Right;
            break;
        }
        int clickCount=0;
        if (button!=MouseButtons.None)
          if (wParam==WM_LBUTTONDBLCLK || wParam==WM_RBUTTONDBLCLK) clickCount=2;
          else clickCount=1;
        
        //Marshall the data from callback.
        MouseHookStruct MyMouseHookStruct = (MouseHookStruct) Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
        MouseEventArgs e=new MouseEventArgs(
          button,
          clickCount,
          MyMouseHookStruct.pt.x,
          MyMouseHookStruct.pt.y,
          0 );
        OnMouseActivity(this, e);
      }
      return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
    }

  没有实现的部分
  using System.Reflection;
  using System.Runtime;

  在动态加载的AppDomain中绑定一个事件到函数:
  void LoadDomain()
    {
      //Set the Application Domain Setup.
      AppDomainSetup domainSetup = new AppDomainSetup();
      domainSetup.ApplicationBase = System.Environment.CurrentDirectory;

      //Create Domain
      AppDomain Domain = AppDomain.CreateDomain("RemoteDomain", null, domainSetup);
      //Add the DotNetHookDll.dll
      Assembly assembly = Domain.Load("DotNetHookDll");
      
      object asseblyObject = assembly.CreateInstance("DotNetHook.DotNetHookDll");

      System.Type DotNetHookDll = asseblyObject.GetType();

      EventInfo[] eventInfors = DotNetHookDll.GetEvents() ;


      eventInfors[0].AddEventHandler(eventInfors[0],MouseEventHandler(MouseMoved));
//这一句总报错。
      AppDomain.Unload(Domain);
    }

  这个函数想做到:不用工程引入Dll,要动态加载Dll然后动态释放Dll,并动态绑定Dll中的一个Event到Exe中的一个Delegate.
Click to Open in New Window

  总结
  .Net下实现一个全局的Hook或者某个进程的Hook都不是很好写,写的都比较多,在这一点上没有MFC简单,但是.Net下的AppDomain应用程序域,这种先进的安全的概念,即使Dll出了问题,有异常产生,主程序动态释放这个域,主程序还可以继续执行,而MFC动态加载Dll,Dll里的函数有了问题,整个程序就死了。MFC在这点上远比不上.Net。

  参考文章
  http://www.microsoft.com/china/msdn/library/langtool/vcsharp/csharp05162002.mspx
  http://blog.joycode.com/percyboy/

  本文所有事例程序在中文WindowsXp Sp2 + VC7 下编译通过
   File: 本文源程序
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值