0

I was thinking how can I hook an API with C# or VB.Net, without using a C++ Library like EasyHook or similar libs. The purpose why I like to learn this is not for anything malicous, its just to get more experience and find the limits of whats possible with .net. Lets say I like to hook the MessageBoxA API. I first import it by Importing System.Runtime.InterropServices and then add the PInvoke Signiature for The MessageBoxA API Call in user32.dll

<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

I basically like now to hook every process, which calls the MessageBoxA API get the normal text, but with the hook I like to append "hooked" at the end of the messageBox text. A friend who is very experienced with .net, but unfortunately to busy to help me with this, told me its definitly possible to do that. The steps would be, first I need the actual hooking function in a dll (library) which I will later inject in a process, then I need to determine if its a native or a managed process. If its a managed then there is no problem, but if it is a native process I need a loader. A native process doesn't have .net loaded so i need to load it manually first and then injectz the dll.

Then I need to get the Pointer to the .net method as a pointer so I know the adress where my hook should be directed to and then I can use GetProcessAdress and LoadLibraryA to get the Pointer to the API. The JMP I like to write at the beginning of the API can be realized by using WriteProcessMemory. Can someone show me how this can be realized on a simple example as mentioned above by hooking hte messagebox api and apending some text to it before it is called.

=)

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
nexno
  • 429
  • 8
  • 26
  • "this is not for anything malicious" -> from your question (making API calls?!), I didn't expect it to be for any malicious purpose. Now I have my doubts. – varocarbas Mar 05 '14 at 12:12
  • In any case you seem to be over-complicating things; calling APIs is a more or less simple process, just type "messagebox api vb.net" in any search engine and you would see lots of examples. – varocarbas Mar 05 '14 at 12:14
  • 1
    I know that API calls are not malicous, but api hooks can be used malicous. And what i mean is hooking the messagebox api not just simply calling it ;) Please reread my startpost. And the thing which is complicated and I am not sure how to realize is the actual hooking part in .net – nexno Mar 05 '14 at 12:29
  • What you mean with hooking instead of calling it? These functions are meant to have a full control on virtually anything in the given computer. You can do whatever what these functions allow you to do (what, as said, is virtually anything). To accomplish this you have to call them (by following the corresponding conventions). This is what you are doing in your code: http://www.pinvoke.net/default.aspx/user32.messagebox See? Your code represents the way in which the given function is expected to be CALLED. What you mean with hooking? – varocarbas Mar 05 '14 at 12:35
  • Note that I use the word "hook" for this kind of "low-level"-ish references. But, at the end, all these are calls to functions (= put there by .NET to allow you call them). Can you please elaborate a bit more about the differences hooking/calling for those, like myself, who perhaps misuse both words? – varocarbas Mar 05 '14 at 12:40
  • 1
    Ok, let me explain it to help you understanding. Lets say I call function above, messageboxa with the pinvoke signiature. i pass al parameters and a messagebox will popup, right? If I mean hooking, I redirect the call to the api. That means, I need to write a JMP (Pointer) at the beginning of the api, which points to my own function. Now If I execute the apicall of messageboxa and the system likes to execute it, it gets redirected to my function because of the JMP. In my function I like to append a "hooked" to the msgbox text, and then send the modified result back. – nexno Mar 05 '14 at 12:46
  • 1
    Result would now be: Actual MessageBox text + " hooked" (or whatever I append in my function. So steps are redirecting the api call to my own function, modify the results and send the modified results back to the api. (Basiclly like detours). – nexno Mar 05 '14 at 12:47
  • OK. Now it is much more clear what you mean with hooking. So... what you are saying is: "I want to locate the specific memory location where the function I want to called is started" (= via pointer what, BTW, cannot be done in VB.NET); I want to change this entry value such that it redirects to whatever I want... – varocarbas Mar 05 '14 at 12:49
  • ... well with this definition; it does sound pretty malicious. Actually, I cannot think of a single non-malicious application. As explained above, the given function allows you to perform certain changes and thus you only have one non-malicious option: perform these changes. If you want to do anything which is not accounted for by the given function; you shouldn't use it. On the other hand, you don't want to extend the function; you want everyone calling this function to actually call yours?! I am not sure if this can be done at all + I am certain that this is malicious... – varocarbas Mar 05 '14 at 12:52
  • 1
    API Hooking is not always malicous, for example AV's also hook apis to improve their security etc. – nexno Mar 05 '14 at 12:54
  • ...+ I am certain that you cannot use pointers in VB.NET (but pointers to change the way in which an API is called?!... where are planning you to store this information?! Because you want all the programs in the given computer to account for this change! You want to modify the basic .NET Framework in the given computer?!)... After understanding what you meant; I think that you have put together some rough ideas without thinking too much about it. – varocarbas Mar 05 '14 at 12:54
  • 1
    The messageboxhook should just be a sample to understand hwo the concept of api hooking works in general for .net. – nexno Mar 05 '14 at 12:55
  • 1
    Sure you can use pointers in .net: http://www.codeproject.com/Articles/712/How-to-do-pointers-in-Visual-Basic – nexno Mar 05 '14 at 12:56
  • This conversation has got too long already (too long comments are not helpful for future readers) and my conclusion is that you need much more help than what SO can bring you in a question (& answer). Please think twice (and thrice) about what you want to accomplish and ask specific problems by making sure that you use words easily understandable by everyone (e.g., "with hook I mean that I want to intercept all the calls to a given .NET function and redirect it to mine"). – varocarbas Mar 05 '14 at 12:58
  • PS: regarding VB.NET pointers. NO, you cannot use pointers in VB.NET (because it does not accept unsafe code; only thing which allows pointers, that is, making a small exception to the automatic memory management of .NET). You might try to come up with workarounds. Honestly not sure if the link you propose works at all (there are lots of people talking without knowing too well what they are talking about in internet; or things which worked in previous versions might not work now. You shouldn't trust any claim blindly). – varocarbas Mar 05 '14 at 12:59
  • Just out of curiosity: you are saying that with this library (EasyHook) you can change the way in which an (API) .NET function works? Perhaps I have to learn a bit more on this front because I thought that this was almost impossible (even in case of tracking/changing the memory; how can the other programs care about this at all? Each call to the given function would use different memory locations!). I will take a further look at all this in the next days (and eventually come back to you). – varocarbas Mar 05 '14 at 13:08
  • 1
    For more information about easyhook look here: http://stackoverflow.com/questions/13354882/easyhook-net-remoting-sharing-interface-between-both-client-and-server and here:https://code.google.com/p/easyhook-continuing-detours/ But I am still looking for a way to do it in pure .net, which is possible somehow. And I swear you can use pointers in .net by using marshalling for example :P – nexno Mar 05 '14 at 13:24
  • 1
    (apparently an "objective" up-voter came to this post) Perhaps you haven't understood what I have said: I am not saying that it is not possible to emulate this library (or any other one). The only problem here is that I seriously doubt that this library can do what you want (i.e., intercepting API calls). This whole idea goes against the most basic security concept of software development (locating the exact memory position where a given function is always called and intercept it from anywhere?!). So... I have tried to say you "think about it twice/learn more" a bit softly. – varocarbas Mar 05 '14 at 13:55
  • PS: in any case any pointer-based implementation cannot be done directly in VB.NET. There are workarounds? Well... there are always workarounds but this is not a simple matter. – varocarbas Mar 05 '14 at 13:59
  • Hm, well it wasn't me. – nexno Mar 05 '14 at 14:59
  • Do you still think you can give it a try, to my problem described above, by using API Calls (Getprocessadress) and marshalling to workarround the pointer-problem in .net and show me how I can hook the messageboxa function by appending a string to the actual text? =) – nexno Mar 05 '14 at 15:00
  • Apparently there was a misunderstanding here; I will be more clear with you: ask specific questions (e.g., "how I do this and that"), with a specific example; and try to avoid generic reliance on not-too-clear ideas ("hooking different than calling as a way to intercept functions from memory"); all this is not done in this question IMO. Summary: your question (+ your clarifications via comments) is for me completely off-topic. Quicker way to get what you want? Clarify your ideas regarding what you want exactly. – varocarbas Mar 05 '14 at 15:05
  • Okay, please stop flaming right here! Both of you! Would really appreciate talkign on topic, instead of discrespecting each other we better shoudl talk about the question and how we can solve it ;) So keep calm guys. Anyone who knows how the actual hooking part with .net can be done? Normally with C++ its done by using TypeDef. – nexno Mar 05 '14 at 15:21
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/49073/discussion-between-elektrostudios-and-varocarbas) – ElektroStudios Mar 05 '14 at 15:41

1 Answers1

1

I'm not sure if this is what you are looking for, but this is how I Hook into the mouse. Maybe it can help you figure out other hooks.

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
John
  • 1,310
  • 3
  • 32
  • 58
  • Well thanks for your effort, but I am not sure how this can help me by hooking an API? How would I hook it? This hooks a mouseevent. – nexno Mar 05 '14 at 22:12
  • 1
    I don't know about an API, I just thought this might give you some direction on hooking in general. You mentioned that you were trying to learn more about hooking so I thought this might give you some insight. – John Mar 05 '14 at 22:15
  • Yeah I know about Mouse and Keyboard hooking, but what I like to learn is hooking an API, which is, I guess, a bit more difficult :/ But I know that it is possible. – nexno Mar 05 '14 at 22:16