There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5057219    Comments: 173    
 日历归档
<<  <  2024 - 04  >  >>
SuMoTuWeThFrSa
 123456
78910111213
14151617181920
21222324252627
282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年4月18日 星期四 RSS CLI Mine Sweeper. In Javascript.

  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: 本文源程序
  Posted @ 8/29/2005 11:38:32 PM | Hits (50202) | Comments (4

  Comment
 #re:UsbHook  11/28/2010 3:12:18 PM  sdads
加密你放上边干吗 晕死
 #re:UsbHook  12/22/2005 5:16:33 PM  guest
加密干什么 不够意思
 #re:UsbHook  12/15/2005 9:46:48 PM  淡如云烟
怎么截获U盘被加进系统的消息呢?
好象里面就有截获鼠标和键盘消息的呀?
怎么获得U盘的盘符呢?
 #re:UsbHook  10/31/2005 6:01:44 PM  游客
放上来下载还加密
  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code