Worms United (1996) code injection problem

Memory scanning, code injection, debugger internals and other gamemodding related discussion
Post Reply
polipolictosaurus
Noobzor
Noobzor
Posts: 6
Joined: Sat Mar 09, 2019 4:47 pm
Reputation: 0

Worms United (1996) code injection problem

Post by polipolictosaurus »

Hello everyone, i'm searching someone that can help me with a problem i've encountered so far:

I'm relatively new to assembly and cheat engine and i'm doing this for learning and make this old game more fun.
So basically i want to replicate some "Gamemodes" that newer worms game have to this old game by making a cheat table, stuff like DoubleDamage, random weapon for every turn by setting to 0 ammo to every weapon except to a random one.

The problem I've encountered is about the double damage, I can't identify in the game where the damage get's calculated, by far the things i've discovered are:

The game runs over DosBOX 0.74 which's Virtual Memory base address is at 0x01D3A1A0
Then with some searches i figured out the addresses for every worm HP bar in the game, the game store the value as a byte value (Max 255)
With the addressess and HexCalc i got the offsets so that i don't have to find them every single time I open the game.
When everything was set up, I went to a worm hpbar address to check what code writes on that address (Find out what instructions writes on this address)
Now the problem is, there's no sub code here, i mean i supposed that damage was calculated by a subtraction, instead there is a mov, so i guessed that simply the game ovverride the old life value with a new life value by that mov code, exactly it goes like this:
Image

mov [eax+ecx],ebx
I confirmed my guess because cheking eax+ecx result them in being EAX the base vmem address, and ecx the offset to that worm hpbar.
No matter which worm it is always this one function that changes their life.
Now the problem is i would like to change the value of the damage dealt to the worm, but I can't find neither the value itself by normally searching for it, neither find some clue in the code where this happens, theorically in EBX there should be stored the new life value (Old life - damage taken), but there is no sub whatsoever the code near that line.
I've tried changing the ebx register manually for example : Mov [eax+ecx],50 because i thought that insteand of use the new value it would simply set the worm life to 50 but it just crashes immediatly after.
Also i figured out that in the ESI is registered the damage value for the turn, in this case is 33 (51), the turn after i dealt 15 dmg and it was F so it should be correct, so i tried to change the ESI value but nothing happens at all...

Hope someone can help me, thanks everyone for any reply!

TimFun13
Expert Cheater
Expert Cheater
Posts: 1353
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 7

Re: Worms United (1996) code injection problem

Post by TimFun13 »

It's at a stack address esp+24, you'll need to understand a bit more about ASM and memory, plus how the stack works. But ultimately you'll want to see where it writes to the address of esp+24. But you might need to find where this is called from or it might be just above the code your looking at.

polipolictosaurus
Noobzor
Noobzor
Posts: 6
Joined: Sat Mar 09, 2019 4:47 pm
Reputation: 0

Re: Worms United (1996) code injection problem

Post by polipolictosaurus »

Ok, At least I have some clues now, I know how stack works but maybe not enough ahahah, so i'm trying to backtrace where it writes on that esp+24, without much of results, if i try to break and trace that function i just get endless results and it's hard to get something
Above the code i've sent in the screen there is nothing about it, and also i tried to NOP it just for the sake of kinda: "Nullifying it to get 0 damage" but it crashes the game.
Not gonna give up on this, thanks for the reply!

TimFun13
Expert Cheater
Expert Cheater
Posts: 1353
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 7

Re: Worms United (1996) code injection problem

Post by TimFun13 »

I'd break and trace the instruction, just use a start condition with the actual address of the HP and set it up to step over calls. Then this will help you find where it's being called.

Here's a video that goes over it; it's a bit outdated, but you should be able to figure it out.
https://youtu.be/KlvW4CuEqCg

polipolictosaurus
Noobzor
Noobzor
Posts: 6
Joined: Sat Mar 09, 2019 4:47 pm
Reputation: 0

Re: Worms United (1996) code injection problem

Post by polipolictosaurus »

Ok i'm back after some more tests ahah, i couldn't manage to find properly where the stack pointer is called but i've discovered the reason why i can't touch anything about the code without making it crash, my guess it's due to the game being emulated, that causes the instruction I try to override to be used for multiple addresses ence making the software crash as soon as i execute the changes.
So i thought that i can try to make an If statement in assembly that goes: "Do this ONLY if the address stored in eax+ecx is the one of the health value" and with that it "works"the game doesn't crash anymore and also checking the adress with "Check what writes to this address" result in a new function being recognized when the script is active, yet i tried with something stupid like: mov [eax+ecx],1 and despite not crashing, it still didn't set my hp to 1, i've also tried 0x1 as value to put in it but nothing...

