Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[Tut] Making Minesweeper its own trainer

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Ksbunker
Advanced Cheater
Reputation: 0

Joined: 18 Oct 2006
Posts: 88

PostPosted: Fri Sep 21, 2007 3:18 am    Post subject: [Tut] Making Minesweeper its own trainer Reply with quote

Premise behind how we patch minesweeper to become its own trainer;
- Hardcode required strings in the .code section in your code cave
- Modify OEP to direct the new EP (Entry Point) located at the start on our codecave. (After the strings of course... otherwise it will stall upon executing having mistaken the for string array for actual instructions)
- Write the code responsible for creating a new thread (if required, use relevant API to load additional functions).
- Write a jump instruction directing program flow back to the OEP (Original EP).
- Write the code responsible for the actual thread (Make sure the third parameter of CreateThread that points to the procedure/routine).

Now that was the theory, here's the practical code.

Code:
01004B00: "CreateThread",0
01004B0D: "Thread created s"
01004B1D: "uccessfully",0
01004B29: "Loaded...",0
01004B33: "F5 was pressed.."
01004B43: ".",0
01004B45: 00
01004B46: PUSH ksbunker.010045E4        ; FileName = "KERNEL32.dll"<--NEW EP
01004B4B: CALL kernel32.LoadLibraryA    ; LoadLibraryA
01004B50: PUSH ksbunker.01004B00        ; ProcNameOrOrdinal = "CreateThread"
01004B55: PUSH EAX                      ; hModule
01004B56: CALL kernel32.GetProcAddress  ; GetProcAddress
01004B5B: PUSH 0                        ; /
01004B5D: PUSH 0                        ; |
01004B5F: PUSH 0                        ; |
01004B61: PUSH ksbunker.01004B85        ; Thread Address
01004B66: PUSH 0                        ; |
01004B68: PUSH 0                        ; |
01004B6A: CALL EAX                      ; \CreateThread
01004B6C: PUSH 0                        ; Style = MB_OK|MB_APPLMODAL
01004B6E: PUSH ksbunker.01004B29        ; Title = "Loaded..."
01004B73: PUSH ksbunker.01004B0D        ; Text = "Thread created successfully"
01004B78: PUSH 0                        ; hOwner = NULL
01004B7A: CALL USER32.MessageBoxA       ; MessageBoxA
01004B7F: JMP ksbunker.01003E21         ; <-----------------JMP BACK TO OEP
01004B84: NOP                           ;
01004B85: PUSH 0A                       ; /Timeout = 10. ms <--Start of Thread--\
01004B87: CALL kernel32.Sleep           ; \Sleep                                |
01004B8C: PUSH 74                       ; /Key = VK_F5                          |
01004B8E: CALL USER32.GetAsyncKeyState  ; \GetAsyncKeyState                     |
01004B93: CMP EAX,0                     ; ...Error?                             |
01004B96: JE SHORT ksbunker.01004B85    ; ...If yes, jump to start of thread----/
01004B98: MOV EAX,ksbunker.0100569F     ; Move ENDOF mineboard address in EAX   |
01004B9D: /CMP EAX,ksbunker.01005340    ; ...is eax, 01005340? <----------------|---\
01004BA2: |JE SHORT ksbunker.01004B85   ; ...if yes, jump to start of thread----/   |
01004BA4: |CMP BYTE PTR DS:[EAX],8F     ; ...current byte in eax 8F? (mine)     |
01004BA7: |JNZ SHORT ksbunker.01004BAC  ; ...if not, dec counter, cont. loop----\   |
01004BA9: |MOV BYTE PTR DS:[EAX],41     ; ...if YES! Move 41 (no mine) into eax |   |
01004BAC: |DEC EAX                      ; dec eax (eax=current address) <-------/   |
01004BAD: \JMP SHORT ksbunker.01004B9D  ; jump to start of loop --------------------/


You will notice that LoadLibrary and GetProcess were used to dynamically load CreateThread(), but then I didn't dynamically load MessageBox(), Sleep() or GetAsyncKeyState(). I choose to get their function address from user32.dll and call the address of the function directly. IDEALLY, if you were going to distribute this file afterwards, you would dynamically load all of the API you create (i.e. if the API is not loaded via the IAT). Using the current approach, should I dynamically load, createthread, that will work on most/all computers, however come the sleep, messagebox and getasynckeystate functions, the code may fail on these, because the address of the functions varies depending on service pack, os, if you had modified kernel32.dll, etc...

The other thing to now is that in the memory of minesweeper, the board begins at address 1005340 and ends at 1005694 (Maximum size board). Typically, all these bytes are not required, because board size varies from easy, moderate and hard. However, I have harded the max size in this example, just incase I choose to make a custom board, it will work there too.

Regarding the loop, it cycles through each byte between the end of the board and start and searches for the mine byte, if it is found, it is replaced with a non-mine byte. It the current address is the starting address, it will exit the loop and jump back to the start of the thread.

Now. This is all well and good. But how does one change the Entry Point to point to your new code instead of the original EP. OK! No need to download any external programs.

Presuming you have made you codecave and all the code works fine, its time to direct the Entry Point to your NEW EP. Assuming your process is loaded;

View > Memory (Alt+M) >

A window will appear displaying the memory attributes and addresses of all currently running processes and services. Using the Address column as a guide, locate your process in memory (typically at 00400000), or in the case of the current example, its at 01000000, you will see;

Code:
Address  Size  Section Contains
01000000  1000         PE Header
01001000  4000 .text   Code, Imports
01005000  1000 .data   Memory Data
01006000 1A000 .rsrc   Resources


Double Click the 'PE Header' Line. Scroll down untill you see the line labelled 'AddressOfEntryPoint = 3E21' [The original EntryPoint, in RVA that is 01003E21. Using the same logic to get the offset to our NEW EP, do;

Address of New EP = 01004B46
ImageBase = 01000000

EP-ImageBase = 4B46, modify the bytes of the 'AddressOfEntryPoint = 4B46', SAVE, and ViOLA!!!

Comments, Critism, Suggestions most welcome!
Back to top
View user's profile Send private message
Pseudo Xero
I post too much
Reputation: 0

Joined: 16 Feb 2007
Posts: 2607

PostPosted: Fri Sep 21, 2007 3:31 am    Post subject: Reply with quote

Nice tutorial.
_________________
haxory' wrote:
can't VB do anything??
windows is programmed using VB right? correct me if im wrong.

so all things in windows you have like the start menu is a windows form too.
Back to top
View user's profile Send private message
TheSaint
Advanced Cheater
Reputation: 0

Joined: 25 Sep 2007
Posts: 75
Location: Behind You

PostPosted: Tue Sep 25, 2007 11:15 am    Post subject: Reply with quote

Hehe great tutorial but tbh Minesweeper sux i get really bored of it even in half a sec, i dnt even click on it Razz
_________________
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites