C#使用easyHook筆記一


  大家好,這里是TSIR,當大牛們,都在討論如何去hook的時候,哪種hook方式比較方便,我卻在為hook是什么而發愁,於是決定寫下這篇帖子,一是作為自己學習的筆記,二是給和我一樣存在困惑的哥們,拋個磚,引個玉。當然了,畢竟是小白,里面的言論可能會出現錯誤,望大佬斧正(本文參考了easyHook官方教程第一章,奈若何,官方的教程有點難懂,故有此篇)。
一.什么是hook
  首先說下我理解的hook,簡而言之就是偷天換日之術,假如程序中有一個sayHello的函數,它會輸出字符串 ”hello”,那么我們也定義一個sayHello(當然名字為了區分可能叫做sayHelloHook,這樣一來感覺高大上多了),然后讓它返回字符串 “你好”。再經過各種代碼,一頓操作,程序里面調用sayHello的時候 就會直接執行我們的sayHelloHook函數。當然,hook可以操作的事情並非這些,還有很多,具體就靠大家的奇思妙想了。
二.開始學習之前
  我用的是easyHook,語言采用C#,系統win10,代碼編輯器VS2015。別問我為什么,因為用他們寫代碼賊雞兒簡單,方便小白。三.正文(序言)我們先大致的思考一個小問題,如何hook,雖然我們有神器easyHook,但是他總要有個步驟,聲控寫代碼是不可能的(我想hook這個函數,嗯 還有這個函數,不對不對還有那個函數)。一般而言分為四個步驟,我提煉出來的話就是:  EasyHook函數四步走

  • 找函數
  • 匹配委托
  • 編寫hook函數
  • 注入hook(這里包含了裝載hook和卸載hook

我們來解釋下,首先第一步驟,我們應該了解,windows下的很多api,都是已經寫好了的,我們程序中寫的很多函數都是依靠他們作為底層來完成的,我們直接拿來用就行,就我們的程序而言,就是哪個動態鏈接庫(這里寫了一堆一堆的函數),里面的哪個函數,可以做什么。所以第一步,我們需要知道這個函數在哪里,其實也就是easyHook需要知道,他要hook哪個函數的地址。第二步,匹配委托,這個可能有點不好理解,說實在的我現在對委托還是一頭霧水,但是簡單的理解就是,函數指針(再通俗點就是我們編寫函數的地址),要替換函數,要知道替換函數的地址,還要知道我們自己寫的函數地址才能實現注入,注意這里寫委托一定要和欲hook的函數參數和返回值一樣,否則,就會出現大問題,我知道你不想搞一個大事情,所以,老老實實按照原型寫委托吧。第三步,編寫我們自己的函數就是上文中說到的sayHelloHook,我們自己實現函數要做哪些事情,最后別忘了一定要和原函數,參數,返回值對應。第四步,最輕松的一步,由easyHook替我們完成,他會自己實現函數的替換,注入啥的。我們只需要聲明調用就ok
四.代碼編寫
  我們按照上面的一步一步的寫(核心)第一步,找函數

[C#]  純文本查看 復制代碼
?
1
IntPtr messageBeep = EasyHook.LocalHook.GetProcAddress( "user32.dll" , "MessageBeep" );

第二步,匹配委托

[C#]  純文本查看 復制代碼
?
1
2
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true )]
         delegate bool MessageBeepDelegate( uint uType);

第三步,寫hook

[C#]  純文本查看 復制代碼
?
1
2
3
4
5
6
7
//聲明一個用來替換替換原來MessageBeep的函數 也就是hook函數
         static private bool MessageBeepHook( uint uType)
         {
             Console.WriteLine();
             Console.WriteLine( "----我們自定義的MessageBeepHook函數,- -無聲MessageBeep----" );
             return true ;
         }

第四步,注入hook

[C#]  純文本查看 復制代碼
?
1
var hook = EasyHook.LocalHook.Create(messageBeep, messageBeepDelegate, null );


然后是通篇的代碼,里面只加了一些修飾,或者其他的膠水代碼粘連。
對了,如果需要體驗的話,用vs2015新建一個控制台項目然后復制代碼到主文件,添加NUGet 在里面搜索 easyHook 導入安裝就行了,so easy!

[C#]  純文本查看 復制代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Runtime.InteropServices;
 
namespace easyHook
{
     class Program
     {
 
         //C#中要調用MessageBeep函數必須這樣寫,沒轍
         [DllImport( "user32.dll" )]
         static extern bool MessageBeep( uint uType);
 
 
         //二.----------------------匹配委托------------------------------
         [UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true )]
         delegate bool MessageBeepDelegate( uint uType);
         //聲明一個用來替換替換原來MessageBeep的函數 也就是hook函數
 
         //三.----------------------編寫hook函數------------------------------
         static private bool MessageBeepHook( uint uType)
         {
             Console.WriteLine();
             Console.WriteLine( "----我們自定義的MessageBeepHook函數,- -無聲MessageBeep----" );
             return true ;
         }
 
        
         static void Main( string [] args)
         {
             //一.----------------------找函數------------------------------
             IntPtr messageBeep = EasyHook.LocalHook.GetProcAddress( "user32.dll" , "MessageBeep" );
 
 
             MessageBeepDelegate messageBeepDelegate = new MessageBeepDelegate(MessageBeepHook);
             Console.WriteLine( "1.當程序載入的時候就調用一次MessageBeep函數,這里的MessageBeep還沒有被hook" );
             MessageBeep(0xFFFFFFFF);
             Console.Write( "\n按下回車鍵,將會hook MessageBeep(也就是程序調用MessageBeep時,會替換成我們自定義的MessageBeepHook函數):" );
             Console.ReadLine();
 
             // 創建local hook 使用我們自己定義的 MessageBeepDelegate and MessageBeepHook 函數
             //四.----------------------創建hook------------------------------
             var hook = EasyHook.LocalHook.Create(messageBeep, messageBeepDelegate, null );
             hook.ThreadACL.SetInclusiveACL( new int [] { 0 });
             MessageBeep(0xFFFFFFFF);
             Console.Write( "\n按下回車鍵 禁用當前的hook(也就是還原MessageBeep函數,調用的時候就是原本的MessageBeep函數了):" );
             Console.ReadLine();
             hook.ThreadACL.SetExclusiveACL( new int [] { 0 });
             //再次調用再次調用PlayMessageBeep 這個是原生的了
             MessageBeep(0xFFFFFFFF);
             Console.Write( "\n按下回車鍵 卸載hook並退出" );
             Console.ReadLine();
             hook.Dispose(); 
         }
     }}


五.后記
   其實,說起來就是想寫個hook程序scoket 發包 接包的軟件,然后歷程幾天,終於還是寫了出來,但是還是對代碼的整體,沒有比較好的把握,下一篇如果有的話應該就是遠程注入的教程了,關於recv和send hook的教程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM