精品一区二区三区影院在线午夜_天天躁日日躁狠狠躁AV麻豆_国产午夜福利短视频_中文字幕乱偷无码AV先锋蜜桃_久久精品一二区东京热_国产成人亚洲日韩欧美久久久,国产成人精品久久一区二区三区

【VB.NET】托管代碼也可以處理HOOK API

HOOK API是一個(gè)老生常談的話(huà)題了,因為這種技術(shù)可以讓我們在原有代碼的基礎上添加自己的其他代碼進(jìn)去,而實(shí)現我們的目的。對于C程序員來(lái)講,這并不陌生,因為C語(yǔ)言可以編寫(xiě)標準的DLL文件,可以操作指針;對VB.NET程序員來(lái)講,很多人都選擇使用C語(yǔ)言去完成HOOK工作然后在VB.NET中進(jìn)行調用,但實(shí)際上,并非如此。

接下來(lái)我們詳細介紹一下如何用VB.NET來(lái)HOOK API:

一、HOOK本進(jìn)程API并用托管函數處理

如果你熟悉C語(yǔ)言的HOOK API的基本方式,那么可以直接看代碼。

1、查找要HOOK的API的地址

通常,我們使用API函數GetModleHandle和GetProcAddress。當然,也可以用VB.NET提供的Process.GetCurrentProcess.Modules來(lái)獲取模塊句柄之后解析PE結構來(lái)獲取函數地址,但在一般應用當中有點(diǎn)小題大做。

2、查找跳轉到的函數的地址

對于C程序員來(lái)講,只需要利用函數指針即可(一個(gè)指向函數基地址的指針),但是VB.NET并不是不能取得函數指針,只是該函數應聲明為一個(gè)委托的實(shí)例。如果你不了解委托可以先參考一下介紹委托的文章。將委托轉化為可供非托管調用地址的函數就是讓讓你看了就灰常激動(dòng)的marshal提供的Marshal.GetFunctionPointerForDelegate函數了。

3、構造跳轉

只要有一點(diǎn)匯編基礎只是即可,當然沒(méi)有也可以。我們要實(shí)現這么一個(gè)流程:

a修改原API,使之被調用時(shí)就跳轉到我們的函數

b在我們的函數中恢復原API并調用之

重復以上步驟即可。一般我們使用jmp遠跳轉來(lái)實(shí)現。還有人總結了所謂“新入口計算公式”:lpAddress.ToInt32 - ProcAddress.ToInt32 – 5。我們只需要構造如下代碼即可:

Jmp oldFuncAddress

Jmp newFuncAddress

好了,萬(wàn)事俱備,上代碼:

【HOOK API類(lèi)】很短小的

Imports System.Runtime.InteropServices

Public Class APIHOOK

'巨注意:有的該死的版本里面marshal的讀寫(xiě)方法滴偏移量參數無(wú)效,自己改改代碼,把偏移直接加到基地址里面,偏移量用0 。有興趣可以用Reflector察看一下。

'有的同志習慣于用lstrcpyn這個(gè)api來(lái)取數組地址,方法就是把參數1,2都設置為數組本身,其返回值就是數組的內存地址。

'雖然這是一種取變量非托管內存指針的有效方式。但這存在一些問(wèn)題,建議還是使用marshal類(lèi)直接在非托管內存操作。

<DllImport("Kernel32.dll")> _

Private Shared Function VirtualProtect(ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flNewProtect As Integer, ByRef lpflOldProtect As Integer) As Boolean

End Function

<DllImport("Kernel32.dll")> _

Private Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal lpProcName As String) As IntPtr

End Function

Const PAGE_EXECUTE_READWRITE As Integer = &H40 '內存保護屬性

Private ProcAddress As IntPtr 'api函數地址

Private lpflOldProtect As Integer = 0 '原始內存保護屬性

Private OldEntry As IntPtr = Marshal.AllocHGlobal(5) '原始入口點(diǎn)數據

Private NewEntry As IntPtr = Marshal.AllocHGlobal(5) '新入口點(diǎn)數據

Private _Installed As Boolean

