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 


Towns - Unit Owner Help

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
Ulic Qel-Droma
Newbie cheater
Reputation: 0

Joined: 13 Jul 2010
Posts: 15

PostPosted: Mon Nov 26, 2012 1:00 pm    Post subject: Towns - Unit Owner Help Reply with quote

I am attempting to use what I think is a unit owner id to write a script that applies only to my units and I have a few questions.

I'm playing around with Towns, for the uninitiated you have citizens who build your town but get tired and hungry over time and also have health. I'd like to set/freeze these values for all my citizens. I have the unit's structure mapped out and know the offsets for Current Health, Turns to Sleep, and Turns to Eat and with a little tweak of jgoemat's table (forum.cheatengine[dot]org/viewtopic.php?t=567707&sid=2a711eea06faa9213f5cb337afdf1f3c) to find the selected unit I can create a table that lets me edit the selected unit's values. The downside is that I have to do this again and again for each unit because as soon as I click a new unit the values for the previous unit obviously unfreeze.

I have found that what writes to the Health address when I take damage or the Turns to Sleep and Turns to Eat address when they decrease is always the same. I know there is a script I could write which would prevent the game from changing the values for my units but unfortunately I can't figure out what these opcodes are doing because I don't know Assembly. Can someone recommend a resource or help me decipher it?
Code:

036101C8 - 8B D0                 - mov edx,eax
036101CA - C1 EA 19              - shr edx,19
036101CD - 83 E2 01              - and edx,01
036101D0 - C1 E8 1C              - shr eax,1C
036101D3 - 83 E0 0F              - and eax,0F
036101D6 - 0F85 0C000000         - jne 036101E8
036101DC - 58                    - pop eax
036101DD - 59                    - pop ecx
036101DE - 3B 01                 - cmp eax,[ecx]
036101E0 - 88 04 19              - mov [ecx+ebx],al
036101E3 - E9 C8000000           - jmp 036102B0
036101E8 - 83 F8 03              - cmp eax,03  <-- Could this be checking for unit owner/type?  If so I am 3?
036101EB - 0F85 0C000000         - jne 036101FD
036101F1 - 58                    - pop eax
036101F2 - 59                    - pop ecx
036101F3 - 3B 01                 - cmp eax,[ecx]
 
036101F5 - 89 04 19              - mov [ecx+ebx],eax  <--Found writing to my health address. Could this be lowering my Health/decreasing Turns to Sleep/Eat
 
036101F8 - E9 B3000000           - jmp 036102B0
036101FD - 83 F8 07              - cmp eax,07
03610200 - 0F85 17000000         - jne 0361021D
03610206 - 58                    - pop eax
03610207 - 59                    - pop ecx
03610208 - 3B 01                 - cmp eax,[ecx]
0361020A - 89 04 19              - mov [ecx+ebx],eax
0361020D - C1 E9 09              - shr ecx,09
03610210 - C6 04 0D 00503D4B 00  - mov byte ptr [ecx+4B3D5000],00
03610218 - E9 93000000           - jmp 036102B0
0361021D - 83 F8 01              - cmp eax,01
03610220 - 0F85 0D000000         - jne 03610233
03610226 - 58                    - pop eax
03610227 - 59                    - pop ecx
03610228 - 3B 01                 - cmp eax,[ecx]
0361022A - 66 89 04 19           - mov [ecx+ebx],ax


If I'm right and "mov [ecx+ebx],eax" is responsible for me taking damage, turns to sleep decreasing, etc. in the script I write should I just "nop" "mov [ecx+ebx],eax" when active or is there a better way to handle this?

So…

Am I on the right track?

Does it seem like I’m reading Assembly right there?

Any advice on the script I ultimately write?

Thanks in advance to anyone who responds.
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Tue Nov 27, 2012 12:21 pm    Post subject: Re: Towns - Unit Owner Help Reply with quote

Ulic Qel-Droma wrote:
I'm playing around with Towns
If you're speaking about this town: http://www.townsgame.com/ then I recommend getting a java/.jar decompiler, and maybe a java source code editor if notepad is not enough. Unless the source code is obfuscated modding the game is way easier the hacking it with cheat engine.

Ulic Qel-Droma wrote:
I can't figure out what these opcodes are doing because I don't know Assembly. Can someone recommend a resource or help me decipher it?
It's not really noob-friendly, but whenever I have a doubt about what an instruction does, I check Intel® 64 and A-32 Architectures Software Developer’s Manual. It's the official definition of each x86 opcode.

Ulic Qel-Droma wrote:
If I'm right and "mov [ecx+ebx],eax" is responsible for me taking damage, turns to sleep decreasing, etc. in the script I write should I just "nop" "mov [ecx+ebx],eax" when active or is there a better way to handle this?
At the left of mov [ecx+ebx],eax you can see 3 pairs of numbers, that means your instruction takes 3 bytes, so you should write 3 nops. Your script would then be:
Code:
[enable]
036101F5:
nop
nop
nop

[disable]
036101F5:
mov [ecx+ebx],eax
That's for how to use the nop instruction.
But your game is in java, which means [blah blah blah] that your code code will most likely NOT be at 036101F5 the next time you restart your game simple way to check: in the memory editor, go to view->show module addresses. If each address becomes like Something.exeOR.dll+12345 then aobscans are not mandatory. Anyway, I bet the address display will not change so you should use an aobscan (scan for code signature). Your script would then look like this:
Code:
[enable]
label(CodeToPatch)
aobscan(CodeToPatch_aob,89 04 19 E9 B3 00 00 00 83 F8 07)
registersymbol(CodeToPatch)

CodeToPatch_aob:
CodeToPatch:
nop
nop
nop

[disable]
CodeToPatch:
mov [ecx+ebx],eax
unregistersymbol(CodeToPatch)
As for the bunch of numbers on the aobscan line, it's just the bytes at the left of the instruction you want to modify + those of the few next instructions. Just pick enough so that the signature is unique/there is only one match. That's for the aobscan...

...but actually if you disable this mov I guess your game will not work as expected. Perhaps it'll crash, or at least lots of things won't work because this single instruction looks like it handle lots of stuff: you said health, food and sleep, but it probably does much more. To quickly test that, right click on "mov [ecx+ebx],eax"->replace by code that does nothing. Use the code list (main window->advanced options) when you want to restore the mov.

Ulic Qel-Droma wrote:
Am I on the right track?
If it were a typical game, I'd say yes, but since it's in java, go for the source code decompiler.

Ulic Qel-Droma wrote:
Does it seem like I’m reading Assembly right there?
Yes.
Back to top
View user's profile Send private message
Ulic Qel-Droma
Newbie cheater
Reputation: 0

Joined: 13 Jul 2010
Posts: 15

PostPosted: Wed Nov 28, 2012 6:48 pm    Post subject: Reply with quote

Hey Gniarf thanks.

Quote:
If you're speaking about this town: www[DOT]townsgame[DOT]com/ then I recommend getting a java/.jar decompiler

I was talking about this game. I'll look into a decompiler.
Quote:
Intel® 64 and A-32 Architectures Software Developer’s Manual.

Thanks I'll keep it in mind as a reference.
Quote:
...but actually if you disable this mov I guess your game will not work as expected

Nopping the region does kill the game so I guess I'll stick to manually messing with it until I can look into a decompiler

However I have one more question...

I have a script using the aobscan command to return the selected unit which I then use to create pointers to get that unit's health etc. which works most of the time, (see below) however occasionally it doesn't because when I search for the array it sometimes returns two distinct addresses relatively close together instead of one. I've tried comparing the two regions around the addresses and they are identical for many many many lines preceding and proceeding the target address so I don't really know how to handle this.
I thought maybe I could somehow limit the region it started and/or stopped searching in as it always seems to be the second address in these cases but sometimes the second address will appear in the same region as the first address did in a previous scan so....
When this come up I've been manually cheating it by searching for the array and manually inserting that address into the script.
Code:
[ENABLE]
alloc(newmem,1024)

aobscan(aobHover,8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00)

//=========================================
// Declarations
label(injectHover)
label(_Hover)
label(_returnHover)
label(pHoverBase)
label(pHoverStats)

registersymbol(injectHover)
registersymbol(pHoverBase)
registersymbol(pHoverStats)

//=========================================
// Code
newmem:

_Hover:
  mov esi,[edx+000000BC] // original code
  mov [pHoverBase],edx
  mov [pHoverStats],esi

  jmp _returnHover

//=========================================
// Variables
pHoverBase:
  dd 0
pHoverStats:
  dd 0

//=========================================
// Hacking Point
aobHover+7:
//????????+7:
injectHover:
  jmp _Hover
  nop
_returnHover:

[DISABLE]
injectHover:
  // ALT: mov esi,[edx+000000BC]
  db 8B B2 BC 00 00 00

unregistersymbol(injectHover)
unregistersymbol(pHoverBase)
unregistersymbol(pHoverStats)

dealloc(newmem)


Any general advice here or is this an odd case because it's a Java game?

Thanks again.
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Wed Nov 28, 2012 8:15 pm    Post subject: Reply with quote

There are actually 2 versions of the aobscan:
-the auto assembler command that you know.
-the lua version, that can returns multiple results (sample script).

I suggest:
1-writing a lua function (ex: MyAobScan) that will do the aobscan and put a registered label at the 2nd match if any, otherwise the first.
2-Then using an AA script like:
(changes marked with //*******)
Code:
[enable]
alloc(newmem,1024)

//aobscan(aobHover,8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00)
luacall(MyAobScan) //*******

//=========================================
// Declarations
label(injectHover)
label(_Hover)
label(_returnHover)
label(pHoverBase)
label(pHoverStats)

registersymbol(injectHover)
registersymbol(pHoverBase)
registersymbol(pHoverStats)

//=========================================
// Code
newmem:

_Hover:
  mov esi,[edx+000000BC] // original code
  mov [pHoverBase],edx
  mov [pHoverStats],esi

  jmp _returnHover

//=========================================
// Variables
pHoverBase:
  dd 0
pHoverStats:
  dd 0

//=========================================
// Hacking Point
//aobHover+7:
RegisteredAOBScanResult+7: //*******
//????????+7:
injectHover:
  jmp _Hover
  nop
_returnHover:

[DISABLE]
injectHover:
  // ALT: mov esi,[edx+000000BC]
  db 8B B2 BC 00 00 00

unregistersymbol(injectHover)
unregistersymbol(pHoverBase)
unregistersymbol(pHoverStats)
unregistersymbol(RegisteredAOBScanResult) //*******

dealloc(newmem)

3-You may need to put the luacall line in a separate AA script if it is not executed before the rest of the script.
Back to top
View user's profile Send private message
Ulic Qel-Droma
Newbie cheater
Reputation: 0

Joined: 13 Jul 2010
Posts: 15

PostPosted: Wed Nov 28, 2012 11:01 pm    Post subject: Reply with quote

That's super helpful thanks. I've been trying to mess around with this but sadly Dark Byte's table for the tutorial never got reposted after the forum crash and I'm having some trouble...

First I run the lua script with the "LUA Engine" option in the memory viewer...

Here's the script almost verbatim Dark Byte's sample

Code:
function _memrec_myCheat_activating(mr)
  results=AOBScan("8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00")  --Saves my AOBScan to "results"
  if (results~=nil) then  --If "results" does not equal nil then...
    count=stringlist_getCount(results)  --Count the results
    if (count>1) then  --If the count is greater than 1 then...
      address=stringlist_getString(results,1)  -- Take the second address in "results." ,0 is the first
      script=[[
        label(aobresult_myCheat)  --Label the second address "aobresult_myCheat"
        registersymbol(aobresult_myCheat)  -- Register the symbol "aobresult_myCheat"
        ]]..address..[[:  --?????
        aobresult_myCheat:
        ]]
      autoAssemble(script);
    end
    object_destroy(results)  --Destroys saved AOBScan
    results=nil  --Sets "results" equal" to nil
  end
end


I'm on board until here:
Code:
 ]]..address..[[:  --?????
        aobresult_myCheat:
        ]]
      autoAssemble(script);

What's happening there?

Second do I run this manually each time I start up cheat engine?

Lastly, I'm having trouble with the script you suggested. Line 5 is failing.
Code:
luacall(aobresult_myCheat)

It says "Error in line 5 (luacall(aobresult_myCheat)) :[string "aobresult_myCheat"]1: '=' expected near '<eof>'"
What's that about?

Thanks again.
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Thu Nov 29, 2012 3:38 am    Post subject: Reply with quote

Ulic Qel-Droma wrote:
I'm on board until here:
Code:
 ]]..address..[[:  --?????
        aobresult_myCheat:
        ]]
      autoAssemble(script);

What's happening there?
It's some string concatenation. Lets say that address contains 12345678, this line and the few around are making the variable script contain:
Code:
label(aobresult_myCheat)  --Label the second address "aobresult_myCheat"
registersymbol(aobresult_myCheat)  -- Register the symbol "aobresult_myCheat"
12345678:
aobresult_myCheat:
Does look like a simple auto assembler script, heh? Well, the next line is used to run that small script.

Ulic Qel-Droma wrote:
Second do I run this manually each time I start up cheat engine?
No, you only need to run it each time you use this hack for Towns, or after each modification.

Note: the big "execute" button at the bottom of the lua window will compile your function, NOT execute it.

