HOOK API是一个老生常谈的话题了,因为这种技术可以让我们在原有代码的基础上添加自己的其他代码进去,而实现我们的目的。对于C程序员来讲,这并不陌生,因为C语言可以编写标准的DLL文件,可以操作指针;对VB.NET程序员来讲,很多人都选择使用C语言去完成HOOK工作然后在VB.NET中进行调用,但实际上,并非如此。

接下来我们详细介绍一下如何用VB.NETHOOK API

一、HOOK本进程API并用托管函数处理

如果你熟悉C语言的HOOK API的基本方式,那么可以直接看代码。

1、查找要HOOKAPI的地址

通常,我们使用API函数GetModleHandle和GetProcAddress。当然,也可以用VB.NET提供的Process.GetCurrentProcess.Modules来获取模块句柄之后解析PE结构来获取函数地址,但在一般应用当中有点小题大做。

2、查找跳转到的函数的地址

对于C程序员来讲,只需要利用函数指针即可(一个指向函数基地址的指针),但是VB.NET并不是不能取得函数指针,只是该函数应声明为一个委托的实例。如果你不了解委托可以先参考一下介绍委托的文章。将委托转化为可供非托管调用地址的函数就是让让你看了就灰常激动的marshal提供的Marshal.GetFunctionPointerForDelegate函数了。

3、构造跳转

只要有一点汇编基础只是即可,当然没有也可以。我们要实现这么一个流程:

a修改原API,使之被调用时就跳转到我们的函数

b在我们的函数中恢复原API并调用之

重复以上步骤即可。一般我们使用jmp远跳转来实现。还有人总结了所谓“新入口计算公式”:lpAddress.ToInt32 - ProcAddress.ToInt32 5。我们只需要构造如下代码即可:

Jmp oldFuncAddress

Jmp newFuncAddress

好了,万事俱备,上代码:

 

【HOOK API类】很短小的

 

Imports System.Runtime.InteropServices

Public Class APIHOOK

    '巨注意:有的该死的版本里面marshal的读写方法滴偏移量参数无效,自己改改代码,把偏移直接加到基地址里面,偏移量用0 。有兴趣可以用Reflector察看一下。

    '有的同志习惯于用lstrcpyn这个api来取数组地址,方法就是把参数1,2都设置为数组本身,其返回值就是数组的内存地址。

    '虽然这是一种取变量非托管内存指针的有效方式。但这存在一些问题,建议还是使用marshal类直接在非托管内存操作。

 

    <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)    '原始入口点数据

    Private NewEntry As IntPtr = Marshal.AllocHGlobal(5)    '新入口点数据

    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()

    '定义一个引用变量以防止垃圾回收机制回收回调

    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等函数时可能需要修改调试选项以便可以从非托管进入托管,并且不应直接使用debug.print等函数进行显示

        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的时候,流程和经典的HOOK处理没有什么区别,主要在于:

1、声明一个托管函数,其原型要与HOOK的API原型一致(这里说的一致不一定是完全一样的类型,例如C里面字节指针,字符指针等都可以用byte数组代替,当然最好是明确封送约定了,不过我不习惯那样做,看起来乱七八糟的,都是用VB.NET提供的基本类型声明)

2、实例化托管并将其转化为可供非托管代码调用的函数指针:Marshal.GetFunctionPointerForDelegate(fix_COCD_HttpOpenRequest))

 

 

其实很简单是吧,呵呵,而且这里只列出了HOOK本进程的API。这是所写的一个工具的一部分,这个工具主要是用来注入托管代码到其他进程并HOOK其API函数,同时通过ebp取得调用堆栈,来进行一定的函数调用追踪的——当然可以用调试工具,前提是能调试…………哎,有些HOOK真的真的是……让VB.NET跑到内核里得写多少代码啊,那可要了亲命了,不如变通

 

注入托管代码到非托管进程其实也不难,一般可以用一个VC的DLL写几句代码来加载CLR并进而加载并运行托管DLL,这方面的资料网上已经不少了,不罗列了。而获取ebp只是一个内嵌汇编过程,方法有很多种,一般来讲可以用远线程或本地线程、marshal类重构造委托代码或指针转化为委托等方式来做具体实现。在这篇文章中就不进行罗列了,因为还需要对ebp取得的call stack进行解码,基本的stack结构只能得到上层ebp,返回值,参数1,而还有很多工作需要做。

 

你可以转发或修改代码,但请注明出处

posted @ 2011-10-10 09:44 流浪d&#232;风 Views(221) Comments(1) Edit
完全屏蔽FLASH右键菜单Read More
posted @ 2011-09-28 09:05 流浪d&#232;风 Views(88) Comments(0) Edit
介绍tesseract训练,使用。着重说明了一些训练、使用当中的易错点。希望能给大家一些帮助。Read More
posted @ 2011-02-21 11:34 流浪d&#232;风 Views(2895) Comments(8) Edit
其实这东西不止一次被科普过了。本文针对AS3且适用于AS2,AS2的人家都有修改器的。不过说起来修改FLASH游戏,我这也只是初级方法,现在还在看flexsdk4.1里面的fdb的源码,呵呵。理论上应该可以找到更好的解决办法——直接去修改二次编译后的代码,那样就可以为所欲为了,咕~~(╯﹏╰)b。闲话少说,进入这次的正题,后面的“高级”东东以后再说,反正弄着玩嘛,又不指望这吃饭,兴趣使然。 有位老大爷说得好,工欲善其事必先利其器!建议往下看之前先搞个这:http://www.yogda.com/Yogda.1.0.564.zip 。 当然了,去主页看看也挺好;要是你有闪客精灵、ASV啥的也行,Read More
posted @ 2011-02-08 16:44 流浪d&#232;风 Views(2082) Comments(1) Edit
VB.NET内嵌ASM——示例为调API~~让我写ASM估计我和大多数人一样头疼~~~没长那好脑子,不过微软的示例给了一个很好的方法:先VC之,然后反编译,哇咔咔,还是复制粘贴来的快!! 尾巴:消息过滤器处理本窗体的键盘鼠标啥的消息……做点WndProc做不了的事Read More
posted @ 2011-01-14 11:40 流浪d&#232;风 Views(1044) Comments(4) Edit
内存中的FLASH提取工具源码~~~程序~~~~(修复了一个BUG,并优化了查找逻辑)Read More
posted @ 2010-12-24 14:31 流浪d&#232;风 Views(2438) Comments(3) Edit
首先,说一下宗旨,写这些东西主要是给生手们一些建议和求高手们给予一些指点。这一系列文章主要涉及POWERPOINT和FLASH及一些VBA和VB编程。主要放在一些POWERPOINT的使用技巧和简单的交互处理、FLASH动画用AS2(之所以讲AS2是想避开AS3的复杂组织和面向对象编程——虽然AS2可能比较乱,但因为我们毕竟只是做个课件,又不是去做什么大东东,去学面向对象再...Read More
posted @ 2010-11-17 08:55 流浪d&#232;风 Views(141) Comments(0) Edit
呃,小儿科拿出来讨论一下。巨注意:不是让大家去写外挂哦!纯属技术讨论。先写一部分,测试是用GDI+写的,非常的简陋,而且整体只是一个雏形,抛砖引玉。【一、物理引擎】 所谓物理引擎,是通过为刚体赋予真实的物理属性的方式来计算它们的运动、旋转、碰撞等等的结果。也许你曾经编写过台球游戏,使用了大量的类似于碰撞检测,线相交和折返等等数学方法来解决问题,但那不是对真实世界的物理模拟,虽然可以使你的游戏看起来...Read More
posted @ 2010-09-09 16:55 流浪d&#232;风 Views(2122) Comments(3) Edit
以前用VB6写过一个枚举程序,总是觉得不是很直观,这次用VB.NET写可能要好一点,但是也存在一些问题,例如没有枚举父,没有提供测试功能。简要的写几句,其实对照HTML代码就可以了,只是为了解决有得页面比较复杂或者运行脚本导致查看源码看到的东东不全的问题。非常简单,一按钮,一个文本框,一panel,一webbrowser。将panel拖动到页面元素上文本框里就显示内容了,不过一般还是拖动到其父上,...Read More
posted @ 2010-07-21 21:26 流浪d&#232;风 Views(148) Comments(0) Edit
基于模板识别的一个实例。有情况可以联系shaoyan5@163.comRead More
posted @ 2010-05-15 22:47 流浪d&#232;风 Views(3582) Comments(2) Edit