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