Ulic Qel-Droma wrote:
Lastly, I'm having trouble with the script you suggested. Line 5 is failing.
Code:
luacall(aobresult_myCheat)

It says "Error in line 5 (luacall(aobresult_myCheat)) :[string "aobresult_myCheat"]1: '=' expected near '<eof>'"
What's that about?
Luacall is use to run a lua FUNCTION, so you should past the name of the function you created, _memrec_myCheat_activating, in your case. You'll probably need to remove the "mr" parameter from the function declaration if you want to use this function through luacall.
Back to top
View user's profile Send private message
Ulic Qel-Droma
Newbie cheater
Reputation: 0

Joined: 13 Jul 2010
Posts: 15

PostPosted: Thu Nov 29, 2012 8:21 pm    Post subject: Reply with quote

Super cool thanks.
For the record I'll post my final lua script and table here. Really the only things of value in the table are Current Health, Happiness, Turns to Eat, Turns to Sleep, and Experience. If anyone ends up using it I'd just delete the others but I left them there for completeness anyway. The table is currently set up with aobscan rather than lua so if you want lua just run the lua script and delete out/add the comments in assembler script

lua script:
Code:
function _memrec_myCheat_activating()
  results=AOBScan("8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00")
  if (results~=nil) then
    count=stringlist_getCount(results)
    if (count>1) then
      address=stringlist_getString(results,1)
      script=[[
        label(aobresult_myCheat)
        registersymbol(aobresult_myCheat)
        ]]..address..[[:
        aobresult_myCheat:
        ]]
      autoAssemble(script);
    end
    object_destroy(results)
    results=nil
  end
end



Towns - v8a Full.CT
 Description:

Download
 Filename:  Towns - v8a Full.CT
 Filesize:  6.73 KB
 Downloaded:  1519 Time(s)


Towns - v8a.lua
 Description:

Download
 Filename:  Towns - v8a.lua
 Filesize:  492 Bytes
 Downloaded:  910 Time(s)

Back to top
View user's profile Send private message
Ulic Qel-Droma
Newbie cheater
Reputation: 0

Joined: 13 Jul 2010
Posts: 15

PostPosted: Sat Dec 01, 2012 10:24 am    Post subject: Reply with quote

After some more playing I've found that sometimes there's only one address, sometimes there are two, and sometimes there are three. I modified the script to grab the third address if it's there:
Code:
function _memrec_myCheat_activating()
  results=AOBScan("8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00")
  if (results~=nil) then
    count=stringlist_getCount(results)
    if (count>1) then
      if (count==3) then
      address=stringlist_getString(results,2) else
        if (count==2) then
        address=stringlist_getString(results,1)
        end
      end
      script=[[
        label(aobresult_myCheat)
        registersymbol(aobresult_myCheat)
        ]]..address..[[:
        aobresult_myCheat:
        ]]
      autoAssemble(script);
    end
    object_destroy(results)
    results=nil
  end
end

However I'm worried that this will keep going on forever. As it always seems to be the last address what I really want is the lua script to just grab the final address in "results." Anyone have advice on how to do that?
Back to top
View user's profile Send private message
Gniarf
Grandmaster Cheater Supreme
Reputation: 43

Joined: 12 Mar 2012
Posts: 1285

PostPosted: Mon Dec 03, 2012 12:29 pm    Post subject: Reply with quote

Ulic Qel-Droma wrote:
what I really want is the lua script to just grab the final address in "results." Anyone have advice on how to do that?
Try something like that:

Code:
function _memrec_myCheat_activating()
  results=AOBScan("8B 94 24 ?? 01 00 00 8B B2 BC 00 00 00")
  if (results~=nil) then
    count=stringlist_getCount(results)
    address=stringlist_getString(results,count-1) -- <-most important modification here
    script=[[
      label(aobresult_myCheat)
      registersymbol(aobresult_myCheat)
      ]]..address..[[:
      aobresult_myCheat:
      ]]
    autoAssemble(script);
    object_destroy(results)
  end
  results=nil
end
Back to top
View user's profile Send private message
frenchiveruti
Cheater
Reputation: 0

Joined: 07 Jun 2009
Posts: 35

PostPosted: Mon Mar 25, 2013 3:08 pm    Post subject: YOU ARE AWESOME! Reply with quote

Your cheat Table Still works for the version 11a of Towns Very Happy
Also, maybe you could check it out, or even make a trainer of this game, because you script works perfect!
I have to say you, THANKS A LOT!

_________________
Acknowledgeable enough.
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking 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