日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# Hook原理及EasyHook简易教程

發布時間:2024/9/20 C# 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# Hook原理及EasyHook简易教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

  在說C# Hook之前,我們先來說說什么是Hook技術。相信大家都接觸過外掛,不管是修改游戲客戶端的也好,盜取密碼的也罷,它們都是如何實現的呢?

  實際上,Windows平臺是基于事件驅動機制的,整個系統都是通過消息的傳遞來實現的。當進程有響應時(包括響應鼠標和鍵盤事件),則Windows會向應用程序發送一個消息給應用程序的消息隊列,應用程序進而從消息隊列中取出消息并發送給相應窗口進行處理。

  而Hook則是Windows消息處理機制的一個平臺,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達后,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。

  所以Hook就可以實現在鍵盤/鼠標響應后,窗口處理消息之前,就對此消息進行處理,比如監聽鍵盤輸入,鼠標點擊坐標等等。某些盜號木馬就是Hook了指定的進程,從而監聽鍵盤輸入了什么內容,進而盜取賬戶密碼。

C# Hook

  我們知道C#是運行在.NET平臺之上,而且是基于CLR動態運行的,所以只能操作封裝好的函數,且無法直接操作內存數據。而且在C#常用的功能中,并未封裝Hook相關的類與方法,所以如果用C#實現Hook,必須采用調用WindowsAPI的方式進行實現。

  WindowsAPI函數屬于非托管類型的函數,我們在調用時必須遵循以下幾步:

  1、查找包含調用函數的DLL,如User32.dll,Kernel32.dll等。

  2、將該DLL加載到內存中,并注明入口

  3、將所需參數轉化為C#存在的類型,如指針對應Intptr,句柄對應int類型等等

  4、調用函數

  我們本篇需要使用的函數有以下幾個:

  SetWindowsHookEx     用于安裝鉤子

  UnhookWindowsHookEx   用于卸載鉤子

  CallNextHookEx      執行下一個鉤子

  詳細API介紹請參考MSDN官方聲明

  接下來在C#中需要首先聲明此API函數:

[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,IntPtr hInstance, int threadId);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook);[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public static extern int CallNextHookEx(int idHook, int nCode,IntPtr wParam, IntPtr lParam);

  聲明后即可實現調用,SetWindowsHookEx()把一個應用程序定義的鉤子子程安裝到鉤子鏈表中,SetWindowsHookEx函數總是在Hook鏈的開頭安裝Hook子程。當指定類型的Hook監視的事件發生時,系統就調用與這個Hook關聯的Hook鏈的開頭的Hook子程。每一個Hook鏈中的Hook子程都決定是否把這個事件傳遞到下一個Hook子程。Hook子程傳遞事件到下一個Hook子程需要調用CallNextHookEx函數。 且鉤子使用完成后需要調用UnhookWindowsHookEx進行卸載,否則容易影響到其他鉤子的執行,并且鉤子太多會影響目標進程的正常運行。

  關于實例詳細操作過程不再贅述,請參考:http://blog.csdn.net/ensoo/article/details/2045101 及?https://www.cnblogs.com/ceoliujia/archive/2010/05/20/1740217.html

EasyHook

  C#本身調用WindowsAPI進行Hook功能受到很大的限制,而C++則不受此限制,因此就有一些聰明的人想到了聰明的方法:使用C++將基本操作封裝成庫,由C#進行調用,由此誕生了偉大的EasyHook,它不僅使用方便,而且開源免費,還支持64位版本。

  接下來我們一起使用C#操作EasyHook來實現一個Demo,完成對MessageBox的改寫。

  首先我們建立一個WinForm項目程序,并添加一個類庫ClassLibrary1,再從官網https://easyhook.github.io/或Nuget獲取到dll后引用到我們的項目中,注意:32位和64位版本都需要引用,建立項目如圖所示:

   

  其中WinForm程序用于獲取目標進程,并對目標進程進行注入,相關步驟如下:

  1、根據進程ID獲取相關進程,并判斷是否為64位;

  2、將所需DLL注冊到GAC(全局程序集緩存),注冊到GAC的目的是需要在目標進程中調用EasyHook及我們所編寫的DLL;

private bool RegGACAssembly(){var dllName = "EasyHook.dll";var dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath))){new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);Thread.Sleep(100);}dllName = "ClassLibrary1.dll";dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);new System.EnterpriseServices.Internal.Publish().GacRemove(dllPath);if (!RuntimeEnvironment.FromGlobalAccessCache(Assembly.LoadFrom(dllPath))){new System.EnterpriseServices.Internal.Publish().GacInstall(dllPath);Thread.Sleep(100);}return true;} 

  此處需要注意,要將自己編寫的類庫DLL加入GAC,需要對DLL進行強簽名操作,操作方法請參考:https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains/how-to-sign-an-assembly-with-a-strong-name

  3、注入目標進程,此處需使用EasyHook的RemoteHooking.Inject()方法進行注入:

