;================================================= ===============================
; Titel: The 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 DirectX 9, I have already written a tutorial about
; that so I will not explain too much here
; The theory behind:
; We will catch the call to "EndScene" and let our own code run before executing EndScene itself.
; Why do we do that? 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.
; And were will we catch the call to EndScene?
; This is done inside the game/application you are hacking.
; 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?
; 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.
; IMPORTANT: I will explain how to find the place where EndScene is called from the game/app in
; the forum post you hopefully got this tutorial from.
; 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
.gif)
WORD,
.gif)
WORD,
.gif)
WORD ; 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
.gif)
WORD,reason
.gif)
WORD,reserved1
.gif)
WORD
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
; see first tutorial
;################################################# ############################################
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
.gif)
WORD,TheColor
.gif)
WORD
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
.gif)
WORD,lpNewValue
.gif)
WORD,nByte
.gif)
WORD
; 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