【问题标题】:Hook API with pure managed code使用纯托管代码挂钩 API
【发布时间】:2014-03-05 11:40:54
【问题描述】:

我在想如何在不使用 EasyHook 或类似库之类的 C++ 库的情况下将 API 与 C# 或 VB.Net 挂钩。 我喜欢学习这个的目的不是为了任何恶意,它只是为了获得更多的经验并找到.net 的极限。 假设我喜欢挂钩 MessageBoxA API。 我首先通过 Importing System.Runtime.InterropServices 导入它,然后在 user32.dll 中为 MessageBoxA API 调用添加 PInvoke 签名

<DllImport("user32.dll", EntryPoint:="MessageBoxW", 
           SetLastError:=True, Charset:=Charset.Unicode)> 
Public Function MessageBox(
     hwnd As IntPtr, 
     <MarshalAs(UnmanagedType.LPTSTR)>ByVal lpText As String, 
     <MarshalAs(UnmanagedType.LPTSTR)>ByVal lpCaption As String, 
     <MarshalAs(UnmanagedType.U4)>ByVal uType As MessageBoxOptions
) As <MarshalAs(UnmanagedType.U4)>MessageBoxResult
End Function

我现在基本上喜欢钩住每个调用 MessageBoxA API 的进程来获取普通文本,但我喜欢使用钩子在 messageBox 文本的末尾附加“钩子”。 一位对 .net 非常有经验的朋友,但不幸的是忙于帮我解决这个问题,他告诉我它绝对可以做到这一点。 步骤是,首先我需要 dll(库)中的实际挂钩函数,稍后我将在进程中注入该函数,然后我需要确定它是本机进程还是托管进程。如果它是托管的,那么没有问题,但如果它是本机进程,我需要一个加载器。 本机进程没有加载 .net,所以我需要先手动加载它,然后再注入 dll。

然后我需要获取指向 .net 方法的指针作为指针,这样我就知道我的钩子应该指向的地址,然后我可以使用 GetProcessAdress 和 LoadLibraryA 来获取指向 API 的指针。 我喜欢在API开头写的JMP可以使用WriteProcessMemory来实现。 有人可以通过挂钩 hte messagebox api 并在调用它之前向它附加一些文本来向我展示如何在上面提到的一个简单示例中实现这一点。

=)

【问题讨论】:

  • 我知道API调用不是恶意的,但是api hooks可以被恶意使用。我的意思是挂钩消息框 api,而不仅仅是简单地调用它;)请重新阅读我的 startpost。而复杂的事情我不知道如何实现是.net中的实际挂钩部分
  • 好吧,我来解释一下,帮助你理解。假设我在上面调用函数,带有 pinvoke 签名的 messageboxa。我传递了所有参数,然后会弹出一个消息框,对吗?如果我的意思是挂钩,我会将调用重定向到 api。也就是说,我需要在api的开头写一个JMP(指针),它指向我自己的函数。现在,如果我执行 messageboxa 的 apicall 并且系统喜欢执行它,它会因为 JMP 而被重定向到我的函数。在我的函数中,我喜欢在 msgbox 文本中附加一个“挂钩”,然后将修改后的结果发回。
  • 结果现在将是:实际 MessageBox 文本 +“钩子”(或我在函数中附加的任何内容。因此,步骤是将 api 调用重定向到我自己的函数,修改结果并将修改后的结果发回到api。(基本上像弯路)。
  • API Hooking 并不总是恶意的,例如 AV 也通过 hook api 来提高其安全性等。
  • messageboxhook 应该只是一个示例,以了解 api 挂钩的概念通常适用于 .net。

标签: c# vb.net api hook api-hook


【解决方案1】:

我不确定这是否是您要查找的内容,但这就是我钩入鼠标的方式。也许它可以帮助你找出其他的钩子。

Public Class MouseDetector
    Public Event MouseLeftButtonClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    Public Event MouseRightButtonClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    Private Delegate Function MouseHookCallback(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
    Private MouseHookCallbackDelegate As MouseHookCallback
    Private MouseHookID As Integer

    Public Sub New()
        If MouseHookID = 0 Then
            MouseHookCallbackDelegate = AddressOf MouseHookProc
            MouseHookID = SetWindowsHookEx(CInt(14), MouseHookCallbackDelegate, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.GetModules()(0)), 0)
            If MouseHookID = 0 Then
                'error
            End If
        End If
    End Sub

    Public Sub Dispose()
        If Not MouseHookID = -1 Then
            UnhookWindowsHookEx(MouseHookID)
            MouseHookCallbackDelegate = Nothing
        End If
        MouseHookID = -1
    End Sub

    Private Enum MouseMessages
        WM_LeftButtonDown = 513
        WM_LeftButtonUp = 514
        WM_LeftDblClick = 515
        WM_RightButtonDown = 516
        WM_RightButtonUp = 517
        WM_RightDblClick = 518
    End Enum

    <StructLayout(LayoutKind.Sequential)> Private Structure Point
        Public x As Integer
        Public y As Integer
    End Structure

    <StructLayout(LayoutKind.Sequential)> Private Structure MouseHookStruct
        Public pt As Point
        Public hwnd As Integer
        Public wHitTestCode As Integer
        Public dwExtraInfo As Integer
    End Structure

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function

    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _
    Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As MouseHookCallback, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _
    Private Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Integer
    End Function

    Private Function MouseHookProc(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
        If nCode < 0 Then
            Return CallNextHookEx(MouseHookID, nCode, wParam, lParam)
        End If
        Dim MouseData As MouseHookStruct = Marshal.PtrToStructure(lParam, GetType(MouseHookStruct))
        Select Case wParam
            Case MouseMessages.WM_LeftButtonUp
                RaiseEvent MouseLeftButtonClick(Nothing, New MouseEventArgs(MouseButtons.Left, 1, MouseData.pt.x, MouseData.pt.y, 0))
            Case MouseMessages.WM_RightButtonUp
                RaiseEvent MouseRightButtonClick(Nothing, New MouseEventArgs(MouseButtons.Right, 1, MouseData.pt.x, MouseData.pt.y, 0))
        End Select
        Return CallNextHookEx(MouseHookID, nCode, wParam, lParam)
    End Function
End Class

Private Sub MouseDetector_MouseLeftButtonClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MouseDetector.MouseLeftButtonClick
        'MessageBox.Show("left")
End Sub

【讨论】:

  • 感谢您的努力,但我不确定这如何通过挂钩 API 来帮助我?我要怎么上钩?这会钩住鼠标事件。
  • 我不知道 API,我只是想这可能会给你一些关于挂钩的方向。您提到您正在尝试了解有关挂钩的更多信息,因此我认为这可能会给您一些见解。
  • 是的,我知道鼠标和键盘挂钩,但我喜欢学习的是挂钩 API,我想这有点困难:/ 但我知道这是可能的。跨度>
猜你喜欢
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 2011-01-29
  • 2010-12-10
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 2023-01-05
相关资源
最近更新 更多