Thread: Hooking my own program with a trampoline and VirtualAlloc()/VirtualProtect()

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    Hooking my own program with a trampoline and VirtualAlloc()/VirtualProtect()

    Hello, lately I've been venturing into the world of hooking. I've been wanting to hook the send() and recv() API functions, but I am starting small first. Before I forget, here are my system statistics :

    Windows Edition :
    Windows 7 home premium
    Service Pack 1
    Processor :
    AMD athlon(tm) II X2 250
    System type : 64 - bit operating system

    I have been using the article here ( x86 API Hooking Demystified | Development & Security ), to try to learn how to use machine code patches to jump to my functions and then return. In the code below, I'm using 32-bit machine instructions because I'm confused on the bitness of my console application. That may be part of my problem of course, since it apparently translates it as a ADD instruction instead of the desired JMP instruction. I'm also having lots of problems making the memory I allocate virtually in my process writable, since it seems even though it allocates it sucessfully with full read/write/execute access it still throws an access violation error when I write to it. Here is the code :


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    
    #include <math.h>
    
    
    #include <windows.h>
    
    
    void win_error( char * message, BOOL exit )
    {
        char buffer[BUFSIZ] = { 0 };
        DWORD error_code = GetLastError( );
    
    
        FormatMessage
        (
            FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            error_code,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) buffer,
            BUFSIZ,
            NULL
        );
    
    
        MessageBox(NULL, buffer, message, MB_ICONWARNING | MB_OK );
    
    
        if ( exit ) ExitProcess( error_code );
    
    
        return;
    }
    
    
    void function_a( )
    {
        /* Do some stuff */
        int stuff = 0;
        stuff = pow( 2, 5 );
    
    
        printf( "Important stuff from function a : %d\n", stuff );
    
    
        return;
    }
    
    
    void function_b( )
    {
        /* Do some stuff */
        int stuff = 0;
        stuff = pow( 10, 5 );
    
    
        printf( "Important stuff from function b : %d\n", stuff );
    
    
        return;
    }
    
    
    int main( )
    {
        void ( * function_trampoline ) ( ) = NULL;
    
    
        DWORD process_id = 0;
        HANDLE process_handle = NULL;
    
    
        BYTE * memory = NULL;
    
    
        BYTE jmp_instruction[] = { 0xE9, 0x00, 0x00, 0x00, 0x00, 0x90 };
        memset( &jmp_instruction[1], ( uint32_t )function_b, sizeof( jmp_instruction - 1 ) );
    
    
        BYTE jmp_instructionB[] = { 0xE9, 0x00, 0x00, 0x00, 0x00, 0x90 };
        memset( &jmp_instructionB[1], ( uint32_t )( function_a + sizeof( jmp_instruction ) ), sizeof( jmp_instructionB - 1 ) );
    
    
        BYTE prev_opcodes[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    
    
        if ( !( memory = ( BYTE * )VirtualAlloc( NULL, sizeof( jmp_instruction ), MEM_RESERVE, PAGE_EXECUTE_READWRITE ) ) )
            win_error( "VirtualAlloc( )", TRUE );
    
    
        process_id = GetCurrentProcessId( );
        if ( !( process_handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, process_id ) ) )
            win_error( "OpenProcess( )", TRUE );
    
    
        if ( !FlushInstructionCache( process_handle, memory, sizeof( jmp_instruction ) ) )
            win_error( "FlushInstructionCache( )", TRUE );
    
    
        if ( !ReadProcessMemory( process_handle, function_a, &prev_opcodes, sizeof( jmp_instruction ), NULL ) )
            win_error( "ReadProcessMemory( )", TRUE );
    
    
        if ( !WriteProcessMemory( process_handle, function_a, &jmp_instruction, sizeof( jmp_instruction ), NULL ) )
            win_error( "WriteProcessMemory( )", TRUE );
    
    
        memset( memory, ( uint32_t )prev_opcodes, sizeof( prev_opcodes ) );
        function_trampoline = ( void * )memory;
        function_a( );
        function_trampoline( );
    
    
        CloseHandle( process_handle );
        if ( !VirtualFree( memory, 0, MEM_RELEASE ) )
            win_error( "VirtualFree( )", TRUE );
    
    
        return 0;
    }
    I usually get a segmentation fault at the memset() line, I tried using more conventional functions( e.g. WriteProcessMemory() ), but it's apparently not a valid address in my process. I read in the documentation somewhere that it doesn't actually activate the memory until I write something to it, so I tried using memset(). This has caused undefined behavior so far, usually in the form of a violation error. I have also gotten past the memset() function without it throwing that violation error, but it gets a violation error when on the first part of function_a. I'm guessing this is my fault for using invalid machine instructions, but I'm not entirely sure what I need to use instead. When I disassemble it, it just appears with the ADD instruction as I mentioned earlier. I added a NOP instruction to see if that might help, but memset() started to throw errors so I can't see what my change did.

    As far as my goal goes, I think the method I would prefer is to dynamically patch the import/export address table to Ws2_32.dll in the PE to my function, but I'm still not entirely sure how to enumerate through the modules and patch them correctly( as is obvious in the code I've written so far ). If anyone could give me some tips on this, that would be extremely helpful.

    Note : Yes I know about Detours, Deviare, EasyHook, etc. libraries. I would rather write my own instead of relying on programs that I've read can either work or be extremely unstable.

    Edit : Note that I'm not interested in doing this globally or system-wide, I just want to do it for a specific process( e.g. internet explorer ) for my eventual goal.

    Edit 2 : If someone does post an example, please don't do it in VC++. Also, I suppose I should supply a valid reason for wanting to learn this. I simply want to intercept any protocols sent and recieved from a process using the internet because I'm curious about how it would look for different processes, and I want to learn about hooks in case I ever need to use it.
    Last edited by HelpfulPerson; 11-09-2013 at 10:36 AM.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  2. #2
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    Honestly?

    What does hooking have to do with all that opcode junk? And why can't you use a debugger (which will tell you exactly why the memset fails, most probably because you're not aware of DEP and other segmentation protections).

    This is the second or third time you've presented similar code/problems and don't seem to have got an inch further. If you want to intercept packets, do so. You'll notice that programs which do that don't do this sort of junk (but usually have a system-driver-level driver of some kind, e.g. firewalls, Wireshark, etc.). If you want to experiment with hooks (which appears to be the latest "Look how I hack" buzzword), then do so. But you don't do it like this. And you certainly don't do it by seemingly injecting machine code into the memory of other processes (20 years ago, that might have worked).

    It's just INCREDIBLY suspicious that you are trying to do this without any reasonable explanation and without even the skill to run your program in a debugger and find out where/why it crashes (which takes, what, 20 seconds?)

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  3. #3
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288
    Quote Originally Posted by ledow View Post
    What does hooking have to do with all that opcode junk? And why can't you use a debugger (which will tell you exactly why the memset fails, most probably because you're not aware of DEP and other segmentation protections).
    I said why it fails, that it was an access violation. I may not have been very clear, but I was trying to explain that at first memset() worked fine, but I assumed it was undefined behavior because my debugger eventually caught up and reported the violation.

    As far as my opcodes, yes I don't know how to use machine code very well, I figured I might as well bring my best attempt instead of nothing at all. Apparently, it just made you think I was just some idiot trying to hack.

    Quote Originally Posted by ledow View Post
    This is the second or third time you've presented similar code/problems and don't seem to have got an inch further.
    What do you mean? None of my problems that I've posted consecutively have been very similar. Most of the most recent ones I posted were about SDL, and I didn't have time to form a response because I can't access this website at school. It's not like I'm still abusing multi-threading and I'm completely ignorant of your advice every time. If you want me to post some code showing that I fixed it just say it outright.

    Quote Originally Posted by ledow View Post
    If you want to intercept packets, do so. You'll notice that programs which do that don't do this sort of junk (but usually have a system-driver-level driver of some kind, e.g. firewalls, Wireshark, etc.).
    Can you provide some more information about that? I didn't even think about trying to capture packages directly. Criticizing me about it doesn't help me change...

    Quote Originally Posted by ledow View Post
    It's just INCREDIBLY suspicious that you are trying to do this without any reasonable explanation and without even the skill to run your program in a debugger and find out where/why it crashes (which takes, what, 20 seconds?)
    I already described what debugging I did and found out where it crashes and why. The where and why I mentioned was that I was writing invalid opcodes, I was writing to an apparently still protected page in my process, and memset was failing sometimes and sometimes not. All causing what I thought to be is undefined behavior. Again, my previous post wasn't very clear, and I apologize, but I'm not sure why you are saying that I didn't do any debugging at all.

    As far as it being suspicious, it indeed is. I can ensure you that I'm not just trying to be some kid trying to randomly hack programs with horribly written code. Really I just wanted to capture packets, and I thought a hook could help me do that. If I used the wrong tool, you don't have to be angry at me for it. All I wanted was someone to post some relevant information to lead me in the right direction if I wasn't going in a way I was supposed to.

    I figured that I would either get some angry person ranting at my "poor skills", or someone helpful that would give me a guide to get me on track to where I want to be, apparently I just got an angry person.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Hooking information from a third party program
    By phantom in forum C++ Programming
    Replies: 2
    Last Post: 10-11-2009, 12:38 PM
  2. new invokes VirtualAlloc
    By George2 in forum C++ Programming
    Replies: 12
    Last Post: 01-29-2008, 03:58 AM
  3. VirtualAlloc() and free()?
    By cpjust in forum Windows Programming
    Replies: 2
    Last Post: 01-21-2008, 10:55 AM
  4. new and VirtualAlloc
    By George2 in forum C++ Programming
    Replies: 12
    Last Post: 01-13-2008, 09:13 AM
  5. VirtualAlloc help
    By Elysia in forum C++ Programming
    Replies: 10
    Last Post: 12-09-2007, 09:32 AM