Public ReadOnly Property Installed() As Boolean

Get

Return _Installed

End Get

End Property

Public Sub New()

End Sub

Public Sub New(ByVal ModuleName As String, ByVal ProcName As String, ByVal lpAddress As IntPtr)

Install(ModuleName, ProcName, lpAddress)

End Sub

Public Function Install(ByVal ModuleName As String, ByVal ProcName As String, ByVal lpAddress As IntPtr) As Boolean

'模塊句柄

Dim hModule As IntPtr

For Each md As ProcessModule In Process.GetCurrentProcess.Modules

If md.ModuleName.ToLower = ModuleName.ToLower Then

hModule = md.BaseAddress

Exit For

End If

Next

If hModule = IntPtr.Zero Then Return False

'函數入口

ProcAddress = GetProcAddress(hModule, ProcName)

If ProcAddress = IntPtr.Zero Then Return False

'修改內存屬性

If Not VirtualProtect(ProcAddress, 1, PAGE_EXECUTE_READWRITE, lpflOldProtect) Then Return False

'------------------------------------------在非托管內存構造數據---------------------------------------------

'讀原始5字節

For i As Integer = 0 To 4

Marshal.WriteByte(OldEntry, i, Marshal.ReadByte(ProcAddress, i))

Next

'構造新5字節

'jmp

Marshal.WriteByte(NewEntry, 0, &HE9)

'新入口地址——我們的處理函數的非托管地址,jmp是相對地址

Marshal.WriteInt32(NewEntry, 1, lpAddress.ToInt32 - ProcAddress.ToInt32 - 5)

'---------------------------------------------數據構造完畢-----------------------------------------------------

_Installed = True

Return True

End Function

Public Sub UnHook()

If Not _Installed Then Return

For i As Integer = 0 To 4

Marshal.WriteByte(ProcAddress, i, Marshal.ReadByte(OldEntry, i))

Next

End Sub

Public Sub Hook()

If Not _Installed Then Return

For i As Integer = 0 To 4

Marshal.WriteByte(ProcAddress, i, Marshal.ReadByte(NewEntry, i))

'Debug.Print(Marshal.ReadByte(NewEntry, i) & " " & Marshal.ReadByte(OldEntry, i))

Next

End Sub

Public Function Uninstall() As Boolean

If Not _Installed Then Return True

UnHook()

VirtualProtect(ProcAddress, 1, lpflOldProtect, lpflOldProtect)

_Installed = True

Return True

End Function

End Class

【測試代碼】也很短小

Imports System.Runtime.InteropServices

'函數原型

'HttpOpenRequest  HINTERNET HttpOpenRequest (HINTERNET hInternet ,LPCTSTR lpszUrl ,LPCTSTR lpszHeaders ,DWORD dwHeadersLength ,DWORD dwFlags ,DWORD_PTR dwContext)

Public Class Form1

<DllImport("wininet.dll", CharSet:=CharSet.Ansi, setlasterror:=True)> _

Private Shared Function HttpOpenRequestA(ByVal hHttpSession As Integer, ByVal sVerb As String, _

ByVal sObjectName As String, ByVal sVersion As String, _

ByVal sReferer As String, ByVal something As Integer, _

ByVal lFlags As Integer, ByVal lContext As Integer) As Integer

End Function

Private HttpOpenRequest_Hook As New APIHOOK()

'定義一個(gè)引用變量以防止垃圾回收機制回收回調

Private fix_COCD_HttpOpenRequest As HttpOpenRequestCallback

Private Delegate Function HttpOpenRequestCallback(ByVal hHttpSession As Integer, ByVal sVerb As String, _

ByVal sObjectName As String, ByVal sVersion As String, _

ByVal sReferer As String, ByVal something As Integer, _

ByVal lFlags As Integer, ByVal lContext As Integer) As Integer

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

WebBrowser1.Navigate("http://www.163.com")

If HttpOpenRequest_Hook.Installed Then HttpOpenRequest_Hook.Uninstall()

fix_COCD_HttpOpenRequest = New HttpOpenRequestCallback(AddressOf HttpOpenRequestProc)

