DABhand
26-08-2005, 16:56
http://www.vwaskar.pwp.blueyonder.co.uk/asm4FF/asmtrain.txt if you want to read as it is
Here it comes
Building an ASM Trainer from a Skeleton Build
=============================================
Needed-
1. MASM (http://www.masm32.com/)
2. Trainer Skeleton Build (http://www.vwaskar.pwp.blueyonder.co.uk/asm4FF/trainerasm.rar - Thanks Sheep for releasing this ;) )
3. Helps to know basic ASM at least :P
Ok why an ASM trainer and not using TMK or other easy to build trainer programs, well ASM has a huge size advantage..
For example
A trainer done in ASM can be around 50-70k size, 20-40k with an external packer.
A trainer done in TMK (same bitmaps,etc) will be around 200k+ compressed with its own packer.
And lets not forget TMK trainers usually cause AV scanners to go mad of trojan warnings when there isnt one lol
Ok lets get started....
1. MASM
Yep goto the site above and download MASM 8.2 and install it
Do please leave it to its default install folder for now, will be easier to use the skeleton code to do your trainer
So when thats done (it may take a while depending on your machine specs)
2. Skeleton Code
Download the skeleton trainer from my webspace, unfortunately for now Sheep's site has closed for a while :\ so ill host
in the mean time :) Im sure he wont mind..
Unpack the file to say c:\trainers\ or whatever you prefer.
3. Lets analyse...
Well lets start from the top, open up trainer.asm file in your skeleton folder...
; ********************************
; * PGC Trainer Code *
; ********************************
; * *
; * Code : [sheep] *
; * date : 08.26.01 *
; * language : asm *
; * *
; ********************************
;.GO.
;################################################# ###############################
.386
.model flat,stdcall
option casemap:none
Top off course is Sheep's little signature, anything you want to add to the coding to explain anything start with a ;
this will make sure when the coding is compiled it will ignore these as instructions and wont compile it ;)
.386 - Model version of your CPU, 386's are really old lol basically this means this can be run on a very early 386
processor and above you can offcourse set to 586 or 486 etc, but to make it more available to others just use 386.
.model flat - A program written in native 32 bit Windows format is created in what is called FLAT memory model which has a single
segment that contains both code and data. The programs must be run on a 386 or higher processor.
Differing from earlier 16 bit code that used combined segment and offset addressing with a 64k segment limit, FLAT
memory model works only in offsets and has a range of 4 gigabytes. This makes assembler easier to write and the code
is generally a lot faster.
All segment registers are automatically set to the same value with this memory model and this means that segment / offset
addressing must NOT be used in 32 bit programs that run in 32 bit Windows.
For programmers who have written code in DOS, a 32 bit Windows PE executable file is similar in some respects to a dos
COM file, they have a single segment that can contain both code and data and they both work directly in offsets, neither
use Segment / Offset addressing.
The defaults in flat-model programs are NEAR code addressing and NEAR data addressing within the range of 4 gigabytes.
The FS and GS segment registers are not normally used in application programs but are used in some instances by the
operating system. (Taken from masm32 help docs, as it was easier to explain lol)
stdcall - Calling Convention, this is best explained by searching for it on the net, if you want to :P
casemap:none - Case Sensitive Control, set to none, if set to ALL it makes all lower case characters upper case.
I.E. Best leave these settings as is ;)
Next
----
;.LIBS AND INCS.
;################################################# ###############################
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib\masm32\lib\user32.lib
includelib\masm32\lib\kernel32.lib
For a more detailed idea on what is happening here, check the masm32 help docs.
But basically your telling which API's your going to use in your program. If you dont include them
any API you use later will not be recognised, and will result in the coding not being compiled.
Next
----
The fun bit :P
;.DATA.
;################################################# ###############################
.data
DlgName db "MyDialog",0
AppName db "Pizza Trainer v1.10",0
bufferw db 65 dup (0)
infocap db "INFO",0
infomessage db "TITLE............: Doulber Escape From The 80's ",0ah
db "VERSION......: ?? ",0ah
db "TRAINER....: crayola ",0ah
db "CODE............: crayola ",0ah
db "QUOTE.........: 'LUV not WAR' ",0h
errorcap db "ERROR",0
errormessage db "COULD NOT OPEN PROCESS!!!",0ah
db " ",0ah
db "MAKE SURE TRAINER IS IN ",0ah
db "SAME DIRECTORY AS THE ",0ah
db "GAME. ",0h
detectcap db "ERROR",0
detectmessage db " ",0ah
db " GAME IS NOT LOADED!!!",0ah
db " ",0h
Gaddress1 dd 0040cdd3h
Gval1 db 090h,090h,090h,090h,090h,090h
Gnum1 db 6
Gaddress2 dd 0040d84fh
Gval2 db 090h,090h
Gnum2 db 2
Gaddress3 dd 0040900eh
Gval3 db 0c6h,083h,05eh,014h,001h,000h,000h,090h
Gnum3 db 8
Gaddress4 dd 0040cd10h
Gval4 db 0e9h,009h,001h,000h,000h,090h
Gnum4 db 6
Gaddress5 dd 00478020h
Gval5 db 080h,03dh,050h,080h,047h,000h,001h,00fh,085h,0d7h, 09eh,0f8h,0ffh,0c6h,005h,050h,080h,047h,000h,000h, 0e9h,038h,09eh,0f8h,0ffh
Gnum5 db 25
Gaddress5_2 dd 00401e6bh
Gval5_2 db 0e9h,0b0h,061h,007h,000h,090h
Gnum5_2 db 6
Gaddress5_3 dd 00478050h
Gval5_3 db 001h
Gnum5_3 db 1
g5_flag db 0
bytes_written dw 0
FileName db "game.exe",0
flag_loaded db 0
Flag_@error db 0
Hwnd dd 0
.data?
StartUpInfo STARTUPINFO <>
hProcess dd ?
hInstance HINSTANCE ?
CommandLine LPSTR ?
buffer db 512 dup(?)
buffer2 dd ?
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
IDM_GETTEXT equ 32000
IDM_CLEAR equ 32001
IDM_EXIT equ 32002
ID_TIMER1 equ 4000
This is the area where you declare any variables your going to use and any possible values included.
DlgName db "MyDialog",0 - the db part means it will allocate each character by byte, anything involving text will have
db used. dw = word (2 bytes) dd = dword (4 bytes) others can be checked in the help files.
This is just setting the Dialogue name of the trainer to "MyDialog". The 0 at the end, just
terminates the line, as in no more to show.
AppName db "Pizza Trainer v1.10",0 - This sets what it will show in Title Bar of the trainer.
bufferw db 65 dup (0) - Just setting a buffer size here, dont worry about this, leave as is.
Next parts is setting error messages, which is quite straight forward. The 0ah means new line (i.e. as if the return has been pressed),
again with 0h at the end to terminate the line. h is hex incase you forgot :P
Gaddress1 dd 0040cdd3h - Address at which to write data
Gval1 db 090h,090h,090h,090h,090h,090h - What data to write, in hex offcourse
Gnum1 db 6 - Size of data to be written (in decimal - dec for short)
This is where you place your own code injections or code patching, always start with your code cave first then the amended game code after.
Or else the game will crash since it cant find opcodes to use.
bytes_written dw 0
FileName db "game.exe",0
flag_loaded db 0
Flag_@error db 0
Hwnd dd 0
Just more variables we set up, one more important
FileName db "game.exe",0 - whats the games exe name?
The rest, except Hwnd, are byte values with the value of 0 assigned to them.
The next area are undefined values, which will be defined when the trainer is run. Again dont worry about this at the moment.
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
IDM_GETTEXT equ 32000
IDM_CLEAR equ 32001
IDM_EXIT equ 32002
ID_TIMER1 equ 4000
Here we are setting constant values, i.e. values that will never change at all. Whats EQU?
IDC_EDIT equ 3000
EQU evaluates the numeric value of 3000 and assigns the resulting constant value to IDC_EDIT.
EQU does not allow numeric equates to be redefined (i.e 3+4=7), you can however have 3+4 and it will
work out the value 7 for you.
If the value (3000) cannot be evaluated, EQU treats the value as text.
Basically we are setting, in this case, offset values for later.
Now onto the .code section
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, 100,NULL,addr DlgProc,NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
mov eax,hWnd
mov Hwnd,eax
invoke GetDlgItem, hWnd,200
invoke SetFocus,eax
invoke SetTimer,hWnd,ID_TIMER1,80,NULL
call @keyboardflush
.ELSEIF uMsg==WM_CLOSE
invoke ExitProcess,0
.ELSEIF uMsg==WM_TIMER
cmp wParam,ID_TIMER1
jnz @next_timer
invoke GetAsyncKeyState,"1"
cmp eax,0
jz @key2
cmp flag_loaded,1
jz @startf1
call error1
jmp @next_timer
@startf1:
;int 3
invoke WriteProcessMemory,hProcess,Gaddress1,addr Gval1,Gnum1,bytes_written
@key2:
invoke GetAsyncKeyState,"2"
cmp eax,0
jz @key3
cmp flag_loaded,1
jz @startf2
call error1
jmp @next_timer
@startf2:
invoke WriteProcessMemory,hProcess,Gaddress2,addr Gval2,Gnum2,bytes_written
@key3:
invoke GetAsyncKeyState,"3"
cmp eax,0
jz @key4
cmp flag_loaded,1
jz @startf3
call error1
jmp @next_timer
@startf3:
invoke WriteProcessMemory,hProcess,Gaddress3,addr Gval3,Gnum3,bytes_written
@key4:
invoke GetAsyncKeyState,"4"
cmp eax,0
jz @key5
cmp flag_loaded,1
jz @startf4
call error1
jmp @next_timer
@startf4:
invoke WriteProcessMemory,hProcess,Gaddress4,addr Gval4,Gnum4,bytes_written
@key5:
invoke GetAsyncKeyState,"5"
cmp eax,0
jz @next_timer
cmp flag_loaded,1
jz @startf5
call error1
jmp @next_timer
@startf5:
cmp g5_flag,0
jnz @set1
invoke WriteProcessMemory,hProcess,Gaddress5,addr Gval5,Gnum5,bytes_written
invoke WriteProcessMemory,hProcess,Gaddress5_2,addr Gval5_2,Gnum5_2,bytes_written
@set1:
invoke WriteProcessMemory,hProcess,Gaddress5_3,addr Gval5_3,Gnum5_3,bytes_written
mov g5_flag,1
@next_timer:
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.ELSE
mov edx,wParam
shr edx,16
.IF dx==BN_CLICKED
.IF ax==101
invoke CreateProcess, ADDR FileName, NULL,NULL,NULL,NULL,\
NORMAL_PRIORITY_CLASS,NULL,NULL,ADDR StartUpInfo,ADDR hProcess
cmp eax,0
jnz loaded_ok
invoke MessageBoxA,hWnd,ADDR errormessage,ADDR errorcap,64
jmp @errorexit
loaded_ok:
mov flag_loaded,1
@errorexit:
.ELSEIF ax==102
invoke MessageBoxA,hWnd,ADDR infomessage,ADDR infocap,64
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
error1 proc
cmp Flag_@error,0
jnz @end1
mov Flag_@error,1
invoke MessageBoxA,Hwnd,ADDR detectmessage,ADDR detectcap,64
mov Flag_@error,0
@end1:
ret
error1 endp
@keyboardflush proc
;invoke GetAsyncKeyState,VK_F1
;invoke GetAsyncKeyState,VK_F2
;invoke GetAsyncKeyState,VK_F3
;invoke GetAsyncKeyState,VK_F4
;invoke GetAsyncKeyState,VK_F5
;invoke GetAsyncKeyState,VK_F6
;invoke GetAsyncKeyState,VK_F7
;invoke GetAsyncKeyState,VK_F8
;invoke GetAsyncKeyState,VK_F9
invoke GetAsyncKeyState,"1"
invoke GetAsyncKeyState,"2"
invoke GetAsyncKeyState,"3"
invoke GetAsyncKeyState,"4"
invoke GetAsyncKeyState,"5"
;invoke GetAsyncKeyState,"6"
;invoke GetAsyncKeyState,"7"
;invoke GetAsyncKeyState,"8"
;invoke GetAsyncKeyState,"9"
;invoke GetAsyncKeyState,"0"
ret
@keyboardflush endp
end start
Quite long huh :P
Lets get to the more important part
.ELSEIF uMsg==WM_TIMER
cmp wParam,ID_TIMER1 - Timer run out?
jnz @next_timer - Goto next timer coding
invoke GetAsyncKeyState,"1" - Check the state of the key 1, if been pressed or not
cmp eax,0 - Was the key pressed?
jz @key2 - If not jump to @key2 section
cmp flag_loaded,1 - Has the game been loaded yet?
jz @startf1 - If yes jump to @startf1 section
call error1 - If not call error msg that game is not loaded
jmp @next_timer - Jump to @next_timer section
@startf1:
;int 3
invoke WriteProcessMemory,hProcess,Gaddress1,addr Gval1,Gnum1,bytes_written - Write values to address
Its pretty much the same for the rest.
If you had just 1 option, you could do this
invoke GetAsyncKeyState,"1"
cmp eax,0
jz @next_timer
....etc
Since there is no more keys, you would just goto the @next time section to loop the trainer again.
Next is this
.IF dx==BN_CLICKED - Was mouse button clicked?
.IF ax==101 - Was it on the button ID 101 (this is our run game)
invoke CreateProcess, ADDR FileName, NULL,NULL,NULL,NULL,\
NORMAL_PRIORITY_CLASS,NULL,NULL,ADDR StartUpInfo,ADDR hProcess - If so Load the game executable
cmp eax,0 - Load ok?
jnz loaded_ok - If so goto loaded_ok section, if not..
invoke MessageBoxA,hWnd,ADDR errormessage,ADDR errorcap,64 - show error msg window
jmp @errorexit - jmp to @errorexit...
loaded_ok:
mov flag_loaded,1 - Move the value 1 to flag_loaded variable (remember this when checking keys?)
@errorexit:
.ELSEIF ax==102 - Or was the button ID 102 (Info) pressed?
invoke MessageBoxA,hWnd,ADDR infomessage,ADDR infocap,64 - If so show our info window
.ELSEIF ax==IDC_EXIT - Have they pressed the OK button on either window?
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0 - If so close window.
.ENDIF
I know it looks difficult, but search the net for these API's and their functions
CreateProcess
MessageBoxA
SendMessage
GetAsyncKeyState
@keyboardflush proc
;invoke GetAsyncKeyState,VK_F1
;invoke GetAsyncKeyState,VK_F2
;invoke GetAsyncKeyState,VK_F3
;invoke GetAsyncKeyState,VK_F4
;invoke GetAsyncKeyState,VK_F5
;invoke GetAsyncKeyState,VK_F6
;invoke GetAsyncKeyState,VK_F7
;invoke GetAsyncKeyState,VK_F8
;invoke GetAsyncKeyState,VK_F9
invoke GetAsyncKeyState,"1"
invoke GetAsyncKeyState,"2"
invoke GetAsyncKeyState,"3"
invoke GetAsyncKeyState,"4"
invoke GetAsyncKeyState,"5"
;invoke GetAsyncKeyState,"6"
;invoke GetAsyncKeyState,"7"
;invoke GetAsyncKeyState,"8"
;invoke GetAsyncKeyState,"9"
;invoke GetAsyncKeyState,"0"
ret
This section just sets out what keys are used, and flushes their values. Just change to whatever your using for your keys in the trainer,
i.e. change "1" to "A" to use A, etc. If you want to use SHIFT+1, check the net for how to set this, likewise for CTRL and ALT :)
Ok, I know it seems WOOOOAHHHHHHH but im tired and im trying to make it easy :P
Just change the necessary areas, like AppName, The error messages, the Info messages, The address+values of your code injection/patching
Also if using different keys, make sure in each section to write the data that you tell it which key you pressed.
for example
invoke GetAsyncKeyState,"A"
cmp eax,0
....etc
Once your done save your .asm file as something like "gamename.asm" gamename being your game your training.
Now.... Load up Rsrc.rc file into notepad... you will get this...
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
100 DIALOG DISCARDABLE 0, 0, 236, 154
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Trainer v1.10"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "Run Game",101,10,93,50,14
DEFPUSHBUTTON "About!",102,178,93,50,14
CONTROL 113,IDC_STATIC,"Static",SS_BITMAP | WS_BORDER,4,7,229,43
GROUPBOX "Trainer Options :",IDC_STATIC,65,60,108,77
LTEXT "'1' - Infinite Lives",IDC_STATIC,91,77,53,8
LTEXT "'2' - Stop Timer",IDC_STATIC,91,87,48,8
LTEXT "'3' - Open Exit",IDC_STATIC,91,97,44,8
LTEXT "'4' - Invulnerability",IDC_STATIC,91,107,56,8
LTEXT "'5' - Skip Level",IDC_STATIC,91,117,47,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
pizza BITMAP DISCARDABLE "pizza.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "Winupd.ico"
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
Ive only shown the more important part for you...
100 DIALOG DISCARDABLE 0, 0, 236, 154 - ID 100, Dialog window, its discardable (i.e. can close :P), start at x,y coordinates 0,0 with
length 236 and Depth 154 pixels. Remember the depth is downwards unlike maths when the Y value
is upwards with positive values.
Dont worry about the Style section, unless you dont want a caption bar (title) then you can remove WS_CAPTION
CAPTION "Trainer v1.10" - change this to whatever you want the title to say
FONT 8, "MS Sans Serif" - Set font type and size, make sure you select a font everyone has
BEGIN
DEFPUSHBUTTON "Run Game",101,10,93,50,14 - Set a button with ID 101 (remember in asm file?) with co-ords 10,93 and length 50 and depth 14
DEFPUSHBUTTON "About!",102,178,93,50,14 - Set a button with ID 102, co-ords 178,93 and length 50 and depth 14
CONTROL 113,IDC_STATIC,"Static",SS_BITMAP | WS_BORDER,4,7,229,43 - Set the static area for a bitmap picture to be shown, and set border
GROUPBOX "Trainer Options :",IDC_STATIC,65,60,108,77 - Make a group box with title Trainer Options, at co-ords 65,60 etc etc
LTEXT "'1' - Infinite Lives",IDC_STATIC,91,77,53,8 |
LTEXT "'2' - Stop Timer",IDC_STATIC,91,87,48,8 |
LTEXT "'3' - Open Exit",IDC_STATIC,91,97,44,8 |- Set text to be shown at co-ords and length,depth
LTEXT "'4' - Invulnerability",IDC_STATIC,91,107,56,8 |
LTEXT "'5' - Skip Level",IDC_STATIC,91,117,47,8 |
END
Before I forget the CONTROL has an ID 113... These are important so the program can distinquish what is being used and refering to.
pizza BITMAP DISCARDABLE "pizza.bmp" - set the bitmap picture to be shown, best in 256 colors to keep size of trainer down.
Also take note of the size you set above, 229 length and 43 depth, make sure bitmap
file has those dimensions
IDI_ICON1 ICON DISCARDABLE "Winupd.ico" - Set the Icon of the trainer exe, make sure the icon is 256 colors again. There is lots
of icon editors on the net, that can convert from 16bit to 256.
Once you change what you need to change, save as Rsrc.rc (NOT anything else)...
Ok if everything is done correctly, you can run MAKEIT.BAT....
For best results, goto Start > Run > cmd {press enter} and in the dos window, type
cd/trainer/ (or whatever your folder name was)
then type
MAKEIT.BAT
This will help to show any errors without the window dissapearing.
If none, your trainer is complete, run it to test it :D
If it works and keys work etc...
While still in the dos window type
UPX -9 trainer.exe (or whatever your exe is called)
This will pack your file and encrypt it, to make it smaller and to stop noob thiefs stealing your work by changing text with a hex editor
Hope you understood all that
BYE
Here it comes
Building an ASM Trainer from a Skeleton Build
=============================================
Needed-
1. MASM (http://www.masm32.com/)
2. Trainer Skeleton Build (http://www.vwaskar.pwp.blueyonder.co.uk/asm4FF/trainerasm.rar - Thanks Sheep for releasing this ;) )
3. Helps to know basic ASM at least :P
Ok why an ASM trainer and not using TMK or other easy to build trainer programs, well ASM has a huge size advantage..
For example
A trainer done in ASM can be around 50-70k size, 20-40k with an external packer.
A trainer done in TMK (same bitmaps,etc) will be around 200k+ compressed with its own packer.
And lets not forget TMK trainers usually cause AV scanners to go mad of trojan warnings when there isnt one lol
Ok lets get started....
1. MASM
Yep goto the site above and download MASM 8.2 and install it
Do please leave it to its default install folder for now, will be easier to use the skeleton code to do your trainer
So when thats done (it may take a while depending on your machine specs)
2. Skeleton Code
Download the skeleton trainer from my webspace, unfortunately for now Sheep's site has closed for a while :\ so ill host
in the mean time :) Im sure he wont mind..
Unpack the file to say c:\trainers\ or whatever you prefer.
3. Lets analyse...
Well lets start from the top, open up trainer.asm file in your skeleton folder...
; ********************************
; * PGC Trainer Code *
; ********************************
; * *
; * Code : [sheep] *
; * date : 08.26.01 *
; * language : asm *
; * *
; ********************************
;.GO.
;################################################# ###############################
.386
.model flat,stdcall
option casemap:none
Top off course is Sheep's little signature, anything you want to add to the coding to explain anything start with a ;
this will make sure when the coding is compiled it will ignore these as instructions and wont compile it ;)
.386 - Model version of your CPU, 386's are really old lol basically this means this can be run on a very early 386
processor and above you can offcourse set to 586 or 486 etc, but to make it more available to others just use 386.
.model flat - A program written in native 32 bit Windows format is created in what is called FLAT memory model which has a single
segment that contains both code and data. The programs must be run on a 386 or higher processor.
Differing from earlier 16 bit code that used combined segment and offset addressing with a 64k segment limit, FLAT
memory model works only in offsets and has a range of 4 gigabytes. This makes assembler easier to write and the code
is generally a lot faster.
All segment registers are automatically set to the same value with this memory model and this means that segment / offset
addressing must NOT be used in 32 bit programs that run in 32 bit Windows.
For programmers who have written code in DOS, a 32 bit Windows PE executable file is similar in some respects to a dos
COM file, they have a single segment that can contain both code and data and they both work directly in offsets, neither
use Segment / Offset addressing.
The defaults in flat-model programs are NEAR code addressing and NEAR data addressing within the range of 4 gigabytes.
The FS and GS segment registers are not normally used in application programs but are used in some instances by the
operating system. (Taken from masm32 help docs, as it was easier to explain lol)
stdcall - Calling Convention, this is best explained by searching for it on the net, if you want to :P
casemap:none - Case Sensitive Control, set to none, if set to ALL it makes all lower case characters upper case.
I.E. Best leave these settings as is ;)
Next
----
;.LIBS AND INCS.
;################################################# ###############################
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib\masm32\lib\user32.lib
includelib\masm32\lib\kernel32.lib
For a more detailed idea on what is happening here, check the masm32 help docs.
But basically your telling which API's your going to use in your program. If you dont include them
any API you use later will not be recognised, and will result in the coding not being compiled.
Next
----
The fun bit :P
;.DATA.
;################################################# ###############################
.data
DlgName db "MyDialog",0
AppName db "Pizza Trainer v1.10",0
bufferw db 65 dup (0)
infocap db "INFO",0
infomessage db "TITLE............: Doulber Escape From The 80's ",0ah
db "VERSION......: ?? ",0ah
db "TRAINER....: crayola ",0ah
db "CODE............: crayola ",0ah
db "QUOTE.........: 'LUV not WAR' ",0h
errorcap db "ERROR",0
errormessage db "COULD NOT OPEN PROCESS!!!",0ah
db " ",0ah
db "MAKE SURE TRAINER IS IN ",0ah
db "SAME DIRECTORY AS THE ",0ah
db "GAME. ",0h
detectcap db "ERROR",0
detectmessage db " ",0ah
db " GAME IS NOT LOADED!!!",0ah
db " ",0h
Gaddress1 dd 0040cdd3h
Gval1 db 090h,090h,090h,090h,090h,090h
Gnum1 db 6
Gaddress2 dd 0040d84fh
Gval2 db 090h,090h
Gnum2 db 2
Gaddress3 dd 0040900eh
Gval3 db 0c6h,083h,05eh,014h,001h,000h,000h,090h
Gnum3 db 8
Gaddress4 dd 0040cd10h
Gval4 db 0e9h,009h,001h,000h,000h,090h
Gnum4 db 6
Gaddress5 dd 00478020h
Gval5 db 080h,03dh,050h,080h,047h,000h,001h,00fh,085h,0d7h, 09eh,0f8h,0ffh,0c6h,005h,050h,080h,047h,000h,000h, 0e9h,038h,09eh,0f8h,0ffh
Gnum5 db 25
Gaddress5_2 dd 00401e6bh
Gval5_2 db 0e9h,0b0h,061h,007h,000h,090h
Gnum5_2 db 6
Gaddress5_3 dd 00478050h
Gval5_3 db 001h
Gnum5_3 db 1
g5_flag db 0
bytes_written dw 0
FileName db "game.exe",0
flag_loaded db 0
Flag_@error db 0
Hwnd dd 0
.data?
StartUpInfo STARTUPINFO <>
hProcess dd ?
hInstance HINSTANCE ?
CommandLine LPSTR ?
buffer db 512 dup(?)
buffer2 dd ?
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
IDM_GETTEXT equ 32000
IDM_CLEAR equ 32001
IDM_EXIT equ 32002
ID_TIMER1 equ 4000
This is the area where you declare any variables your going to use and any possible values included.
DlgName db "MyDialog",0 - the db part means it will allocate each character by byte, anything involving text will have
db used. dw = word (2 bytes) dd = dword (4 bytes) others can be checked in the help files.
This is just setting the Dialogue name of the trainer to "MyDialog". The 0 at the end, just
terminates the line, as in no more to show.
AppName db "Pizza Trainer v1.10",0 - This sets what it will show in Title Bar of the trainer.
bufferw db 65 dup (0) - Just setting a buffer size here, dont worry about this, leave as is.
Next parts is setting error messages, which is quite straight forward. The 0ah means new line (i.e. as if the return has been pressed),
again with 0h at the end to terminate the line. h is hex incase you forgot :P
Gaddress1 dd 0040cdd3h - Address at which to write data
Gval1 db 090h,090h,090h,090h,090h,090h - What data to write, in hex offcourse
Gnum1 db 6 - Size of data to be written (in decimal - dec for short)
This is where you place your own code injections or code patching, always start with your code cave first then the amended game code after.
Or else the game will crash since it cant find opcodes to use.
bytes_written dw 0
FileName db "game.exe",0
flag_loaded db 0
Flag_@error db 0
Hwnd dd 0
Just more variables we set up, one more important
FileName db "game.exe",0 - whats the games exe name?
The rest, except Hwnd, are byte values with the value of 0 assigned to them.
The next area are undefined values, which will be defined when the trainer is run. Again dont worry about this at the moment.
.const
IDC_EDIT equ 3000
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
IDM_GETTEXT equ 32000
IDM_CLEAR equ 32001
IDM_EXIT equ 32002
ID_TIMER1 equ 4000
Here we are setting constant values, i.e. values that will never change at all. Whats EQU?
IDC_EDIT equ 3000
EQU evaluates the numeric value of 3000 and assigns the resulting constant value to IDC_EDIT.
EQU does not allow numeric equates to be redefined (i.e 3+4=7), you can however have 3+4 and it will
work out the value 7 for you.
If the value (3000) cannot be evaluated, EQU treats the value as text.
Basically we are setting, in this case, offset values for later.
Now onto the .code section
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, 100,NULL,addr DlgProc,NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
mov eax,hWnd
mov Hwnd,eax
invoke GetDlgItem, hWnd,200
invoke SetFocus,eax
invoke SetTimer,hWnd,ID_TIMER1,80,NULL
call @keyboardflush
.ELSEIF uMsg==WM_CLOSE
invoke ExitProcess,0
.ELSEIF uMsg==WM_TIMER
cmp wParam,ID_TIMER1
jnz @next_timer
invoke GetAsyncKeyState,"1"
cmp eax,0
jz @key2
cmp flag_loaded,1
jz @startf1
call error1
jmp @next_timer
@startf1:
;int 3
invoke WriteProcessMemory,hProcess,Gaddress1,addr Gval1,Gnum1,bytes_written
@key2:
invoke GetAsyncKeyState,"2"
cmp eax,0
jz @key3
cmp flag_loaded,1
jz @startf2
call error1
jmp @next_timer
@startf2:
invoke WriteProcessMemory,hProcess,Gaddress2,addr Gval2,Gnum2,bytes_written
@key3:
invoke GetAsyncKeyState,"3"
cmp eax,0
jz @key4
cmp flag_loaded,1
jz @startf3
call error1
jmp @next_timer
@startf3:
invoke WriteProcessMemory,hProcess,Gaddress3,addr Gval3,Gnum3,bytes_written
@key4:
invoke GetAsyncKeyState,"4"
cmp eax,0
jz @key5
cmp flag_loaded,1
jz @startf4
call error1
jmp @next_timer
@startf4:
invoke WriteProcessMemory,hProcess,Gaddress4,addr Gval4,Gnum4,bytes_written
@key5:
invoke GetAsyncKeyState,"5"
cmp eax,0
jz @next_timer
cmp flag_loaded,1
jz @startf5
call error1
jmp @next_timer
@startf5:
cmp g5_flag,0
jnz @set1
invoke WriteProcessMemory,hProcess,Gaddress5,addr Gval5,Gnum5,bytes_written
invoke WriteProcessMemory,hProcess,Gaddress5_2,addr Gval5_2,Gnum5_2,bytes_written
@set1:
invoke WriteProcessMemory,hProcess,Gaddress5_3,addr Gval5_3,Gnum5_3,bytes_written
mov g5_flag,1
@next_timer:
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.ELSE
mov edx,wParam
shr edx,16
.IF dx==BN_CLICKED
.IF ax==101
invoke CreateProcess, ADDR FileName, NULL,NULL,NULL,NULL,\
NORMAL_PRIORITY_CLASS,NULL,NULL,ADDR StartUpInfo,ADDR hProcess
cmp eax,0
jnz loaded_ok
invoke MessageBoxA,hWnd,ADDR errormessage,ADDR errorcap,64
jmp @errorexit
loaded_ok:
mov flag_loaded,1
@errorexit:
.ELSEIF ax==102
invoke MessageBoxA,hWnd,ADDR infomessage,ADDR infocap,64
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
error1 proc
cmp Flag_@error,0
jnz @end1
mov Flag_@error,1
invoke MessageBoxA,Hwnd,ADDR detectmessage,ADDR detectcap,64
mov Flag_@error,0
@end1:
ret
error1 endp
@keyboardflush proc
;invoke GetAsyncKeyState,VK_F1
;invoke GetAsyncKeyState,VK_F2
;invoke GetAsyncKeyState,VK_F3
;invoke GetAsyncKeyState,VK_F4
;invoke GetAsyncKeyState,VK_F5
;invoke GetAsyncKeyState,VK_F6
;invoke GetAsyncKeyState,VK_F7
;invoke GetAsyncKeyState,VK_F8
;invoke GetAsyncKeyState,VK_F9
invoke GetAsyncKeyState,"1"
invoke GetAsyncKeyState,"2"
invoke GetAsyncKeyState,"3"
invoke GetAsyncKeyState,"4"
invoke GetAsyncKeyState,"5"
;invoke GetAsyncKeyState,"6"
;invoke GetAsyncKeyState,"7"
;invoke GetAsyncKeyState,"8"
;invoke GetAsyncKeyState,"9"
;invoke GetAsyncKeyState,"0"
ret
@keyboardflush endp
end start
Quite long huh :P
Lets get to the more important part
.ELSEIF uMsg==WM_TIMER
cmp wParam,ID_TIMER1 - Timer run out?
jnz @next_timer - Goto next timer coding
invoke GetAsyncKeyState,"1" - Check the state of the key 1, if been pressed or not
cmp eax,0 - Was the key pressed?
jz @key2 - If not jump to @key2 section
cmp flag_loaded,1 - Has the game been loaded yet?
jz @startf1 - If yes jump to @startf1 section
call error1 - If not call error msg that game is not loaded
jmp @next_timer - Jump to @next_timer section
@startf1:
;int 3
invoke WriteProcessMemory,hProcess,Gaddress1,addr Gval1,Gnum1,bytes_written - Write values to address
Its pretty much the same for the rest.
If you had just 1 option, you could do this
invoke GetAsyncKeyState,"1"
cmp eax,0
jz @next_timer
....etc
Since there is no more keys, you would just goto the @next time section to loop the trainer again.
Next is this
.IF dx==BN_CLICKED - Was mouse button clicked?
.IF ax==101 - Was it on the button ID 101 (this is our run game)
invoke CreateProcess, ADDR FileName, NULL,NULL,NULL,NULL,\
NORMAL_PRIORITY_CLASS,NULL,NULL,ADDR StartUpInfo,ADDR hProcess - If so Load the game executable
cmp eax,0 - Load ok?
jnz loaded_ok - If so goto loaded_ok section, if not..
invoke MessageBoxA,hWnd,ADDR errormessage,ADDR errorcap,64 - show error msg window
jmp @errorexit - jmp to @errorexit...
loaded_ok:
mov flag_loaded,1 - Move the value 1 to flag_loaded variable (remember this when checking keys?)
@errorexit:
.ELSEIF ax==102 - Or was the button ID 102 (Info) pressed?
invoke MessageBoxA,hWnd,ADDR infomessage,ADDR infocap,64 - If so show our info window
.ELSEIF ax==IDC_EXIT - Have they pressed the OK button on either window?
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0 - If so close window.
.ENDIF
I know it looks difficult, but search the net for these API's and their functions
CreateProcess
MessageBoxA
SendMessage
GetAsyncKeyState
@keyboardflush proc
;invoke GetAsyncKeyState,VK_F1
;invoke GetAsyncKeyState,VK_F2
;invoke GetAsyncKeyState,VK_F3
;invoke GetAsyncKeyState,VK_F4
;invoke GetAsyncKeyState,VK_F5
;invoke GetAsyncKeyState,VK_F6
;invoke GetAsyncKeyState,VK_F7
;invoke GetAsyncKeyState,VK_F8
;invoke GetAsyncKeyState,VK_F9
invoke GetAsyncKeyState,"1"
invoke GetAsyncKeyState,"2"
invoke GetAsyncKeyState,"3"
invoke GetAsyncKeyState,"4"
invoke GetAsyncKeyState,"5"
;invoke GetAsyncKeyState,"6"
;invoke GetAsyncKeyState,"7"
;invoke GetAsyncKeyState,"8"
;invoke GetAsyncKeyState,"9"
;invoke GetAsyncKeyState,"0"
ret
This section just sets out what keys are used, and flushes their values. Just change to whatever your using for your keys in the trainer,
i.e. change "1" to "A" to use A, etc. If you want to use SHIFT+1, check the net for how to set this, likewise for CTRL and ALT :)
Ok, I know it seems WOOOOAHHHHHHH but im tired and im trying to make it easy :P
Just change the necessary areas, like AppName, The error messages, the Info messages, The address+values of your code injection/patching
Also if using different keys, make sure in each section to write the data that you tell it which key you pressed.
for example
invoke GetAsyncKeyState,"A"
cmp eax,0
....etc
Once your done save your .asm file as something like "gamename.asm" gamename being your game your training.
Now.... Load up Rsrc.rc file into notepad... you will get this...
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
100 DIALOG DISCARDABLE 0, 0, 236, 154
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Trainer v1.10"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "Run Game",101,10,93,50,14
DEFPUSHBUTTON "About!",102,178,93,50,14
CONTROL 113,IDC_STATIC,"Static",SS_BITMAP | WS_BORDER,4,7,229,43
GROUPBOX "Trainer Options :",IDC_STATIC,65,60,108,77
LTEXT "'1' - Infinite Lives",IDC_STATIC,91,77,53,8
LTEXT "'2' - Stop Timer",IDC_STATIC,91,87,48,8
LTEXT "'3' - Open Exit",IDC_STATIC,91,97,44,8
LTEXT "'4' - Invulnerability",IDC_STATIC,91,107,56,8
LTEXT "'5' - Skip Level",IDC_STATIC,91,117,47,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
pizza BITMAP DISCARDABLE "pizza.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "Winupd.ico"
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
Ive only shown the more important part for you...
100 DIALOG DISCARDABLE 0, 0, 236, 154 - ID 100, Dialog window, its discardable (i.e. can close :P), start at x,y coordinates 0,0 with
length 236 and Depth 154 pixels. Remember the depth is downwards unlike maths when the Y value
is upwards with positive values.
Dont worry about the Style section, unless you dont want a caption bar (title) then you can remove WS_CAPTION
CAPTION "Trainer v1.10" - change this to whatever you want the title to say
FONT 8, "MS Sans Serif" - Set font type and size, make sure you select a font everyone has
BEGIN
DEFPUSHBUTTON "Run Game",101,10,93,50,14 - Set a button with ID 101 (remember in asm file?) with co-ords 10,93 and length 50 and depth 14
DEFPUSHBUTTON "About!",102,178,93,50,14 - Set a button with ID 102, co-ords 178,93 and length 50 and depth 14
CONTROL 113,IDC_STATIC,"Static",SS_BITMAP | WS_BORDER,4,7,229,43 - Set the static area for a bitmap picture to be shown, and set border
GROUPBOX "Trainer Options :",IDC_STATIC,65,60,108,77 - Make a group box with title Trainer Options, at co-ords 65,60 etc etc
LTEXT "'1' - Infinite Lives",IDC_STATIC,91,77,53,8 |
LTEXT "'2' - Stop Timer",IDC_STATIC,91,87,48,8 |
LTEXT "'3' - Open Exit",IDC_STATIC,91,97,44,8 |- Set text to be shown at co-ords and length,depth
LTEXT "'4' - Invulnerability",IDC_STATIC,91,107,56,8 |
LTEXT "'5' - Skip Level",IDC_STATIC,91,117,47,8 |
END
Before I forget the CONTROL has an ID 113... These are important so the program can distinquish what is being used and refering to.
pizza BITMAP DISCARDABLE "pizza.bmp" - set the bitmap picture to be shown, best in 256 colors to keep size of trainer down.
Also take note of the size you set above, 229 length and 43 depth, make sure bitmap
file has those dimensions
IDI_ICON1 ICON DISCARDABLE "Winupd.ico" - Set the Icon of the trainer exe, make sure the icon is 256 colors again. There is lots
of icon editors on the net, that can convert from 16bit to 256.
Once you change what you need to change, save as Rsrc.rc (NOT anything else)...
Ok if everything is done correctly, you can run MAKEIT.BAT....
For best results, goto Start > Run > cmd {press enter} and in the dos window, type
cd/trainer/ (or whatever your folder name was)
then type
MAKEIT.BAT
This will help to show any errors without the window dissapearing.
If none, your trainer is complete, run it to test it :D
If it works and keys work etc...
While still in the dos window type
UPX -9 trainer.exe (or whatever your exe is called)
This will pack your file and encrypt it, to make it smaller and to stop noob thiefs stealing your work by changing text with a hex editor
Hope you understood all that
BYE