EDIT: I finally managed to get it to work, the problem was at the CMP function, i compared what is IN eax+ecx due to the [] (So it was my health value) instead of comparing their addresses combined, for now i've fixed this by comparing ecx (that contain the offset to the worm hp from the emulator vmem base address) and to negate all damage to one specific worm by this code and i think i can probably manage to turn this around from here on, i hope!

Code: Select all

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: 
cmp ecx,0x3B7856
jne originalcode
nop
add esp,18
jmp exit

originalcode:
mov [eax+ecx],ebx
add esp,18

exit:
jmp returnhere

"DOSBox.exe"+18EDA:
jmp newmem
nop
returnhere:


 
 
[DISABLE]
dealloc(newmem)
"DOSBox.exe"+18EDA:
mov [eax+ecx],ebx
add esp,18
//Alt: db 89 1C 08 83 C4 18

TimFun13
Expert Cheater
Expert Cheater
Posts: 1353
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 7

Re: Worms United (1996) code injection problem

Post by TimFun13 »

For the compare, you can use LEA (load effective address, I think):

Code: Select all

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem:
push esi // store ESI to the stack
lea esi,[eax+ecx] // set ESI to the address of EAX+ECX
cmp esi,DEADBEEF // compare ESI to the Hex number DEADBEEF
pop esi // restore ESI
jne originalcode // jump if not equal
// there's no need for the NOP (no operation) here, 
//      only at the injection point of the game's code.
add esp,18
jmp exit

originalcode:
mov [eax+ecx],ebx
add esp,18

exit:
jmp returnhere


"DOSBox.exe"+18EDA:
jmp newmem
nop // The NOP is  needed here for padding.
returnhere:


[DISABLE]
dealloc(newmem)
"DOSBox.exe"+18EDA:
mov [eax+ecx],ebx
add esp,18
//Alt: db 89 1C 08 83 C4 18
Here are some resources.
[Link]
[Link]
[Link]
[Link]
[Link]

polipolictosaurus
Noobzor
Noobzor
Posts: 6
Joined: Sat Mar 09, 2019 4:47 pm
Reputation: 0

Re: Worms United (1996) code injection problem

Post by polipolictosaurus »

Ohh thanks for the tip!, I'll try everything in the next days, and share the results here.

polipolictosaurus
Noobzor
Noobzor
Posts: 6
Joined: Sat Mar 09, 2019 4:47 pm
Reputation: 0

Re: Worms United (1996) code injection problem

Post by polipolictosaurus »

Ok, I tried the way you suggested, it works perfectly but i had to change everything for the what i had in mind originally:
I want to make a double damage gamemode, the script i've originally created and yours checked for 1 particular hp address, so it worked but only for that 1 worm out of the possibly 16 in the game,

So i've adjusted it for 4 worms currently as this:

Code: Select all

[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
label(damage)

newmem: 
cmp eax,0x09850020 //First check for the vmem base address to be in eax, if i skip this the game crashes
//my guess is the emulator has other istances where ecx is the same as the offsets
jne originalcode
cmp ecx,0x3B75A6 //Then i just check for every offsets of the hp bar,
je damage
cmp ecx,0x3B7652
je damage
cmp ecx,0x3B76FE
je damage
cmp ecx,0x3B77AA
je damage
jmp originalcode //If nothing is found everything runs as normal

damage:
push ebx
sub ebx,esi //I found that esi keeps the damage value during this so i just subract it again from the hp value (Double damage)
mov [eax+ecx],ebx
pop ebx //restore ebx, if i don't do this the game crashes again, i have to try if adding esi back again instead can work
add esp,18
jmp exit

originalcode:
mov [eax+ecx],ebx
add esp,18

exit:
jmp returnhere

"DOSBox.exe"+18EDA:
jmp newmem
nop
returnhere:


 
 
[DISABLE]
dealloc(newmem)
"DOSBox.exe"+18EDA:
mov [eax+ecx],ebx
add esp,18
//Alt: db 89 1C 08 83 C4 18
Sooo it probably is not efficent but it works and it's the best solution i came up with my knowledge and now i can move one to the random weapon thingy.
Thanks for all the help!

Post Reply

Who is online

Users browsing this forum: No registered users