HttpOpenRequest_Hook.Install("wininet.dll", "HttpOpenRequestA", Marshal.GetFunctionPointerForDelegate(fix_COCD_HttpOpenRequest))

HttpOpenRequest_Hook.Hook()

Debug.Print("hook: " & HttpOpenRequest_Hook.Installed)

End Sub

Private Function HttpOpenRequestProc(ByVal hHttpSession As Integer, ByVal sVerb As String, _

ByVal sObjectName As String, ByVal sVersion As String, _

ByVal sReferer As String, ByVal something As Integer, _

ByVal lFlags As Integer, ByVal lContext As Integer) As Integer

'注意:在鉤CreateFile等函數時(shí)可能需要修改調試選項以便可以從非托管進(jìn)入托管,并且不應直接使用debug.print等函數進(jìn)行顯示

Debug.Print(sObjectName)

'卸載鉤子以便調用原函數

HttpOpenRequest_Hook.UnHook()

'調用原函數

Dim ret As Integer = HttpOpenRequestA(hHttpSession, sVerb, sObjectName, sVersion, sReferer, something, lFlags, lContext)

'加載鉤子以便繼續獲取數據

HttpOpenRequest_Hook.Hook()

Return ret

End Function

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

HttpOpenRequest_Hook.Uninstall()

End Sub

End Class

可以看出,用托管代碼處理HOOK的時(shí)候,流程和經(jīng)典的HOOK處理沒(méi)有什么區別,主要在于:

1、聲明一個(gè)托管函數,其原型要與HOOK的API原型一致(這里說(shuō)的一致不一定是完全一樣的類(lèi)型,例如C里面字節指針,字符指針等都可以用byte數組代替,當然最好是明確封送約定了,不過(guò)我不習慣那樣做,看起來(lái)亂七八糟的,都是用VB.NET提供的基本類(lèi)型聲明)

2、實(shí)例化托管并將其轉化為可供非托管代碼調用的函數指針:Marshal.GetFunctionPointerForDelegate(fix_COCD_HttpOpenRequest))

其實(shí)很簡(jiǎn)單是吧,呵呵,而且這里只列出了HOOK本進(jìn)程的API。這是所寫(xiě)的一個(gè)工具的一部分,這個(gè)工具主要是用來(lái)注入托管代碼到其他進(jìn)程并HOOK其API函數,同時(shí)通過(guò)ebp取得調用堆棧,來(lái)進(jìn)行一定的函數調用追蹤的——當然可以用調試工具,前提是能調試…………哎,有些HOOK真的真的是……讓VB.NET跑到內核里得寫(xiě)多少代碼啊,那可要了親命了,不如變通

注入托管代碼到非托管進(jìn)程其實(shí)也不難,一般可以用一個(gè)VC的DLL寫(xiě)幾句代碼來(lái)加載CLR并進(jìn)而加載并運行托管DLL,這方面的資料網(wǎng)上已經(jīng)不少了,不羅列了。而獲取ebp只是一個(gè)內嵌匯編過(guò)程,方法有很多種,一般來(lái)講可以用遠線(xiàn)程或本地線(xiàn)程、marshal類(lèi)重構造委托代碼或指針轉化為委托等方式來(lái)做具體實(shí)現。在這篇文章中就不進(jìn)行羅列了,因為還需要對ebp取得的call stack進(jìn)行解碼,基本的stack結構只能得到上層ebp,返回值,參數1,而還有很多工作需要做。

你可以轉發(fā)或修改代碼,但請注明出處

松原市| 罗源县| 民权县| 镇坪县| 台州市| 台前县| 台江县| 威信县| 凤翔县| 察隅县| 四平市| 乾安县| 军事| 石阡县| 大理市| 长垣县| 林芝县| 建宁县| 夹江县| 万全县| 随州市| 会昌县| 北安市| 福建省| 景洪市| 灌云县| 河北省| 抚州市| 甘谷县| 盖州市| 湟源县| 邮箱| 万全县| 绵竹市| 陵水| 赞皇县| 西贡区| 靖西县| 北海市| 新巴尔虎右旗| 东安县|