Results 1 to 5 of 5
  1. #1
    u.A.v.A's Avatar
    Join Date
    Feb 2012
    Gender
    male
    Posts
    640
    Reputation
    17
    Thanks
    621

    Hooking the unreal engine

    Now onto some examples of how to hook into the unreal engine using vtables. I will be using the vmthooks library written by Casual_Hacker over at Game/Deception to abstract the whole hooking process. If you wish to adapt your own feel free to do so.

    You will also need an SDK for the game you are hacking (uNrEaL has released alot for the unreal engine).

    First we would create a new DLL. The OnAttach function is what will be called when you inject your DLL into the game.

    Code:
    BOOL WINAPI DllMain ( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
    {
        if ( dwReason == DLL_PROCESS_ATTACH )    
            OnAttach ();
        
        return TRUE;
    }
    Basic stuff really. Then we will need to declare some global variables and includes that we will be using later one. You can do this in a separate header if you like, or not.

    Code:
    #pragma once //Header guard
    #include <windows.h> // duh
    #include "vmthooks.h" //vmt hooking class
    #include "SDKheaders.h" //SDK headers
    
    toolkit::VMTHook* hook; //Pointer to the VMTHook class
    typedef void (__stdcall *ProcessEvent ) ( UFunction*, void*, void* ); //typedef for the processevent function pointer
    ProcessEvent pProcessEvent = NULL; //pointer to original processevent
    UFunction *pUFunc                        = NULL; //pointers to processevent arguements
    void      *pParms                        = NULL;
    void      *pResult                        = NULL;
    If you aren't sure what these will be used for, I will get to that later. Next you will need to start by implementing the OnAttach function and the first thing you need to do is find an instance of the object you want to hook. Good classes to hook for the unreal engine are the "HUD class", the "Viewport class" and the "PlayerController". In my example I'll be hooking the viewport class, as it allows engine drawing in postrender.

    Code:
    UObject* viewport = getViewport(); //get a pointer to the viewport
        hook = new toolkit::VMTHook(viewport); //hook object
        pProcessEvent = hook->GetMethod<tProcessEvent>(60); //save the orginal funtion in global variable
        hook->HookMethod(&ProcessEventHooked, 60); //replace the orginal function with the hooked function
    I'll leave it up to you to find the viewport, it shouldn't be hard and there are many ways to do it. (tip: use the object dump (GObjects). Next we hook the object using the VMThook class. This will allow you to manipulate teh vtable. Make sure you store a pointer to the old pProcesEvent. Its at index 60 for APB, not sure about other unreal games.

    Then proceed by replacing the Vtable with a copy( Don't modify the orginal or your hack will be much easier to detect) and now replace the pointer at the proper index with a pointer to your own hooked function, which we still need to make.

    Code:
    void __declspec(naked) ProcessEventHooked ()
    {
    
        __asm mov pCallObject, ecx; //get caller from ecx register and save it in pCallObject
    
        __asm
        {
            push eax
            mov eax, dword ptr [esp + 0x8]
            mov pUFunc, eax
            mov eax, dword ptr [esp + 0xC]
            mov pParms, eax
            mov eax, dword ptr [esp + 0x10]
            mov pResult, eax
            pop eax        
        } // Manually get the proper parameters for the function
    
        __asm pushad //Save registers on stack   
        //Do stuff here!
        __asm popad //restore registers from stack
        __asm
        {
            push pResult
            push pParms
            push pUFunc
            call pProcessEvent
    
            retn 0xC
        } //put parameters on stack and call the orginal function
    
    }
    This is an empty template for the a hooked processevent function (thanks lowHertz!). I'll try to explain briefly what goes on here (as far as my understanding of it goes).

    __declspec(naked) is a calling convention that basicly leaves it to the programmer to prepare and clean the stack for the function. Don't ask me for details, I basicly c&p this from lowHertz :P.

    With the first line we take a pointer from the ECX register, this pointer points to the object that called the function. Since in my method we already have a pointer to the correct object this is not really necessary.

    The block that follows is asm for putting the arguments (that the orginal function got called with) into the global variables you declared earlier. You also need these to call the orginal function later.

    pushad saves the registers on the stack. So now you can execute whatever code you want and afterwards it restores the registers to their orginal state by popping them off the stack with popad.

    The last bit pushes the arguments onto the stack and calls the orginal function, which you stored earlier. If all is well then the orginal function executes properly and the game resumes as it would usually.

    Virus Scans
    virus total
    Jotti

    Edit: things above used APB as example
    <b>Downloadable Files</b> Downloadable Files
    Last edited by u.A.v.A; 05-16-2012 at 01:35 PM.

  2. The Following 23 Users Say Thank You to u.A.v.A For This Useful Post:

    BeastlyFX (05-16-2012),DAR10F (07-19-2012),DarkSt0rmX (05-22-2012),DryHunter86 (03-16-2014),Heino11 (07-17-2012),ifeldr (05-28-2012),JihadiJohns (03-05-2016),kevintjuh (06-09-2012),kkkk11kk (06-06-2014),ledimiku (09-04-2012),lilpac (06-07-2012),Markcenter (05-30-2012),maxrio (11-13-2013),MyBrute (06-09-2016),ramboamadeus (10-28-2012),riscoooo (06-18-2012),rocmaster97 (05-30-2012),TheBlackSmith (11-12-2012),Wednysday22 (09-14-2015),XxDonnie97 (06-10-2012),xxshootxx123 (06-28-2012),XXslimjimXX (02-03-2013),yangyuejia (08-22-2012)

  3. #2
    BeastlyFX's Avatar
    Join Date
    Dec 2011
    Gender
    male
    Location
    North Adams, MA
    Posts
    5
    Reputation
    10
    Thanks
    2
    Thanks man! Helped me ALOT.

  4. #3
    MuslimSoldier's Avatar
    Join Date
    Feb 2012
    Gender
    male
    Posts
    51
    Reputation
    10
    Thanks
    18
    what is this xd what does it do and how can you activate it or install it xD

  5. The Following User Says Thank You to MuslimSoldier For This Useful Post:

    lilpac (06-07-2012)

  6. #4
    Ba.avr1's Avatar
    Join Date
    Sep 2011
    Gender
    male
    Posts
    54
    Reputation
    10
    Thanks
    375
    My Mood
    Hungover
    Tnx man =)

  7. #5
    bigbang26's Avatar
    Join Date
    Aug 2011
    Gender
    male
    Posts
    2
    Reputation
    10
    Thanks
    0
    My Mood
    Crappy
    VMT Hooking Library


    Download: Sedo Domain Parking - Sedo GmbH
    Doesn't have a license so use however you like, but I appreciate some credits.

    Long-ass documentation post incoming






    Introduction

    I assume you have a decent knowledge of how virtual functions are implemented and what vtables are in C++, if not I suggest you read this first.

    Virtual functions can be hooked in 2 distinct manners:
    • Overwrite the function pointers of the vtable in .rdata. The result is that every instance using that vtable will have its functions hooked. However due to the vtable being located in read-only memory anti-cheats may have an easy time to detect these.
    • Replace the vtable pointer of a specific instance. The result is that only virtual functions of that specific instance will be hooked. Depending on the circumstances it may be VERY difficult for an anti-cheat to detect these.


    However there are 3 different use cases for hooking virtual functions (2 for instance hooking, 1 for .rdata hooking).






    Use case 1: Hook virtual functions of a global instance.

    Use the VMTManager class.
    This is intended to hook global instances (like the interfaces in the Source Engine).

    Methods:

    VMTManager::VMTManager( void* inst, size_t offset = 0, uint vfuncs = 0 );
    Constructor. offset is the offset of the vtable in the instance, can be different from 0 when it is using multiple inheritance. vfuncs Leave 0 if you want it to figure out the number of vfuncs itself.

    VMTManager::~VMTManager();
    Destructor. Will call Unhook() before destructing. If the instance you're hooking is gone at this point it'll crash. See Poof().

    void VMTManager::HookMethod( void* newfunc, size_t index );
    Hook a function by index.

    void VMTManager::UnhookMethod( size_t index );
    Unhook a function by index.

    void VMTManager::Unhook();
    Puts the original vtable pointer back in place. This means the instance looks like it's NOT hooked at all.

    void VMTManager::Rehook();
    Puts our vtable with the hooks back.

    bool VMTManager::Hooked() const;
    Returns true if the instance is hooked.

    void VMTManager::EraseHooks();
    Removes all the currently placed hooks. The instance will still appear hooked, however all vfuncs will redirect to their original functions.

    uint VMTManager::NumFuncs() const;
    Access the vfunc count member.

    void VMTManager::Poof();
    If the instance is somehow destroyed before you get a chance to unhook it or destruct this hook object, call this. It'll prevent the destructor from crashing.
    Do NOT attempt to use the this object after calling Poof(), bad things will happen.

    template< typename Fn > Fn VMTManager::GetMethod( size_t index ) const;
    Get the original function. I highly suggest this over unhooking.
    Use a function prototype for the template argument to make it very easy to call this function. Example syntax: hook.GetMethod<bool (__thiscall*)( void*, int )>( 12 )( inst, arg );


    How I use it in my hack:
    [php]#include "vmthooks.h"

    // Indices of the virtual functions
    enum
    {
    CLIENT_HUDUPDATE = 9,
    CLIENT_DISPATCHUSERMESSAGE = 34,
    CLIENT_CREATEMOVE = 19,
    };

    // Hooked function prototypes
    typedef void (__thiscall* CreateMoveFn)( void* thisptr, int sequence_number, float input_sample_frametime, bool active );
    typedef void (__thiscall* HudUpdateFn)( void* thisptr, bool active );
    typedef bool (__thiscall* DispatchUserMessageFn)( void* thisptr, int msg_type, bf_read& msg_data );

    // Hook Manager (just a small example)
    class CHookMgr
    {
    public:
    // Initializing
    void Init();
    void Close();

    // Hooks in pClient
    static void __fastcall Hooked_CreateMove( void* thisptr, int edx, int sequence_number, float input_sample_frametime, bool active );
    static void __fastcall Hooked_HudUpdate( void* thisptr, int edx, bool active );
    static bool __fastcall Hooked_DispatchUserMessage( void* thisptr, int edx, int msg_type, bf_read& msg_data );

    // Stored here for easy access
    typedef toolkit::VMTManager hook_t;
    hook_t* pClientHook;
    };

    extern CHookMgr* HookMgr;

    // Source file
    #include "hookmgr.h"

    CHookMgr* HookMgr = NULL;

    void CHookMgr::Init()
    {
    pClientHook = NULL;
    if ( Interfaces->pClient )
    {
    static hook_t hook( Interfaces->pClient );
    pClientHook = &hook;
    hook.HookMethod( &Hooked_HudUpdate, CLIENT_HUDUPDATE );
    hook.HookMethod( &Hooked_CreateMove, CLIENT_CREATEMOVE );
    hook.HookMethod( &Hooked_DispatchUserMessage, CLIENT_DISPATCHUSERMESSAGE );
    }
    // Etc for other interfaces...
    }
    void CHookMgr::Close()
    {
    // Because the hook was a local static member it'll keep on existing until our .dll is effectively unloaded.
    // Hence why I call ->Poof() to ensure that once we unload, it won't attempt to access it.
    if ( pClientHook ) { pClientHook->Unhook(); pClientHook->Poof(); }
    // Etc...
    }

    // Hooked functions abusing the __fastcall calling convention to grab the 'this' pointer without inline ASM.
    // Do not worry about saving registers as microsoft's compiler will do that for us.

    void __fastcall CHookMgr::Hooked_HudUpdate( void* thisptr, int edx, bool active )
    {
    HookMgr->pClientHook->GetMethod<HudUpdateFn>( CLIENT_HUDUPDATE )( thisptr, active );
    }
    void __fastcall CHookMgr::Hooked_CreateMove( void* thisptr, int edx, int sequence_number, float input_sample_frametime, bool active )
    {
    HookMgr->pClientHook->GetMethod<CreateMoveFn>( CLIENT_CREATEMOVE )( thisptr, sequence_number, input_sample_frametime, active );
    }
    bool __fastcall CHookMgr::Hooked_DispatchUserMessage( void* thisptr, int edx, int msg_type, bf_read& msg_data )
    {
    return HookMgr->pClientHook->GetMethod<DispatchUserMessageFn>( CLIENT_DISPATCHUSERMESSAGE )( thisptr, msg_type, msg_data );
    }
    [/php]






    Use case 2: Hooking virtual functions of dynamically created instances (like entitites).

    Use the DynManager<type,guard> class.
    A nice side effect is that this method allows us to attach extra bits of data we may want to use.

    This class exploits the idea that you can add some more entries to the vtable to hold whatever extra data you might want. Let's take a look at how that would work:
    Code:
                                     v Actual vtable comes here  ->
    +----------+----------+----------+----------+----------+--------
    | hook ptr |  guard   | RTTI ptr | vfunc #1 | vfunc #2 | ...   
    +----------+----------+----------+----------+----------+--------
    hook ptr: A pointer back to the hook object
    guard: Allows us to detect if this instance has been hooked or not.
    RTTI ptr: Let's not forget about this guy.

    Extending the VMTManager class it adds some extra functionality. Important however is that, should you Unhook() the instance there's no way we can figure out if the instance was hooked! Hence Unhook() and Rehook() are disabled.

    Methods:

    DynManager<T,S>:ynManager( void* inst, size_t offset = 0, uint vfuncs = 0 );
    Same as VMTManager.

    void DynManager<T,S>::Unhook();
    void DynManager<T,S>::Rehook();

    Shouldn't be used. While you can bypass this restriction I still highly discourage it.

    T* DynManager<T,S>::UserData() const;
    void DynManager<T,S>::UserData( T* data );

    Retrieve or set the UserData pointer you've associated with this instance.

    static bool DynManager<T,S>::HookPresent( void* inst, size_t offset = 0 );
    Checks if the instance is already hooked, offset is the offset of the vtable in the instance.

    static DynManager<T,S>* DynManager<T,S>::GetHook( void* inst, size_t offset = 0 );
    Gets the hook object for an instance, returns NULL if there isn't.

    static DynManager<T,S>* DynManager<T,S>::GetOrCreateHook( void* inst, size_t offset = 0, size_t vfuncs = 0 );
    Gets the hook object for an instance, creates a new one if there isn't already one. I consider this one deprecated.


    How I use it in my hack:

    entdata_t is a struct which contains some extra data I wish to use with the entity. This can be anything you want, I use it for some resident aimbot vars and others.
    At any point you can request the entdata_t for an entity with this:
    entdata_t* edata = EntData->GetOrCreateData( pEnt );

    Since entities in Source Engine use multiple inheritance I need more than 1 hook object to hook it. The destructor in IClientEntity needs to be hooked as well as I want to hook DrawModel in IClientRenderable. Instead of specifying the vtable offset I let the compiler figure that out by simply casting it.
    These 2 hook objects are hook_client and hook_render, both their UserData points back to the entdata_t* object. This is how GetOrCreateData gets back at it.

    A simplified overview:

    [php]
    // Declarations
    struct entdata_t;
    typedef toolkit:ynManager<entdata_t,0x08192A3B> enthook_t;

    // Manages entity data
    class CEntMgr
    {
    public:
    void Init();
    void Close();
    // Get the data for an entity
    entdata_t* GetOrCreateData( IClientEntity* pEnt );
    // Hooked destructor cleans up
    static void __fastcall Hooked_Destructor( IClientEntity* thisptr, int edx, unsigned int flags );

    private:
    typedef std::set<entdata_t*> mgr_t;
    mgr_t _datamgr;
    };

    extern CEntMgr* EntData;


    // Data attached to entities
    struct entdata_t
    {
    entdata_t( IClientEntity* pEnt );

    // Entity we're attached to
    IClientEntity* pEnt;

    // The hooks
    enthook_t hook_client;
    enthook_t hook_render;

    // Data members
    float spawntime;

    // Velocity
    bool calcvel;
    Vector velocity;
    Vector accel;

    // Aimbot vars
    float priority;
    float viewfov;
    float distance;

    // etc...
    };


    // Source file
    #include "entdata.h"
    CEntMgr* EntData = NULL;

    void CEntMgr::Close()
    {
    // Clean up as there might be some hooks remaining when we're unloaded
    mgr_t::iterator end = _datamgr.end();
    for ( mgr_t::iterator it = _datamgr.begin(); it!=end; ++it )
    {
    // Cleanup the entdata_t
    delete (*it);
    }
    _datamgr.clear();
    }

    entdata_t* CEntMgr::GetOrCreateData( IClientEntity* pEnt )
    {
    // Get the hook
    enthook_t* pHook = enthook_t::GetHook( pEnt );
    if ( !pHook )
    {
    entdata_t* edata = new entdata_t( pEnt );
    // Hook the destructor to allow us to clean up
    edata->hook_client.HookMethod( &Hooked_Destructor, 0 );
    // Register this edata in the manager
    _datamgr.insert( edata );
    return edata;
    }
    return pHook->UserData();
    }

    void __fastcall CEntMgr::Hooked_Destructor( IClientEntity* thisptr, int edx, unsigned int flags )
    {
    // This hook would not be called if it wasn't hooked. So GetHook() will always return something.
    entdata_t* edata = enthook_t::GetHook( thisptr )->UserData();
    // Remove it
    EntData->_datamgr.remove( edata );
    delete edata;
    // Hook is now deleted, call original destructor
    toolkit::getvfunc<void (__thiscall*)( IClientEntity*, unsigned int )>( thisptr, 0 )( thisptr, flags );
    }

    entdata_t::entdata_t( IClientEntity* pEnt ) : hook_client( pEnt ), hook_render( static_cast<IClientRenderable*>( pEnt ) ),
    spawntime( Interfaces->pGlobals->curtime ), calcvel( IsPlayer( pEnt ) )
    {
    this->pEnt = pEnt;
    // Allow is to connect back to this data
    hook_client.UserData( this );
    hook_render.UserData( this );
    }


    [/php]






    Use case 3: Hooking vtables directly.

    Use the VMTHook class.
    Every instance using the hooked vtable will have its functions hooked.
    This means only instances of the EXACT type you're hooking, derived or base classes won't be hooked.

    Methods:

    VMTHook::VMTHook( void* inst, size_t offset = 0, uint vfuncs = 0 );
    Hook the vtable of this instance. offset and vfuncs are again optional.

    [u]VMTHook::VMTHook( void** vmt, uint vfuncs = 0 );[/i]
    Hook the given vtable.

    VMTHook::~VMTHook();
    Destructor

    void VMTHook::HookMethod( void* new_func, size_t index );
    Hooks a function by index.

    void VMTHook::UnhookMethod( size_t index );
    Unhooks a function by index.

    void VMTHook::Unhook();
    Unhook the vtable. This requires the vtable to by physically swapped with a backup.

    void VMTHook::Rehook();
    Rehook the vtable.

    bool VMTHook::Hooked();
    Returns if the hooks are currently active.

    template< typename Fn > Fn VMTHook::GetMethod( size_t index ) const;
    Get the original function.
    Use a function prototype for the template argument to make it very easy to call this function.
    Example syntax: hook.GetMethod<bool (__thiscall*)( void*, int )>( 0x5 )( inst, arg );


    Idk, just use it the same as you would VMTManager. I don't personally use it due to its detectability but I wanted to include it for the sake of completeness anyway.






    Utility funcs

    uint CountFuncs( void** pVMT );
    Queries memory using VirtualQuery and as long as vfunc pointers land in PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE memory it keeps counting.

    This is more accurate than my previous method of using module bounds (which would fail if the vtable was already hooked).

    uint CountFuncs( void* begin, void* end, void** pVMT );
    Simply count funcs as long as the vfunc ptr lies in [begin;end[

    int FindFunc( void** pVMT, void* pFunc, uint vfuncs = 0 );
    Simply iterates trough the vfuncs and returns the index of pFunc. Leave vfuncs 0 if you want it to count the number of vfuncs itself.



    Conclusion

    While chatting with Xeno he suggested to use a 'database' thingy and dynamically retrieve the indices to make your hack more resistent to updates.

    I think this is everything you can possibly do with vmt hooking. Have fun!

Similar Threads

  1. [GUIDE]Hooking the source engine.
    By Hell_Demon in forum C++/C Programming
    Replies: 15
    Last Post: 02-23-2010, 05:33 PM
  2. (TuT) Hacking HP on Unreal Engine 2 Games
    By Trip-FX in forum General Game Hacking
    Replies: 1
    Last Post: 10-12-2008, 01:31 PM
  3. can some 1 teach me how to use the cheat engine 5.4
    By klk101 in forum WarRock - International Hacks
    Replies: 16
    Last Post: 09-17-2008, 12:38 PM
  4. I Need The Real Engine.exe
    By kimodragon in forum Combat Arms Hacks & Cheats
    Replies: 6
    Last Post: 08-28-2008, 10:39 PM
  5. How can i hook the punkbuster?
    By TheRedEye in forum WarRock - International Hacks
    Replies: 5
    Last Post: 05-27-2007, 01:34 PM