Results 1 to 1 of 1
  1. #1
    Dwar
    Dwar is offline
    Veteran Dwar's Avatar
    Join Date
    2010 Mar
    Posts
    2,222
    Thanks Thanks Given 
    211
    Thanks Thanks Received 
    2,230
    Thanked in
    292 Posts
    Rep Power
    10

    [Tutorial] Ingame trainer menu packed into a dll

    Ingame trainer menu packed into a dll

    I will show you now how to create a DLL you can install a so called hook with that in last consequence will call your trainer menu. Preference is that you know something about DirectX9.

    The theory behind:
    We will catch the call to "EndScene" and let our own code run before executing EndScene itself.

    Q: Why do we do that?
    A: Because when the game wants to call EndScene it has done all its rendering and we can very easy do our stuff and make sure our menu is displayed on the top layer.

    Q: And were will we catch the call to EndScene?
    A: This is done inside the game/application you are hacking.

    Q: Why don't we catch the call to EndScene from the d3d9.dll where the offset of the beginning of that function is well known and that is loaded into every Direct3D process?
    A: Because sometimes the d3d9.dll gets updated. I noticed this when upgrading from SP2 to SP3 and then the offset of EndScene moved 16 bytes ahead. So the trainer won't display a menu anymore, the game will even crash. But when catching the call to EndScene from the game/app you can be sure that this offset (once found) will only change when the game gets updated and then most of the time you need to find new gamehack addresses also.

    For easy beginning our target process will be "tutorial1_eng.exe" so compile it if you haven't.
    .386						; the normal stuff
    .model flat, stdcall ; at the beginning of
    option casemap :none ; an Assembler program

    ; our selfmade functions are declared here

    TrnEng PROTO :DWORD, :DWORD, :DWORD ; a TrainerEngine that works from inside of DLLs
    check_hotkey PROTO ; a proc just to check for hotkeys

    ; now come the imports

    include /masm32/include/windows.inc
    include /masm32/include/kernel32.inc
    include /masm32/include/user32.inc

    includelib /masm32/lib/kernel32.lib
    includelib /masm32/lib/user32.lib

    .data
    FontName db 'Arial',0 ; font name
    TextToDisplay1 db 'Infinite Stuff',0 ; some text
    TextToDisplay2 db 'Unlimited Shit',0 ; some other text
    TextToDisplay3 db 'Refill my beer',0 ; and another text
    d3d9 db 'd3d9.dll',0 ; our beloved Direct3D dll
    d3dx9 db 'd3dx9_28.dll',0 ; our dll for special functions
    ; you need to lookup if your game has already
    ; loaded another version of this dll
    ; (e.g.d3dx9_30.dll), then you must take that one
    menutoggle BOOLEAN FALSE ; is menu activated?
    current_item dd 1 ; currently selected menu item
    FontFunction db 'D3DXCreateFontA',0 ; name of function to create font
    EndSceneAddy dd 132Bh ; offset of place where we want to hook in
    ; I will explain where to find such a spot
    ; in the forum post, see above

    .data?
    pd3d_device dd ? ; pointer for D3D device
    pd3d_font dd ? ; pointer for font
    hInst dd ? ; DLL instance
    dummy dd ? ; variable to store some stuff
    h_d3dx9 dd ? ; handle for d3dx9_??.dll
    oldprotection dd ? ; do we need for "VirtualProtect"
    rct RECT <> ; for displaying our text

    .const
    DrawText equ 038h ; the well known offset used for accessing the
    Release equ 008h ; VTable but this time we only need two


    When a DLL is loaded into a process then the first thing that is done is calling the "Main" function of a DLL (every DLL has only one). So here comes the important code that sets up all the stuff that needs to be done for making our menu work. While programming this DLL think always as if the target process is your own, because the DLL is; loaded into the process it becomes part of it, so you can access the process memory like in your own program

    .code
    ;#######
    Main PROC hInstDLL:DWORD,reason:DWORD,reserved1:DWORD

    pushad ; save all registers before continue

    push hInstDLL ; save the instance
    pop hInst ; of our DLL

    cmp reason,DLL_PROCESS_ATTACH ; is this function called because the DLL
    jne not_attached ; has been attached to the process?
    ; if not, then jmp to end

    ; In this place we need to complete our EndSceneAddy because until now it is only an offset. Since
    ; the call to EndScene (of our app) is inside the app (this could also be inside another DLL) we
    ; only need to add the base that windows loads our app to (most of the time 400000h)

    invoke GetModuleHandle,0 ; get base of game/app
    add EndSceneAddy,eax ; add to EndSceneAddy


    Now we want to set up our hook, that means we redirect some of the app's code (just few lines before it calls EndScene) to our own DLL. To do this we will overwrite the code with a jmp instruction (you know from Code Injection) and calculate where to jump to, because our DLL could be loaded to any place in the memory

    ; first off all get some access right
    invoke VirtualProtect,EndSceneAddy,5,PAGE_EXECUTE_READWRI TE,addr oldprotection

    mov edi,EndSceneAddy ; the full address to our injection place
    mov ebx,offset EndSceneHook ; the label of our hook, look downwards
    sub ebx,edi ; the difference is the number of bytes
    ; we need to jump forward/backward
    sub ebx,5 ; subtract 5 bytes because of the jmp
    mov byte ptr [edi],0E9h ; 0E9h means far jump
    inc edi ; 1 byte behind 09Eh comes distance of jmp
    mov dword ptr [edi],ebx ; ebx contains distance to jump, 4 bytes

    ; restore old access rights
    invoke VirtualProtect,EndSceneAddy,5,oldprotection,addr dummy

    add EndSceneAddy,5 ; after showing our menu we jump back
    ; behind our injected jump, so plus 5 bytes

    ; this thread is only for checking hotkeys
    invoke CreateThread,0,0,offset check_hotkey,0,NORMAL_PRIORITY_CLASS,addr dummy

    not_attached: ; here do we get, when DLL is not attached

    popad ; restore all registers

    mov eax,TRUE ; everything is good
    ret ; return

    Main ENDP
    ;#######

    EndSceneHook: ; to this label jumps the d3d9.dll
    ; after redirection, so instead of calling
    ; EndScene this stuff is called first

    mov eax,4030ACh ; get the D3D device pointer
    push [eax] ; and save it in our variable
    pop pd3d_device ; I need to do a trick here because
    ; push dword ptr [4030ACh]
    ; pop pd3d_device
    ; does not work for me somehow

    pushfd ; save the flag status
    pushad ; save all registers
    ; so we can't mess around with them

    call DrawMenu ; go, draw our menu

    popad ; restore all register
    popfd ; restore the flag status

    mov eax,4030ACh ; original games/apps code, we need to
    mov eax,[eax] ; restore because we have overwritten it
    ; with a jump, remember?
    ; here the trick is also done, important is
    ; only that eax holds the pointer in the
    ; end ... see games code

    jmp EndSceneAddy ; jmp back into games/apps code
    ; to execute real EndScene function


    the easy thing here is that we don't need to create a D3D device because the game has already done this, so we can just start with the stuff that normally belongs into the "render" proc
    DrawMenu PROC

    cmp menutoggle,TRUE ; is the menu toggled on?
    jne outta_here ; if not then jump away from here

    invoke GetActiveWindow ; the active window is the game, mostly
    invoke GetClientRect,eax,addr rct ; were we are allowed to draw?
    add rct.top,50 ; don't draw at the very top


    I do here a "LoadLibrary" for standard, because maybe the game hasn't loaded the D3D special DLL yet. So LoadLibrary gives me the handle to it no matter wether it must be loaded or already is But if you know that the game has it loaded already then of course you can use "GetModuleHandle".
    invoke LoadLibrary,addr d3dx9				; load DLL and get handle
    invoke GetProcAddress,eax,addr FontFunction ; ge the address for font creation
    mov ecx,eax ; save in ecx

    push offset pd3d_font ; pointer to store VTable for font
    push offset FontName ; name of the font
    push (DEFAULT_PITCH+FF_DONTCARE) ; format to display
    push 4 ; quality
    push OUT_DEFAULT_PRECIS ; precision
    push DEFAULT_CHARSET ; character set normal
    push FALSE ; italics?
    push 1 ; MipMap levels or something
    push FW_NORMAL ; how bold are the letters
    push 0 ; how wide are the letters
    push 22 ; font size
    push pd3d_device ; the game's D3D device (VTable)
    call ecx ; call D3DXCreateFontA

    .if current_item == 1 ; the menu item that is selected
    push 0FFFF0000h ; will have another colour
    .else
    push 0FFFFFF00h ; standard color
    .endif
    push offset TextToDisplay1
    call DrawTextLine ; my own little function to make life a bit
    ; easier

    .if current_item == 2
    push 0FFFF0000h
    .else
    push 0FFFFFF00h
    .endif
    push offset TextToDisplay2
    call DrawTextLine

    .if current_item == 3
    push 0FFFF0000h
    .else
    push 0FFFFFF00h
    .endif
    push offset TextToDisplay3
    call DrawTextLine

    mov eax,pd3d_font
    push eax
    mov ecx,[eax]
    call dword ptr [ecx+Release] ; release our font again


    Because the font is created in every cycle we must destroy it in every cycle.
    outta_here:
    ret

    DrawMenu ENDP
    ;#######
    DrawTextLine PROC TheText:DWORD,TheColor:DWORD

    push TheColor ; font colour
    push (DT_LEFT or DT_NOCLIP or DT_CENTER) ; format, experiment with it
    push offset rct ; rectangle that is plotted in
    push -1 ; our string is zero terminated
    push TheText ; the text
    push 0 ; no text inside a sprite
    mov eax,pd3d_font
    push eax
    mov ecx,[eax]
    call dword ptr [ecx+DrawText] ; draw the text

    add rct.top,eax ; the return value in eax is the height
    ; of the drawn text, so just add it to our
    ; y-coordinate and we are writing in the
    ; next line

    ret ; back

    DrawTextLine ENDP
    ;#######
    check_hotkey PROC


    In this proc comes everything that has to do with controling your menu, be creative. Maybe you can also handle with the left and right arrow keys to set a variable (e.g. mov IsGodMode,TRUE) and then have a check in the DrawMenu proc that changes the text (e.g. GodMode ... OFF -> GodMode ... ON) or something like that. Do whatever you want.

    _again:

    invoke Sleep,100 ; only check every 0.1 seconds

    invoke GetAsyncKeyState,VK_F1
    .if eax != 0
    mov menutoggle,TRUE ; menu on
    .endif

    invoke GetAsyncKeyState,VK_F2
    .if eax != 0
    mov menutoggle,FALSE ; menu off
    .endif

    invoke GetAsyncKeyState,VK_UP
    .if eax != 0
    .if (current_item > 1 && menutoggle == TRUE) ; if the first item is selected, don't
    dec current_item ; move one item upwards
    .endif
    .endif

    invoke GetAsyncKeyState,VK_DOWN
    .if eax != 0
    .if (current_item < 3 && menutoggle == TRUE) ; if the last item is selected, don't
    inc current_item ; move one item downwards
    .endif
    .endif

    jmp _again ; check again

    check_hotkey ENDP
    ;#######
    TrnEng PROC Address:DWORD,lpNewValue:DWORD,nByte:DWORD

    ; This is a TrainerEngine for being inside a DLL that is loaded to target process. As I had
    ; explained above we don't need this "WriteProcessMemory" stuff because we can imagine we are
    ; in our own process

    invoke VirtualProtect,Address,nByte,PAGE_EXECUTE_READWRIT E,addr dummy
    mov ecx,nByte ; amount to copy
    mov esi,lpNewValue ; location to copy from
    mov edi,Address ; location to copy to
    rep movsb ; copy
    ret

    TrnEng ENDP
    ;#######
    END Main ; a DLL must end with name of main proc


    by Flyke
    Please, post your questions on forum, not by PM or mail

    I spend my time, so please pay a little bit of your time to keep world in equilibrium

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •