Go Back   FileForums > Games > Game Coders

Closed Thread
 
Thread Tools Display Modes
  #1  
Old 15-04-2007, 20:00
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
Cool Infernal - Trainer & Gadgets

Starting with a basic trainer, and evolving/expanding the project in time once I discover more. I'll keep a diary of what I did, so others benefit from this experience. Also, adding some stuff I discovered while analyzing the game or its files. Hope this board allows constant editing of same post (I'd hate to double/triple post)

First off, let me say that I've tested all the trainers available for this game and all of them have only one option available (Unlimited ammo), and even so, that option is global (works for both player and enemy). Well, if they also had god mode, it wouldn't have been a pain in the ass to have enemies with Uzis shooting constantly on your ass

Therefore, I've been trying to conceive an ammo feature for the last few hours, and since I couldn't find a base pointer for my player (it shifts like mad, even though the game doesn't use code-shifting), I decided to call in for ingenuity and use another method :X Kinda g4y, but it works pretty nice.

Let me show you what I'm talking about...


[ Diary log #1 ]


Both the enemy and I are using the same function, located here :



That's the code that would normally appear amongst others in your debugger window, when you're trying to see what writes to your ammo address.
Quote:
sub [eax+538], ecx

// eax = player ammo pointer
// 538 = weapon slot offset
// ecx = the amount deducted from your weapon's ammo
All nice and fine till here. If you nop that sub, both you and your enemies will have unlimited ammo. That's what all the trainers available on gamecopyworld (haven't checked if CH has one - sheep might beat the crap out of this game) do...

We want it one sided, and for that, also taking into account that I wasn't able to find a base pointer for the weapon pointer, I used something else. Noticed this :



Interesting - "enemy" - that word appears whenever the enemy uses that sub. Problem is the syntax is not always in the same manner. For instance, the pistol will always be "Enemy-pistol-ammo-..." while testing for Uzi, I saw "UZI-ammo-enemy-..."

In case you don't follow so far, I'll use word comparing So far - I'm at level 3, where you have to gain access in a cathedral by blowing its walls, right after Doctor Wolf flies out in a chopper - I haven't encountered a weapon to have the letter y in its description, therefore, the script - I hope you have Cheat Engine 5.3 installed !
Quote:
[ENABLE]

alloc(cave,256)
label(back)
label(loop)
label(out)
label(enemy)

//9B8140:
cave:
pushad
loop:
mov bl, [eax+14]
cmp bl, 79
je enemy
cmp bl, 0
je out
inc eax
jmp loop
out:
popad
jmp back
enemy:
popad
sub [eax+538],ecx
jmp back

5CC158:
jmp cave
nop
back:

[DISABLE]

5CC158:
sub [eax+538],ecx

dealloc(cave)
Time to explain what it actually does, and I'm going to sparse it in pieces, so you get the whole idea :

---
[ENABLE]/[DISABLE]

This is common CE syntax, pretty much and quite similar to ON/OFF. What's below the [ENABLE] tag will work as enabling the cheat/turning on the feature. The script will perform, once assigned to your cheat table, what ever is written below the [ENABLE] tag. How far ? Till the [DISABLE] tag. Same thing goes for [DISABLE]. What ever's under it will be written once you deactivate the script (tick/untick in your table). [DISABLE] works as "restore all" feature, except it restores only what you assign under it.
---
alloc(cave,256)

CE allows users to allocate memory of different sizes, which is pretty easy to work with, removing the worry to have to find an empty cave to write your code in. The syntax is as follows : alloc(name,size)
---
label(back)
label(loop)
label(out)
label(enemy)


The use of labels is also possible. Using labels you can set "waypoints" in your code to work faster and easier. Syntax : label(name) - note that numbers aren't supported in any name.
---
dealloc(cave)

The memory you allocate can be easily deallocated. It's also useful to use this code at the end of your script, since the allocated address will always be the same. If you don't use it, CE will keep allocating different addresses to your cave.
---
[DISABLE]

5CC158:
sub [eax+538],ecx

dealloc(cave)


This is the original code, and that's what CE will write when I disable the option. It's the equivalent for a "turn off the cheat" option.
---

Now to the main "plot" :

cave:
pushad
loop:
mov bl, [eax+14]
cmp bl, 79
je enemy
cmp bl, 0
je out
inc eax
jmp loop
out:
popad
jmp back
enemy:
popad
sub [eax+538],ecx
jmp back

5CC158:
jmp cave
nop
back:


What will the code do is to copy the string I mentioned earlier (Enemy-pistol-ammo-standard-8237) letter by letter and move it in a register, then compare it against the letter y. If that letter is encountered when scanning the string, perform normal code. If not, skip the sub [eax+538],ecx instruction. If the sub is skipped, we don't get anything deducted from out ammo, therefore one-sided unlimited ammo...

---
cave:

That is the address I've allocated at the beginning. The syntax for writing to it is : name: Basically, you tell CE to write at address "name", in my case at address "cave"
---
pushad

Saving the state of the registers, since we'll perform operations and use them. It's always nice to save the state, as the game might crash if one of the registers you use is overwritten.
---
loop:

This is the first label I declared. Labels can be used as addresses, or part of a code. In this case, "loop" will be an address located immediately below the "pushad". You'll see how the full code looks like in the end.
---
mov bl, [eax+14]
cmp bl, 79
je enemy


I chose to work with ebx, and since I'm operating with letters (bytes), I'll use the lower part of ebx (32b), which is bx (16b) and can be sparsed in 2 (bl, bh - both on 8b). 'l' for lower, 'h' for higher. The text string you saw in the 2nd picture is located at eax+14. The pointer is eax, eax+14 is the address holding the string. So - move in bl the first byte found at address eax+14 -> mov bl, [eax+14].

Further on, on the 2nd line, we compare bl with 79 (letter "y" in hexa). If they match (if y is found within the string), jump to label "enemy", where the game will allow their ammo to decrease
---
cmp bl, 0
je out
inc eax
jmp loop


If bl is not 79, compare it against 0. In case you haven't noticed, we only need to compare the string and stop after it. Or we'll hit an endless loop, and game will freeze. So, the cmp I added will check if the whole string has been "scanned" and stop at first 0 that's encountered. If bl is 0, jump to label "out", where the game executes a code that misses the "sub", therefore we don't get any ammo deducted. If bl is not 0, increase our pointer to move on to the next spot, and return to label "loop" to go through the function again, till the whole string is read.
---
out:
popad
jmp back
enemy:
popad
sub [eax+538],ecx
jmp back


Label "out" defines another address in the cave, at which we land from the jump mentioned above. We use "popad" to restore the state of the registers and allow the game to get back in "flow" Once the code is used, we jump back to address "back" (you'll see below)

The other label does the same thing, except it does it for the case in which the letter "y" is found in the string.
---
5CC158:
jmp cave
nop
back:


Our original address 5CC158: at which we write what's below it. The original code has 6 bytes (count them in the 2nd pic). A jmp uses only 5 bytes, so we'll use a nop to even out the code. 5+1=6. As I said above, once the out/enemy labels are used, at the end of each other you see "jmp back". Well, if you look at the code, I used in the function "back:" which defines an address located below the "nop". Therefore, "jmp back" means - jump to the address located below that nop. Since the sub had 6 bytes, "jmp back" means jump to 5CC158+6. Hope it's clear...
---

Phew. Long article. Once you copy the script, open up Memory View, press Ctrl+A and paste it the auto-assembler window. From the top menu (in that window), choose "Assign to table". Then check you table. You'll see what I meant with ON/OFF Ticking the checkbox in front of the script means ON/ENABLE. Unticking it equals OFF/DISABLE.

Time to show you how it all looks like :



Hope now it's understood.

Last edited by کunβeam; 15-04-2007 at 21:15.
Sponsored Links
  #2  
Old 15-04-2007, 20:26
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
Hmm. Yeah, double-posting because :

- it needs a separate post;
- I got past the 12 images limit;

So, before judging, read the above :P

Anyway, was analyzing the file in looks for a clue regarding game's version. I don't want to go in-game, so I poped up PE Explorer. Since right-clicking the file and checking "Properties" didn't show a thing about the file, I used that tool.

Surprise :



I've played this game a while ago, it's made by JoWood. Interesting - Archangel...

As for the version, I could only get this out :



Digging on. They use SolidShield, hah...
  #3  
Old 15-04-2007, 20:46
DABhand DABhand is offline
Banned
 
Join Date: Nov 2004
Location: Near my PC
Posts: 5,406
Thanks: 0
Thanked 3 Times in 3 Posts
DABhand is on a distinguished road
Woulda been better in the coding section, only the lesser minded come into this area :P


But saying that is the game not using static addies to store pointers for players and enemies?


Remember the health injection I wrote about Fable. Similar to that perhaps?
  #4  
Old 15-04-2007, 21:24
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
Haven't read that. I'll start looking for it. Might be. Thing is, with Infernal, I actually found a trace, but it needs more in-depth research.

For instance, sub [eax+538],ecx had a "brother" up ahead like :
Quote:
mov edx,[esi+56C]
...
mov eax,edx
sub [eax+538],ecx
So, if you look at that, you got 2 offsets : 56C and 538. I looked in-depth for a stable link to esi. Searched for a pointer to it, and found plenty (about 600). Debugged it and all I got were opcodes like "mov eax,[edi]" =| I eventually found a pointer for it, was level 3. Kinda like : B6xxxx + 2F0 + 56C + 538. The pointer was static, but once I changed level or reloaded, everything died. Come to think about it, if this game is similar to Archangel in engine, it's all kinda self-explained. I remember I hit the same issues while playing that game...

I think the method I wrote about is quite simple. I'll read your Fable article, and see if I can find anything matching my situation

Oh, almost forgot !

Infernal command lines :

1. /window - start the game in windowed mode (I believe it's 800x600)
2. /safe - start game in safe mode (for some reason, I get an error msg box stating I have to reinstall the game - yeah, missing some files)
3. /nops - am yet to discover what this does (no p - player? - s - something?)
4. /ulkytutft67gfj655gy - no, it's not a joke, it's a command line - I believe it's used to disable some debugging protection features from both LUA/SolidShield - still checking

Enjoy ! I'll be back later...

P.S.: Once this thread gets big, you can move it to the Coding section.

P.S.2: Looking for a way to pop that window up - the one you see in that PE Explorer pic

Last edited by کunβeam; 15-04-2007 at 21:27.
  #5  
Old 16-04-2007, 00:05
TippeX's Avatar
TippeX TippeX is offline
zeroes and ones.....
 
Join Date: Jan 2003
Posts: 3,842
Thanks: 2
Thanked 32 Times in 22 Posts
TippeX is on a distinguished road
why the pushad when you're only using bl

push ebx / pop ebx would be quicker..

also you aren't strictly checking for 'enemy' you're just checking for 'y'
that will probably lead to some false positives being hit and the game
acting strangely..
__________________
bleh
DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you...
  #6  
Old 16-04-2007, 00:29
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
As I said, I'm checking for 'y' because so far there isn't any weapon that has 'y' in its description. In this case, it works, but for other games I might get pwned

Also, I used pushad because I got "burnt" in lots of times. For example, I was training Thief 2 (I'll make an article about it) and I used as you said "push/pop register". I reached to this secret door which was getting opened by a lever. Once pulled, the door wouldn't open. If I used pushad/popad, it did open It's a matter of registers synchronization. At state_1, register_1 is value_1. If I push only register_1, the other ones will change state, and once register_1 is poped, the state will get fuxxed. Using pushad/popad I'm making sure the whole state is restored (even flags - ooops, that's pushfd/popfd, my bad).

Returning to the other issue, I've tested the option thoroughly, and I haven't got any false positives Player's ammo is clean in text, while the AI's ammo always has "enemy" in the string. Letters 'e', 'n', 'm' are also found with ease in one such string. Letter 'y' is only found at the end of the word 'enemy' and doesn't have any other instance in the string. I got lucky :P

Last edited by کunβeam; 16-04-2007 at 11:54.
  #7  
Old 16-04-2007, 02:42
TippeX's Avatar
TippeX TippeX is offline
zeroes and ones.....
 
Join Date: Jan 2003
Posts: 3,842
Thanks: 2
Thanked 32 Times in 22 Posts
TippeX is on a distinguished road
using pushad/popad is just a workaround then, oh and eflags is NOT stored with pushad thats what pushfd/popfd is for

i suggest you brush up on your asm code, there is a different reason for the pushad/popad workaround u do....

dont believe me on the eflags.. try this code then

xor eax,eax
pushad ; < eflags are now 0246h (C 0 P 1 A 0 Z 1 S 0 T 0 D 0 O 0)
inc eax ; < eflags are now 0202h (C 0 P 0 A 0 Z 0 S 0 T 0 D 0 O 0)
popad ; < restore the registers...

flags changed? hell yeh...
__________________
bleh
DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you...

Last edited by TippeX; 16-04-2007 at 02:45.
  #8  
Old 16-04-2007, 03:53
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
I used to believe that pushad stands for push a-d (eAx, eBx, eCx, eDx - A<->D). But I was wrong Anyway, I stand true to my beliefs. Hope you don't mind :P
  #9  
Old 16-04-2007, 06:49
TippeX's Avatar
TippeX TippeX is offline
zeroes and ones.....
 
Join Date: Jan 2003
Posts: 3,842
Thanks: 2
Thanked 32 Times in 22 Posts
TippeX is on a distinguished road
how can u stand true to your beliefs when i just showed you your beliefs were flawed, and that using pushad/popad is just a lame way of fixing a bug caused by bad coding...

POPA/POPAD - Pop All Registers onto Stack (80188+)
POPF/POPFD - Pop Flags off Stack

so its a bit more than a->d
also it is not flags, flags are a different opcode...

why not actually properly learn asm, and the mnemonics, then start teaching eh?
__________________
bleh
DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you...
  #10  
Old 16-04-2007, 11:38
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
I was sure you'd get me wrong I stand true to my beliefs of using pushad rather than normal push. I am aware it doesn't store flags. It isn't lame, it is just logics. You want to tell me if I push/pop a register, the original state will remain unchanged after the pop ? What will happen with the rest of the registers while I push only one ? They don't get saved. So, by the time I pop it, the others would've changed...

I know ASM so far as game training requires it, am not a pro @ it, nor do I like to use excentrisms and talk like "Yeah, but your code isn't 100% ergonomic" or "I could've done better". I am aware there's always room for better.

Also, most of the people are so comfortable nowadays that they like to just reply to others about their flaws/"mistakes", instead of putting their own HAND to writing and explaining. Oh, don't worry, we'll understand it, as complicated as you'd explain it. Show me a really good tutorial that trains a game properly (I mean new games - 2006/2007) and I'll start taking notes...

Sorry if I sound incisive, it's not oriented towards you, it's just that everybody's on my ass lately, no matter how good a post would look like. If I write a code, and post it, those who don't know ASM at all will take it as is. Those who are pro at it will always find room for better and want me to perfect the code to suit their "needs" (they don't actually use the code, but rather enjoy debating around it to no avail)...

One way or another, the code I posted is operational, and as lame as it looks like, it's working - yes, I know, only for this game...

@Tippex: I have a request out of you. Take that code I posted, and make it better. Don't go heuristics like "You should use a player pointer", since I am aware of that. Just that code I posted, your version. Please Am curious what changes you'd addition to it. It's not a sarcastic request, but more like a "trying to grasp more XP" request

You got all you need : the address to jump from, string location, etc...

Last edited by کunβeam; 16-04-2007 at 11:49. Reason: I am open-minded...
  #11  
Old 16-04-2007, 12:06
TippeX's Avatar
TippeX TippeX is offline
zeroes and ones.....
 
Join Date: Jan 2003
Posts: 3,842
Thanks: 2
Thanked 32 Times in 22 Posts
TippeX is on a distinguished road
i dont do requests, and i also do not have to prove myself.. been there, done that

if you push / pop a register then yes, it will be preserved, thats the whole poinf of the opcode, when coding especially at asm level, the register preservation (and in some cases) flags are for YOU to maintain... most api's will definately destroy eax, ecx and edx.. ebx is usually used within windows messaging and within callback procedures..

fundamental flaws in the code would be your looping
inc eax, could lead you well out of the memory boundaries that would be my only cricicism.. but in trainers, especially with what you're doing its important to preserve / set the flags
take for example your little bit of code, see the sub at the end, thats going to effect the flags and could well screw the game up, as it might branch when it shouldnt etc.. thats where the difference between good code and bad code comes in.... stack balancing + register preservation, is very important
__________________
bleh
DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you...
  #12  
Old 16-04-2007, 12:13
کunβeam کunβeam is offline
Banned
 
Join Date: Apr 2007
Location: Romania
Posts: 18
Thanks: 0
Thanked 0 Times in 0 Posts
کunβeam is on a distinguished road
I didn't ask you to prove yourself. I was curious how would your version of that code look like. Also, how would eax go out of the boundaries, when : [1] it's stacked; [2] it only increases so far as bl is not 0; [3] eax gets restored, so nothing crashes; [4] the sub uses the pop'd eax...?

Yeah, I agree - god damn stack gave me so many headaches back in the days. And it still does. Pretty powerful thingie.
  #13  
Old 16-04-2007, 12:37
Joe Forster/STA's Avatar
Joe Forster/STA Joe Forster/STA is offline
Senior forum member
 
Join Date: Nov 2000
Location: Hungary
Posts: 9,798
Thanks: 16
Thanked 329 Times in 214 Posts
Joe Forster/STA is on a distinguished road
(I pity people who have to learn ASM on a relatively sophisticated platform as the x86 CPU and DOS/Windows. Back in the microprocessor days, a Z80 was much easier to understand, not to mention the even simpler good old 65xx series.)
__________________
Joe Forster/STA
For more information, see the FileForums forum rules and the PC Games forum FAQ!
Don't contact me via E-mail or PM to ask for help with anything other than patches (or software in general) done by me, otherwise your request may be deleted without any reply!
Homepage: http://sta.c64.org, E-mail: [email protected]; for attachments, send compressed (ZIP or RAR) files only, otherwise your E-mail will bounce back!
  #14  
Old 16-04-2007, 14:55
caki caki is offline
Registered User
 
Join Date: Dec 2004
Location: UK
Posts: 899
Thanks: 0
Thanked 0 Times in 0 Posts
caki is on a distinguished road
Wow, this section is actually seeing some action
__________________
Sanity is for the weak.
  #15  
Old 17-04-2007, 02:05
TippeX's Avatar
TippeX TippeX is offline
zeroes and ones.....
 
Join Date: Jan 2003
Posts: 3,842
Thanks: 2
Thanked 32 Times in 22 Posts
TippeX is on a distinguished road
Quote:
Originally Posted by کunβeam View Post
Also, how would eax go out of the boundaries, when : [1] it's stacked; [2] it only increases so far as bl is not 0; [3] eax gets restored, so nothing crashes; [4] the sub uses the pop'd eax...?
okay, here goes, u say eax = stack.. fine
cave:

pushad ; preserve registers
loop: ; loop begin
mov bl, [eax+14] ; okay, eax supposedly on the stack
cmp bl, 79 ; is bl = 79
je enemy ; if so, boing out of this routine
cmp bl, 0 ; is bl = 0 (presumably end of string)
je out ; if so, boing out
inc eax ; incriment our pointer by 1
jmp loop ; loop << this is where u can cause a crash eax may be on stack, but the stack does have limits, and this could be reproduced by puting crap in eax
out:
popad ; restore the registers
jmp back ; get out
enemy: ; enemy portion
popad ; restore registers
sub [eax+538],ecx ; and do the mathy thing
jmp back ; then get out

back:


flags not preserved, the sub [eax+538], ecx can adjust the flags

Quote:
[2] it only increases so far as bl is not 0;
erm, it only increases as far as when byte @ [eax] = 0, it will keep going on until this happens or it finds the 'y'

what i would do is check that the byte @ eax fits within an 'acceptable' character range, then i would do an lstrlen or so on it to calculate its length and work from that... its relatively safer..

like check it fits within 'a->z/0-9' or 'A->Z /0-9' then begin processing
the game could act on the flags, from the code, so the cmp, etc can screw
the flags, ideally what u want to do is to set the flags for when u handle the player portion, (where u set the flags to a good condition), and leave them as-is for the enemy portion..

such code could be like

call check_ammo_amount ; this would be the code that you patch
jz user_has_no_ammo

etc..
where the flags are DEFINATELY important, it depends on how the game was coded, but its worth paying attention to..

and i guess u can pity me joe, cos i started out in the dos days, interrupts, 8 bit, 16 bit, pmode... all fun to learn though
__________________
bleh
DO NOT PM me with questions, leave that in the forums...ESPECIALLY if i dont know you...

Last edited by TippeX; 17-04-2007 at 09:28.
Closed Thread

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Rainbow Six Vegas v1.04 Trainer Doesn't work mfw41 Game Trainers 7 30-03-2007 23:13
The best (and fun) NFS:Carbon trainer available intoksicated General Gaming 3 22-12-2006 05:55
Gothic 2 Trainer prb Dark3lement General Gaming 3 17-08-2006 16:50



All times are GMT -7. The time now is 15:17.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Copyright 2000-2020, FileForums @ https://fileforums.com