| | 字体大小 [大 中 小 ] |
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. 总结 .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: 本文源程序 | |