by: toenailed
NOTE: If you didn't made the code, it is still a good idea to give credit to code searcher/hacker sometimes finding a one line code is more difficult than making a trainer.
Here's an Example, for this tutorial I Use the Following
|
Now here's how it looks like when it was translated as ASM
|
PS. Don't Compile the ASM yet
Here's where all the Fun Start's, Finding where to Hook and store the ASM Routine can be relatively easy to annoyingly difficult. Different Hacker (or even in different game) uses different approach/method. For this tutorial we will use the easiest method.
In this Tutorial with our example we will look for where the button routine occur, that's where we hook our ASM Routine
And we will store our ASM Routine on 0x2000010 in RAM, in most ROM it is located in @0x0004010.
NOTE: This definitely is not the greatest idea since it might cause a culprit if you use dipstar along with this trainer and some flashcart stores some important data on those location, if you able to find a better address/offset you should use that instead.
A. Locating the Button Routine
A-1. First Makes a RAM Dump
- First Run the ROM in Emulator, make sure that the game is fully loaded.
- Run Emuhaste or hasteDS
- Press [Snap DeSmuME/iDeaS/NeeDS/no$gba] for hasteDS or [Snap Process for Emuhaste], make sure it doesn't give an error
- Press [DUMP]/[File DUMP] then save the dump, name it with your own choice
A-2. Locating the Button Routine here is 3 different method, you can use any of the following
A-2a. METHOD 1: Using ndsdis2.exe
- Open the command prompt (Start => Run= > cmd)
- Goto directory where the ndsdis2.exe is located
- Type "ndsdis2 -NH9 0 [filename of dump] > dump.txt" (without quotes and close/open bracket)
- Open dump.txt in a text editor.
- Search for 0x04000130
- It might give more than one result but look for where there are occurance of "E12FFF1E bx r14".
- The offset location of "E12FFF1E bx r14" will be hooking address
- Since it stored in RAM we should add 0x2000000 so our final hooking address will be 0x020E7EB8
|
A-2b. METHOD 2: Using iDeaS freeware version and Hex Editor
- Open the dump in Hex Editor
- The Search for 30 01 00 04 (0x04000130 little endian), list out all possible offset result (add 0x02000000 to all offset result)
- Open the ROM in iDeaS, make the game load enough till you see the "Press Touch/Start" or something
- Then Open the Debugger or press Alt+F2
- On Debugger window set the following EXTERN WRAM, Mode: Arm 9 and CPU: ARM (in this tutorial we will use ARM but some game store the button routine in THUMB)
- Then on the Text Box, input each offset then Press GO
- Locate which contains "bx lr".
- Scroll farther upward till you find something like "ldr r1, 0x04000130" followed by something like "ldr r0,0x2FFF" , if not look for other offset. (r1 and r0 can be any register but 0x04000130 and should be 0x2FFF load in register)
If confirmed that it was the button routine we will use the offset of bx lr which is in this example 0x020E7EB8
A-2c. METHOD 3: Using a Commercial Emulator with breakpoint debugger, like No$GBA Debbuger Edition and iDeaS Professional Edition
- Open the ROM in emulator, nope you don't need a dump here
- Set a bpr to 0x04000130
- it might break after a ldr r1, 0x04000130, in the example game it breaks in "ldr r0,0x2FFF"
- Scroll farther downward till you find the first "bx lr" or "bx r14", its location will be our Hooking address which in this game located in 0x020E7EB8
B. Check if the hooking address/offset is compressed
After locating the hooking address/offset we have to make sure that the offset is not compressed in ROM. Anyway the Method is simple just locate if the routine and the value in 0x020E7EB8 can be found in ROM. You have to make sure that it really occurs, If it is then you can skip the next steps and go directly in Preparing the ASM Custom Routine , If not then it requires an additional debugging.
C. Make an ASM Routine that will Patch the Hooking Address
This can be very difficult and requires a big patience, in this tutorial we will use iDeaS freeware version (obviously commercial version of the emulator is still powerful)
|
|
Using the Steps above we can go on debugging,
METHOD 1: Normally in Commercial Debugger the method is very simple
- Reset the game but make sure it was paused after resetting
- Set a bpw/breakpoint write in 0x020E7EB8
- Then Debugger will break somewhere in "0x02000A14",
- Now Study the bx lr or bx r14 below and you can choose anything, I choose 0x02000B44 (Choose which is not far where the debugger break)
METHOD 2: if you are using a Freeware version, the method is very complicated.
- First Open an Emulator with debugger,
- Make sure that the debugger window is opened
- Then load the ROM in emulator and press Play in Emulator Window but not in debugger window
- Open Emuhaste or hasteDS then press Snap Process
- Goto 0x020E7EA0, or any address as long as its a head in our hooking address
- Make sure that Auto Refresh function in emuhaste/hasteds
- Then use the [Trace Into] [F8] function in debugger window and trace
- During tracing, Watch on emuhaste/hasteds till you find the value of 0x020E7EB8 becomes 1E FF 2F E1
- In this game it will write in 0x02000A10.
- Now tracing downward you will see lots of "bx lr" you can choose one but I prefer 0x02000B44 since decompressing ends there
- Now to make sure that it is safe to use it, reset the game again
- Then press the play button in Emulator window but not in debugger window
- Press [F8] once
- Go to 0x02000B44 then click the said address in assembly window then use the [Run to Cursor] [F6] function on debugger window
- The Debugger will break there, then look again in emuhaste/hasteds and go to 0x020E7EB8 see if the value is 1E FF 2F E1
16. The last step would be is to check if 0x02000B44 is not compressed in ROM, you can use it with simple search and find in hex editor and in ACWW 1.0 it is uncompressed and can be found in offset 0x00004B44
METHOD 3: If you don't have a debugger with breakpoint and Method 2 is very complicated then, GUESSING is your additional Option
This one is very inaccurate and very few times that it works. The Idea is in some ROM, executable that decompressed the some executables files in ROM are found between 0x4000 to 0x4C00 or 0x02000000 to 0x02000C00 in RAM before the word "[SDK+NINTENDO:BACKUP]" searching those portion found in RAM and ROM can be use to trace the last bx lr that was hardcoded in ROM, anyway for better understanding here's the step by step Details.
- First open the Dump in Hex Editor
- Then Search for "5B 53 44 4B 2B 4E 49 4E 54 45 4E 44 4F 3A 42 41 43 4B 55 50 5D"
- It should give one offset, after that locate the nearest 1E FF 2F E1 (bx lr) upward, list its location (+0x02000000 to serve as location in RAM)
- Open the ROM in Hex Editor then search for "5B 53 44 4B 2B 4E 49 4E 54 45 4E 44 4F 3A 42 41 43 4B 55 50 5D"
- It should give one option, after that locate the nearest 1E FF 2F E1 (bx lr) upward, list its location,
- If its address/offset is 0x4000 exactly greater than in DUMP, then that will be our Hook address for our Patch Routine
- In this case, address in dump can be found in 0x0B44 and in ROM is 0x4B44
- What we need now is to check for this address in RAM (0x02000000 + [Offset In Dump]) which 0x02000B44,
- Then follow step 12-15 found in Method 2
D. Preparing the ASM Custom Routine
After locating where we can hook our code, we can now prepare our ASM Custom Routine. But first we have to make sure that the register we use is safe to use. We can confirm this by debugging, although it is not always smart to do this, we can skip debugging by simply adding push and pop on our routine. And since we hook that branches in lr, we should add bx lr also in the end.
Our ASM Custom Routine will be like this
push {r0-r1} MaxNookPoints: pop {r0-r1} bx lr
|
E. Calculating the Branch/Jump for Hook Address
Basically the ASM to ARDS by kenobi was design only for ARDS and branching/Jump code especially backwards requires to compile separately. I came up with a simple formula and it might not be the best formulation anyway here it is.
[Compiled Branch] = 0xEA000000 + (([TargetAddress] - [LocationOfHook])/4 - 2) AND 0x00FFFFFF)
or use this tool CBcalc.exe created by: Virus
in Our Example Game we will store it in 0x02000010 so it will be the Target Address computation will be like This
[Compiled Branch] = 0xEA000000 + ((0x02000010 - 0x020E7EB8)/4 - 2) AND
0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + ((0xFFF18158)/4 - 2) AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + (0x3FFC6056- 2) AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + (0x3FFC6054 AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + 0xFC6054
[Compiled Branch] = 0xEAFC6054
using CBcalc.exe by Virus it should looks like this
To test if it has the correct branch/jump, input this code in emuhaste 020E7EB8 EAFC6054 or in hasteDS 220E7EB8 EAFC6054 then open the debugger make sure it is paused then go to 0x020E7EB8 the value should be b 0x02000010
F. Preparing the ASM Patch Routine for Hook Address
NOTE: If Hook address is uncompressed in ROM you can skip this Steps, but on our Example game this is very Important
Creating a ASM Patch Routine is the same as 020E7EB8 EAFC6054 so making it as ASM will be like this
ldr r0, =0x020E7EB8
ldr r1, =0xEAFC6054
str r1,[r0]Now since we will hook it in 0x02000B44 we need to add push and pop and of course bx lr so the code will be like this
push {r0-r1}
ldr r0, =0x020E7EB8
ldr r1, =0xEAFC6054
str r1,[r0]pop {r0-r1}
bx lr
Now we need to find a location to store it, I choose 0x02000200 but you can use around 0x02000200 to 0x02000400, but if you find a better offset choose that instead, Compiling with ASM to ARDS by kenobi code should look like this
E0000000 00000020
E92D0003 E59F000C
E59F100C E5801000
E8BD0003 E12FFF1E
020E7EB8 EAFC6054when stored in RAM it should look like this
02000200 E92D0003
02000204 E59F000C
02000208 E59F100C
0200020C E5801000
02000210 E8BD0003
02000214 E12FFF1E
02000218 020E7EB8
0200021C EAFC6054Last Part will be the Branching/Jump, using the Formula in Step E we came up with following result
[Compiled Branch] = 0xEA000000 + ((0x02000200 - 0x02000B44)/4 - 2) AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + ((0xFFFFF6BC)/4 - 2) AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + (0x3FFFFDAF - 2) AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + (0x3FFFFDAD AND 0x00FFFFFF)
[Compiled Branch] = 0xEA000000 + 0xFFFDAD
[Compiled Branch] = 0xEAFFFDADor simply use this tool CBcalc.exe created by: virus
Now we have to check it using debugger using this code 02000B44 EAFFFDAD for Emuhaste /22000B44 EAFFFDAD for hasteDS
Before we Patch everything in ROM we have to make sure that it should work. First we need is to collect all data and test it in No$GBA what we just need is to use E Code type
The ASM Patch Routine and since it should store in 0x02000200 we just need to edit the E0000000 00000020 to E2000200 00000020
E2000200 00000020
E92D0003 E59F000C
E59F100C E5801000
E8BD0003 E12FFF1E
020E7EB8 EAFC6054
The ASM Custom Routine should store in 0x02000010 so we need to edit E0000000 0000007C to E2000010 0000007C
E2000010 0000007C
E92D0003 E59F004C
E59F104C E1C010B0
E59F0048 E3A01000
E5801000 E5801004
E59F003C E3A01001
E1C010B0 E59F0034
E3A01000 E5C01000
E59F002C E59F102C
E5801000 E59F0028
E59F1028 E5801000
E8BD0003 E12FFF1E
021D8FE4 00004E20
021ECBE0 022A925C
021CD774 021D891C
0001869F 021D8FC0
05F5E0FF 00000000
and since we 02000B44 is already decompressed we just need this on the start of the code 02000B44 EAFFFDAD, and in order to write everything once we will add this one more line 52000B44 E12FFF1E and of course the termination code so the Whole code will be,
52000B44 E12FFF1E
02000B44 EAFFFDAD
E2000200 00000020
E92D0003 E59F000C
E59F100C E5801000
E8BD0003 E12FFF1E
020E7EB8 EAFC6054
E2000010 00000080
E92D0003 E59F004C
E59F104C E1C010B0
E59F0048 E3A01000
E5801000 E5801004
E59F003C E3A01001
E1C010B0 E59F0034
E3A01000 E5C01000
E59F002C E59F102C
E5801000 E59F0028
E59F1028 E5801000
E8BD0003 E12FFF1E
021D8FE4 00004E20
021ECBE0 022A925C
021CD774 021D891C
0001869F 021D8FC0
05F5E0FF 00000000
D2000000 00000000
NOTE: No$gba up to 2.5b has one minor bug in E code type to avoid this i change E2000010 0000007C to E2000010 00000080
Input the code in Cheat list then reset the Game.
Now there is one more reason why we test and use No$gba and it is because No$gba support ARDS E type Code.
What we just need is to run the code in No$GBA, reset the game and now DUMP the Memory. why? so we can easily patch the rom. how?
here's how,
9. Then copy the 0x00000010-0x0000008C of DUMP File to 0x00004010-0x0000408C of ROM
10. Then copy the 0x00000200-0x00000220 of
DUMP File to 0x00004200-0x00004220 of ROM
11.. The Save the ROM, now we need to comfirm if it correctly
patch, the best way is to make a file compare. you can use a typical FC/B in
command prompt or use the File Compare in most hex editor
12. That's it we
already have the Patch ROM, now to test/debug it we will need iDeaS or in No$GBA
Debug version
NOTE: For the Record most game the Initial RAM location can be found in 0x4000 in ROM, but you have to remember that it is not always that way, in most cases you have to make a search in Hex Editor
Now since we already made almost everything we need now to debug the patch we made. To do this we can use the iDeaS freeware version or No$gba Debug version.
10. Now after confirming that it patch, go to 0x020E7EB8, click the address in Disassembly window then click [Run In Cursor] or press F6
11. As the emulator Break, trace it more by clicking the [Trace Into] or press [F8]
12. It should jump to 0x02000010, see if the whole ASM Custom routine can be found there, then debug it
A. Making a Final Patcher
This is the Final Step in Making a Trainer, depending on to hacker, he can distribute his code thru IPS, an EXE or anything. I will not make a full detail on this since the program to make an IPS or patcher depends on the application of choice. Anyway here is a little picture that show how its done anyway its already given in the program.
B. Creating an undo ips/patcher
After we done with almost everything, it is normal that we will encounter people that will says that they don't want a portion in cheat found in one of the trainer. So it is always wise to make an UNDOer. But sometimes they just want one portion but not everything , for example, they want everything in the trainer except the "savings account is full", recreating without that cheat would be a very tough choice. The solution is to create an ips/patcher that will remove only one portion in the trainer for one cheat. Anyway it is relatively simple what we only need to do is to replace it with Noop (No operation) code. In ARM writing a register with the same register will act as noop so it would be like this
mov r0, r0 ;when compiled it is 0xE1A00000
so here's what we need to do,
toenailed © 2007