xboxscene.org forums

Author Topic: If Anyone Is Actually Interested In Making These..  (Read 102 times)

EvoX User

  • Archived User
  • Newbie
  • *
  • Posts: 27
If Anyone Is Actually Interested In Making These..
« on: March 27, 2004, 02:08:00 AM »

smile.gif

QUOTE

Here is tutorial #1

Please post any questions or comments in this thread..


Evox Trainer Tutorial.

Tools needed:

Computer
Xbox
Latest Evox
CXBX (http://www.caustik.com/cxbx/)
Network connection between xbox and computer
brain

Useful tools:

Ida Pro (any will do, 4.30-current is ideal)



The first step to writing a trainer is to pick a game, just about any game will do,
but its best to start out with something simple, where its easy to tell the values
you are dealing with. It helps if the value is something you can see update, such
as lives or amount of ammo.

I looked back through the games that I've wrote trainers for, and most of them weren't
what I'd call simple, Armed and Dangerous and TMNT (# of continues) were easiest, so lets
try one of those..

After selecting a game get a copy of the xbe onto your computer and load it up in caustiks
CXBX, go to the file menu and say 'export exe' and save it to something like tmnt.exe, now
go to the edit menu, and select the dump xbe info to option, dump it to a file so that you
can cut and paste.

Open the output file up with a text editor (notepad/wordpad) and scroll until you see
something like (from max payne 2):

Dumping XBE Certificate...

Size of Certificate : 0x000001EC
TimeDate Stamp : 0x3FB3F515 (Thu Nov 13 16:18:13 2003)
Title ID : 0x5454000C
Title : L"Max Payne 2"

The part you care about it the title ID, copy that to another text editor window and
be sure to save it, you'll need it to write the trainer.

Now load up the game on your xbox (I will be showing how to do the Continue trainer for TMNT),
telnet to your xbox's ip.. You will see:

RemoteX Debugger V1.1
.


Pick a character, I chose Leonardo..
Hit A until you you see a bunch of the little robot thingies coming at you..

Now look at your status bar, you have health (bar) # of Shurikens, score, and '6' hearts.

type: value 6

The output should look like:

Store Game State in slot 0
...
...
Done.
Slot 0 Val 6
--

Now lose a life, and continue, now on the screen it says '5' so do a value 5 search.
the output should look like:

Store Game State in slot 1
...
...
Done.
Slot 0 Val 6
Slot 1 Val 5
--

repeat the above process again (lose a life and continue) then search for 4..

Store Game State in slot 2
...
...
Done.
Slot 0 Val 6
Slot 1 Val 5
Slot 2 Val 4
(a bunch of crap)

I then wen't back to the title screen (Start) and started playing again, now that my life
count is back to 6, so I do a value 6 search..

Check 83d00000:83f58000
83d03088
83d030d0
83d0343c
83d03444
83d034d8
83d03910
83d0395c
83d08084
83d0842c
83d0c2dc
83d0c2e0
83d0c2e4
83d0c2e8
83d0c2ec
83d0c600
83d0c604
83d0c618
83d0c634
83d0c638
83d0c63c
83d0c670
83d17424
83d1781c
83d814c0
83d81830
83d81c1c
Check 00a80000:00b80000
00b72448
Check 83b34000:83c60000
83b97274
83b99a54
Check 83575000:835b5000

From this I would have to say that only three of these addresses look like good targets,
00b72448
83b97274
83b99a54

The next step is to look at what data is stored there..

so type: db <address> 10
you should see:

00b72448 : 06 00 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 | ................
83b97274 : 06 6a 7e d2 06 6c 81 d2 06 6a 7e d2 07 66 79 d0 | .j~R.l.R.j~R.fyP
83b99a54 : 06 67 79 d2 59 a1 af e2 bf dc e1 f4 ff ff ff ff | .gyRY!/b?\at

From this I would have to say the first one is the best canidate. Most if not all games
for xbox are wrote in C (or C++) and in C a integer (whole number) is 4 bytes long.
Although you can store values in a single byte, unless memory is tight, it is seldom
done (from what I've seen so far).

So now what? Lets see if we can change the value..

type: poke 00b72448 7

! The hearts value went up to 7! We may have the correct address..

Now its time to see. Now we want to see when this value is changed..

so type: bpmb 0 00b72448 w

Now its time to die again. When you hit start to continue the game froze. This is
good, it means this value WAS updated when you continued..

BP 0 @ 0002a261
EAX : 00b72424
EBX : 00000000
ECX : 00000001
EDX : 00000006
ESI : 013bcd24
EDI : d0044df0
EBP : d0044d4c

TMNT hangs after you do a break point (At least it does for me) so just reboot your system
(type reset in the telnet window) or turn the xbox on and off and reload TMNT, and reconnect
with telnet.

now in IDA pro, click the VIEW-ASM tab, then go to the jump menu, select jump address
and type in 0002a261.

.text:0002A250 arg_0 = dword ptr 4
.text:0002A250
.text:0002A250 mov eax, dword_2AA8E0
.text:0002A255 mov edx, [eax+24h]
.text:0002A258 mov ecx, [esp+arg_0]
.text:0002A25C sub edx, ecx
.text:0002A25E mov [eax+24h], edx
.text:0002A261 retn
.text:0002A261 sub_2A250 endp

Look at the instruction before the break, they are moving the value in edx to some memory
location, this is whats updating the value we see on the screen. So where does this edx
value come from?

If you look at the line above that:
.text:0002A25C sub edx, ecx

This means: edx = edx - ecx

if we look back to what our break point said, we see that ecx equals one, so that means its
edx = edx - 1 and since edx equals 6 after the subtraction, that means it was previously 7.

so rewrote in english:

move some address stored at 2AA8E0 into eax
*move the value that is at eax + 24h into edx
move the value (1) that was pushed to this routine into ecx
-subtract ecx from edx and place it in edx
*move edx back to where it came from (eax + 24h)

So we have a few options, we can change ecx to 0, we could not subtract the value, or we
could remove all instructions from the function, or we could just return as soon as we get
to the function.

move some address stored at 2AA8E0 into eax
*move the value that is at eax + 24h into edx
move the value (1) that was pushed to this routine into ecx
*move edx back to where it came from (eax + 24h)

If we remove the subtraction part, we end up moving a value from
eax+24h to edx
then from
edx to eax+24h

That will keep the value the same, so lets do that..

The SUB starts at 0002A25C and ends at 0002A25D so we have to remove two bytes,
the simplist way to do this is to 'NOP' (no operation) the SUB instruction.

so in your telnet window type:

poke 0002A25C 90
poke 0002A25D 90

Now start playing, and try to die, the value should stay the same, and you now have
infinite lives!


This is an awesome tut that he made and I hope you guys can find it as useful as I did.
Logged

EvoX User

  • Archived User
  • Newbie
  • *
  • Posts: 27
If Anyone Is Actually Interested In Making These..
« Reply #1 on: March 27, 2004, 02:38:00 AM »

QUOTE
Heres tutorial #2

Please post comments and questions in this thread.

Evox Trainer Tutorial.

Tools needed:

Computer
Xbox
Latest Evox
CXBX (http://www.caustik.com/cxbx/)
Network connection between xbox and computer
brain

Useful tools:

Ida Pro (any will do, 4.30-current is ideal)


Tutorial #2... NBA Jam 2k4 (USA/NTSC)

I assume that you have read the TMNT tutorial, so you are at least
slightly familiar with the tools referenced, if not, please go read it first.

Convert your xbe to an exe, load it into Ida Pro, or whatever your perfered
disassembler is..

Our goal is to add an option so that you can buy any attribute for free, regardless
of how much money you have, and hopefully go on by yourself to extend it to cover
all purchases on unlockable items.

I started out doing a traditional search for values, but came up empty, so I looked
for another way to train the game. I noticed when you start a new career that you
begin with 10,000 jam points to spend on upgrades for your player. So I took 10,000
and converted it to hex (I used the calculate in A.X.E hex editor, but windows calc
will do just fine) and got 2710h, so I search using the text search tool for
(spc)2710h

(spc) being a blank space, so that I wouldn't get matches for 42710h, etc.

The first occurance I come across is:

.text:0001A2EF mov dword ptr [esi+2Ch], 2710h
.text:0001A2F6 mov al, 0FFh

.text:0001A2E0 00 00 89 7E 14 66 A1 A8-5E 2B 00 66 89 46 38 C7 "..ë~¶fí¿^+.fëF8¦"
.text:0001A2F0 46 2C 10 27 00 00 B0 FF-88 86 E6 03 00 00 88 86 "F,'..¦ êåµ..êå"
^^^^^-- Value..

So I poke 0001A2F2 with a value (ff) and start a new player, what do ya know, instead
of starting with 10,000 I started out with 10,239.. So now we know we have found what
initially load the value into some memory location.

*** So I exit out of the menus, and set a 'bpx 0 0001A2EF' and re-enter the jam store.
I instantly get a break...

BP 0 @ 0001a2ef
EAX : 00000019
EBX : 00000000
ECX : 011eaaf4
EDX : 011eabdc
ESI : 011eaaf4
EDI : ffffffff
EBP : d00648c8

(yours may be different)

so I take ESI (011eaaf4) and add '2c' to it and get 11EAB20, this is where the money
is stored (at least at first). so I clear my break point (bpc 0) and choose a profile.

I then go to the create a player screen, and look for somewhere to spend money.
If you hit the 'R' trigger until you are at the guy flexing his muscles you will see
you can buy attributes..

So I hit a, and see a bar below, I hit right, and see that my pts decreases, so I hit
left, then set a breakpoint on the address I learned.

bpmb 0 11EAB20 w

(we only care about writes at this point)

Now hit right again, you should get a break..

!!!! If you don't then choose the menu option discard and exit, go to the create a
player option, then turn back on the bpx 0 0001a2ef and use the new offset, sometimes
it changes on me, sometimes it doesn't..

I had to follow my advice above, and reget the address

BP 0 @ 00084d32
EAX : fffff830
EBX : 00000003
ECX : 012dfb90
EDX : 00000fa0
ESI : 012d4750
EDI : 00000002
EBP : 00000000

Now go to 0084d32 in your disassembly..

.text:00084D26 mov eax, [esp+arg_0] ; Get value to subtract (negative number)
.text:00084D2A add edx, eax ; Take our value (edx) and sub above #
.text:00084D2C mov [ecx+0E0h], edx ; move new value to where we store money
.text:00084D32 retn 4

We have multiple options, we can fix the game to always send '0' or a positive number when
you buy an item to this function, or we can make it not subtract, or we can let it do
all that, and just not update our value, I chose to do the third option since it makes it
easier for me to find other writes to that address (less uf'ing)

So we

poke 00084D2C 90
poke 00084D2d 90
poke 00084D2e 90
poke 00084D2f 90
poke 00084D30 90
poke 00084D31 90

yay, now it doesn't cost anything to buy attributes..

But wait, we aren't done, as you keep hitting right eventually it will stop, since we
don't have enough money to purchase!

Okay, so now that we have the write taken care of, lets see where it reads (since its probably
getting the value, comparing it, then if there is enough, going on)

so set your break point just as you did above (bpmb 0 11EAB20 w) but this time do a
bpmb 0 11EAB20 r (be sure to use the address YOU got, since it will likely be different)

Oh my, as soon as we set this we got a break, but we didn't hit any key...

.bpmb 0 12DFC70 r
.Break
BP 0 @ 00085be5
EAX : 00000fa0
EBX : 3c88b0f0
ECX : 012d4750
EDX : 00000002
ESI : 012dfb90
EDI : 3c88b0f0
EBP : d00648c8

.text:00085BDF mov eax, [esi+0E0h]
.text:00085BE5 push eax
.text:00085BE6 lea ecx, [esi+4C8h]
.text:00085BEC push offset aJamPtsD ; "Jam Pts: %d"
.text:00085BF1 push ecx
.text:00085BF2 call sub_1B37FD


What this is doing is effectively in C is something like sprintf(ecxlocation,"Jam Pts: %d", eax)
eax being our pts, so this is likely JUST doing the screen update stuff, and not effecting
our compare..

So we have two options, put something else in eax, so we don't break, or just live with it
and hold right on our controller and keep entering 'uf's (up enter)

Sooner or later, you should get a break thats different.. It took me 3 uf's.

BP 0 @ 000c0c81
EAX : 00001f40
EBX : 00000003
ECX : 012dfb90
EDX : 000000dc
ESI : 012d4750
EDI : 0000000b
EBP : 00000000

.text:000C0C73 call sub_C0200
.text:000C0C78 mov ecx, [esi+14h]
.text:000C0C7B cmp [ecx+0E0h], eax
.text:000C0C81 jl short loc_C0CC6

So this is getting our value with the ecx+0e0h and comparing it to eax, if we are less
then, then it jumps..

So we want to remove that..

poke 000C0C81 90
poke 000C0C82 90

Hmm, but we still didn't get the item, lets try that again.

BP 0 @ 000c04fe
EAX : 012dfb90
EBX : 00001f40
ECX : 00000001
EDX : 00000001
ESI : 012d4750
EDI : 0000000b
EBP : 00000000

Oh, a second check, but since we patched the first one, now we get to this one.

.text:000C04F5 mov eax, [esi+14h]
.text:000C04F8 cmp ebx, [eax+0E0h]
.text:000C04FE jg short loc_C0513

This looks a bit different, but you can see how its similar, now its going to jump if
the value of the attribute is greater then what we have (ebx - cost, [eax+0e0h] - our $$)

so

poke 000C04FE 90
poke 000C04FF 90


Now clear your breakpoint (bpc 0) and try out your new patch.. Yay it works!

Now for extra credit, attempt the same process with the unlock options =)

If you do go on to do that, remember there ARE multiple checks, and in odd spots
I think there are 11 total checks, I always just nop'd the 'jl'

Hope this helps you out with non value searching usage of the debug tsr..




Havent read all of this one yet but still.. figured I might as well put his in here too.
Logged

the14th

  • Archived User
  • Newbie
  • *
  • Posts: 6
If Anyone Is Actually Interested In Making These..
« Reply #2 on: April 08, 2004, 02:59:00 AM »

blink.gif
Logged