private static bool InstallHookInternal(int processId) {try{var parameter = new HookParameter{Msg = "已經成功注入目標進程",HostProcessId = RemoteHooking.GetCurrentProcessId()};RemoteHooking.Inject(processId,InjectionOptions.Default,typeof(HookParameter).Assembly.Location,typeof(HookParameter).Assembly.Location,string.Empty,parameter);}catch (Exception ex){Debug.Print(ex.ToString());return false;}return true; }   HookParameter類為定義在ClassLibrary1中的一個類,包含消息與進程ID: [Serializable]public class HookParameter{public string Msg { get; set; }public int HostProcessId { get; set; }}

  到這一步我們就完成了對主窗體代碼的編寫,現在我們開始編寫注入DLL的方法:

  1、先引入MessageBox相關的WindowsAPI:

#region MessageBoxW[DllImport("user32.dll", EntryPoint = "MessageBoxW", CharSet = CharSet.Unicode)]public static extern IntPtr MessageBoxW(int hWnd, string text, string caption, uint type);[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]delegate IntPtr DMessageBoxW(int hWnd, string text, string caption, uint type);static IntPtr MessageBoxW_Hooked(int hWnd, string text, string caption, uint type){return MessageBoxW(hWnd, "已注入-" + text, "已注入-" + caption, type);}#endregion#region MessageBoxA[DllImport("user32.dll", EntryPoint = "MessageBoxA", CharSet = CharSet.Ansi)]public static extern IntPtr MessageBoxA(int hWnd, string text, string caption, uint type);[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]delegate IntPtr DMessageBoxA(int hWnd, string text, string caption, uint type);static IntPtr MessageBoxA_Hooked(int hWnd, string text, string caption, uint type){return MessageBoxA(hWnd, "已注入-" + text, "已注入-" + caption, type);}#endregion

  其中MessageBoxA與MessageBoxW是微軟用于區分不同操作系統中的編碼類型,早期的Windows并不屬于真正的32位操作系統,執行的API函數屬于ANSI類型,而從Windows2000開始,屬于Unicode類型,Windows在實際操作中,調用的MessageBox會自動根據平臺區分使用前者還是后者,我們在這里就需要把二者都包含其中。

  而DMessageBoxA與DMessageBoxW屬于IntPtr類型的委托,用于我們在Hook函數之后傳入我們需要修改的方法,此處我們改變了MessageBox的內容和標題,分別在前綴加上了"已注入-"的標記。

  2、完成定義之后我們就需要對函數進行Hook,此處使用LocalHook.GetProcAddress("user32.dll", "MessageBoxW")函數,通過指定的DLL與函數名,獲取函數在實際內存中的地址,獲取到之后,傳入LocalHook.Create()方法,用于創建本地鉤子:

public void Run(RemoteHooking.IContext context,string channelName, HookParameter parameter){try{MessageBoxWHook = LocalHook.Create(LocalHook.GetProcAddress("user32.dll", "MessageBoxW"),new DMessageBoxW(MessageBoxW_Hooked),this);MessageBoxWHook.ThreadACL.SetExclusiveACL(new int[1]);MessageBoxAHook = LocalHook.Create(LocalHook.GetProcAddress("user32.dll", "MessageBoxA"),new DMessageBoxW(MessageBoxA_Hooked),this);MessageBoxAHook.ThreadACL.SetExclusiveACL(new int[1]); }catch (Exception ex){MessageBox.Show(ex.Message);return;}try{while (true){Thread.Sleep(10);}}catch{}}

  其中MessageBoxWHook與MessageBoxAHook均為LocalHook類型的變量,MessageBoxAHook.ThreadACL.SetExclusiveACL(new int[1]); 這句代碼用于將本地鉤子加入當前線程中執行。

  運行之后我們來查看Hook的效果,先打開一個測試窗體,彈出MessageBox,這時候MessageBox沒有標題,且內容是正常的:

    

  接著我們對目標進程進行注入,獲取進程ID后點擊注入,提示已經成功注入目標進程:

    

  此時點擊目標進程MessageBox,可以發現已經Hook成功,并改變了內容和標題:

    

  至此,C#調用EasyHook對目標進程Hook已經實現。

后記

  從這次實踐中我們可以感受到,C#對程序進行Hook是完全可行的,雖然不能直接操作內存和地址,但是我們可以通過操作WindowsAPI與使用EasyHook的方式完成,尤其是后者,大大減少了代碼數量與使用難度。

  但是EasyHook目前中文資料非常少,我在使用的過程中也遇到了很大困難,Hook其他函數的方法也未能完全實現,希望能夠集思廣益,與大家共同思考交流!

  本人剛研究Hook時間不久,文中難免出現紕漏,懇請各位評論指正。

?  ?源代碼已經上傳至百度網盤:鏈接: https://pan.baidu.com/s/1wyin9Ezn6AwFQlQxMenQeg 密碼: dv9b

總結

以上是生活随笔為你收集整理的C# Hook原理及EasyHook简易教程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产欧美日韩精品区一区二污污污 | 久久免费成人 | 日本男女网站 | 色羞羞| 日韩伊人网 | 欧美成人久久久免费播放 | 国产精品国产三级国产aⅴ中文 | 欧美成人激情 | 久久女人 | 日本xxxxwwwww | 欧美中文字幕一区二区 | 草在线| 欧洲av一区二区 | 久久久久麻豆v国产精华液好用吗 | 88av网 | 91浏览器在线观看 | 911精品国产一区二区在线 | 97精品国产97久久久久久粉红 | 一卡二卡在线视频 | 国产精品搬运 | 日日碰日日摸 | 麻豆网站在线看 | 亚洲天码中字 | 中文字幕第十二页 | 欧美大片在线观看 | 91视频看看 | 欧洲黄色录像 | 天堂8在线 | 色婷婷av一区二区三区软件 | 成人乱人乱一区二区三区一级视频 | 国产免费脚交足视频在线观看 | 国产精品丝袜视频 | 日韩少妇内射免费播放 | 永久免费AV无码网站韩国毛片 | 亚洲一区二区视频网站 | 西野翔夫の目の前で犯在线 | 丰满女人又爽又紧又丰满 | 自拍偷拍在线视频 | 国产精品久久综合 | 国产白浆视频 | 北条麻妃久久精品 | 波多野在线视频 | 蜜臀视频一区二区 | 日本免费黄色片 | 国产视频一二区 | 国产大片中文字幕 | 捆绑裸体绳奴bdsm亚洲 | 国产午夜精品一区二区三区视频 | 亚洲国产精品视频在线 | 成人在线小视频 | 日韩无遮挡 | 亚洲一区二区在线播放 | 黄色网址你懂得 | 亚洲精品视频三区 | 成人无码久久久久毛片 | 国产在线1区 | 蜜臀av色欲a片无码精品一区 | 亚洲精品国产精品乱码不卡 | 少妇3p视频 | 欧美激情爱爱 | 国产美女被草 | 波多野结衣免费看 | 波多野结衣先锋影音 | 国产成人精品久久 | 日本免费黄视频 | 国产精品成人在线观看 | 两女双腿交缠激烈磨豆腐 | 91口爆一区二区三区在线 | 色狠| 日韩一及片 | 华人av在线 | 一区二区av电影 | 亚洲成人一二三 | 日韩精品免费一区二区三区竹菊 | 欧美人妻精品一区二区免费看 | 伊人看片 | 亚洲自拍电影 | 一级大片儿 | 天堂网资源 | 尤物毛片| 欧美日韩国产精品一区 | 国产激情片 | 日本免费不卡一区二区 | 五月婷婷久久综合 | av片手机在线观看 | 日韩中文字幕免费 | 自拍超碰| 精品久久视频 | 波多野结衣免费观看视频 | 337p粉嫩日本欧洲亚洲大胆 | 国产传媒视频在线观看 | fc2成人免费视频 | 国产一区二区小视频 | 少妇大叫太粗太大爽一区二区 | 日韩精品电影一区二区三区 | 丰满少妇麻豆av苏语棠 | 国产伦精品 | 好吊妞精品视频 | 一区二区三区四区精品视频 |