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 


Condemned health script not working

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
mouser
Advanced Cheater
Reputation: 0

Joined: 08 Mar 2015
Posts: 50

PostPosted: Mon Mar 21, 2016 2:37 pm    Post subject: Condemned health script not working Reply with quote

It's been quite a while since the last time I was here, I need some help in understanding because I'm still a terrible noob.

I'm trying different things with Condemned Criminal Origins, one of it is health. I've found the address where the health is stored, it's 200 as float. I lock the value and I don't lose any health and enemies go down as usual. I've pointerscanned it to a level 5 pointer, it's not very reliable. Depending on different levels and saves it may pop up with the correct address or not. Maybe I borked the pointerscan or 5 level/depth is not enough. I figured I want to AOB scan this anyway so I found out what writes to the adress and I came up with the script below.

Here is the opcode
Code:
fstp dword ptr [esi+74]



Here is the AOB script

Code:
[ENABLE]

aobscanmodule(hp_aob,GameServer.dll,D9 5E 74 76 07) // should be unique
alloc(newmem,$1000)

label(code)
label(return)

newmem:

code:

  fstp dword ptr [esi+74]
mov [esi+74],(float)200
  jna GameServer.DEditGetOcclusionInfo+1F90
  jmp return

hp_aob:
  jmp code
return:
registersymbol(hp_aob)

[DISABLE]

hp_aob:
  db D9 5E 74 76 07

unregistersymbol(hp_aob)
dealloc(newmem)


I've added
Code:
mov [esi+74],(float)200
as I thought this would put 200 into the address where the value is stored, similar to locking the value at that address.

I don't know why
Code:
jna GameServer.DEditGetOcclusionInfo+1F90
is part of the script but I assume this causes problems, because when I enable the script I don't lose any help, as expected. But the enemies now don't lose any help either. I believe it somehow breaks that section of code when I enable the script. When I disable the script, I start losing health again, but the enemies stay invincible. I have to die and/or reload the save to return to the normal behaviour. I Assume that jump if not above operand is responsible for it, but I'm mentally blocked... don't know how to check or fix this.

How do I take the jna out of the AOB code? I've tried another script where I delete the 2 bytes 76 07 and instead used 4 bytes in front of the opcode I want to change (and adding +4 to the jump so that Cheat Engine knows where to start the injection and commented out the jna line (since I copy/pasted the other script).

Looks like this:
Code:


[ENABLE]

aobscanmodule(hp_aob,GameServer.dll,D8 64 24 30 D9 5E 74) // should be unique
alloc(newmem,$1000)

label(code)
label(return)

newmem:

code:

  fstp dword ptr [esi+74]
mov [esi+74],(float)200
// jna GameServer.DEditGetOcclusionInfo+1F90
  jmp return

hp_aob+4:
  jmp code
return:
registersymbol(hp_aob)

[DISABLE]

hp_aob:
  db D8 64 24 30 D9 5E 74

unregistersymbol(hp_aob)
dealloc(newmem)


but this still takes the next opcode into the script/jump to the new allocated memory. I must be missing something obvious but I can't see what.

Has anyone an Idea on how to change the opcode in a different/better way so it is less prone to side effects?

Below is a screenshot of the code section where the health opcode is.

(btw I just read about Geri, the guy was extremely helpful and good at Cheat Engine. I didn't know him personally but it still came as a shock reading that he is gone, RIP)



Condemned Original Code.JPG
 Description:
Code Section
 Filesize:  83.75 KB
 Viewed:  8331 Time(s)

Condemned Original Code.JPG


Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4719

PostPosted: Mon Mar 21, 2016 2:58 pm    Post subject: Reply with quote

You shouldn't override the jna instruction in the jmp to your code. Start your hook at fsub dword ptr[esp+30] instead. Also note that the test eax,eax instruction sets flags for the jna instruction, so if you do use anything that modifies any flags in your code, make sure to restore those flags (pushfd/popfd or rewrite test eax,eax before the jmp back).

However, the reason why it's working for enemies too may simply be because that section of asm is run when the health of anything (not just your player) should change. See this topic for some tips on dealing with shared code.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
mouser
Advanced Cheater
Reputation: 0

Joined: 08 Mar 2015
Posts: 50

PostPosted: Mon Mar 21, 2016 4:15 pm    Post subject: Reply with quote

Thanks for the advice.

I have 2 questions about what you've wrote if you don't mind, I'm not really that familiar with AA so I didn't quite understand it completely.

1. If you look at the second AOB script I posted, there I start at the address you have suggested, then go forward 4 bytes and inject there. When I watch the memory region there and follow the jump after I activated the script, it still takes the jna with it into the allocated memory. I thought that only the specific code will be taken into consideration that is declared by the AOB and there is no additional bytes after the instruciton I targeted and I didn't have it in the code section in the script.
I don't understand why it's still there? Can you see why this is still happening when looking at the script?

2. The test eax,eax instruction, how can one see that there are flags set for the jna instruction? Is this just common knowledge or can I see it when looking at the code section? I wouldn't have thought that it would have anything to do with the jna as eax is not written in the instruction itself (or at least not in the line where jna is at)

3. This question must read very stupid lol.. and maybe it is but from the screenshot I've posted, can I see where the Instruction set starts and ends? How can you tell where one set is ending and the next is beginning? Is it even possible by just looking at it? I confuse opcodes and instructions/Instruction sets on a regular basis I think, which leads to confusion for everybody.

Thanks for the reply, I'm going to read up on the link now and try to write a better script tomorrow and report back.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4719

PostPosted: Mon Mar 21, 2016 6:43 pm    Post subject: Reply with quote

1. Ok, this is what's going on: you're searching for the AoB signature and it returns the address at ...+1F80. You go 4 bytes forward to ...+1F84 and write the jmp to your code there. Because you went 4 bytes forward, it is now overriding the jna (the instruction at ...+1F84 isn't long enough so it takes the next one too). Your jmp is overriding the jna because you told it to. You didn't change your injection point at all; the only thing you changed was how you found the injection point.

2. The sole purpose of the test instruction is to set flags. This is usually done for a jcc or cmovcc instruction. In this case, it's a jna (one of the jcc instructions). Usually, if you see a jcc instruction, then the last instruction prior to that which modifies the eflags register is usually responsible for determining whether or not the jcc instruction should branch. In this case, fsub and fadd don't modify eflags at all, and since the sole purpose of the test instruction is to modify eflags, it's safe to assume that the test instruction sets flags specifically for the jna instruction.

3. I don't believe you're using the term "instruction set" correctly, so I'll just explain everything.

An "instruction" is a single operation a processor performs. It has two main representations: the mnemonic and the machine code. The mnemonic is what is easier for humans to understand- it is a string of text such as test eax,eax. The machine code is the bytes that a computer understands. The machine code of the test eax,eax instruction would be 85 C0.

An instruction's machine code has two main parts to it: the opcode and the operands. The opcode is the bytes that determine what type of action the processor should perform. For instance, should it move data, add two numbers, push something onto the stack, or, in this case, test two numbers against each other. The operands are the bytes that represent information needed by the opcode. In this case, what the test instruction should be testing.

So, with regards to the test eax,eax instruction, 85 is the opcode that tells the processor it should be testing two registers, and C0 is the operand that tells the processor it should be testing eax against itself.

The term "instruction set" refers to all the instructions a processor can perform and everything involved in using said instructions (i.e. registers, native data types, addressing modes, interrupts & exceptions, etc.).

With regards to the size of instructions, CE presents all the bytes that make up an instruction within the disassembler directly left of the mnemonic and directly right of its location in memory. All you need to do is count them to see how many bytes they take up in memory.

In 32-bit processes, non-short jumps requires 5 bytes of space: 1 byte for the opcode and 4 bytes for the address it should jump to. If CE sees a single instruction is not enough for a jump, it will also override the next one, and continue until it has at least 5 bytes available. If it partially overrides an instruction, it will replace the remaining bytes of the instruction with NOPs to prevent it from looking like gibberish.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Mon Mar 21, 2016 7:03 pm    Post subject: Reply with quote

Try finding out what accesses your health, instead of what writes to it.
Games normally have player-specific code due to the user interface or similar reasons.
If you can find an instruction that only touches the player's health, save the base address for use in your health script.
For example, lets say you save the address to a custom variable called player_ptr, your health script can be:
Code:
[ENABLE]
aobscanmodule(hp_aob,GameServer.dll,D8 64 24 30 D9 5E 74)
alloc(newmem,$1000)

label(code)
label(return)

newmem:
  cmp esi,[player_ptr]
  je code
  fsub dword ptr [esp+30]
code:
  fstp dword ptr [esi+74]
  test eax,eax
  jmp return

hp_aob:
  jmp newmem
  nop
  nop
return:
registersymbol(hp_aob)

[DISABLE]
hp_aob:
  db D8 64 24 30 D9 5E 74
unregistersymbol(hp_aob)
dealloc(newmem)
Back to top
View user's profile Send private message
mouser
Advanced Cheater
Reputation: 0

Joined: 08 Mar 2015
Posts: 50

PostPosted: Tue Mar 22, 2016 3:55 pm    Post subject: Reply with quote

I followed Rydian's guide and I found a single address that accesses my health, I was able to AOB that and apply the same code (insert 200 as float) and now everything works as I wanted it to without strange side effects. Thanks for the tipps and also for the explanations ParkourPenguin and Zanzer, I try to remember them for further CE experiments.

And Zanzer, while I now have what I want, I still find your code template interesting and will try to get it to work also, thanks for that. But I have to admit that I don't understand it completely. Once I've found the playerbase (player stats structure), do I need to aob scan that in the same script or another script. The code you've written is referencing it but it is not scanning for it. I maybe just not seeing why it works because of my lack of knowledge here.
The code in your newmem section, can you explain to me in detail what it does and how you've come to think that this will work?
I really want to understand it in detail:)
Back to top
View user's profile Send private message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Tue Mar 22, 2016 5:14 pm    Post subject: Reply with quote

You would have to use two injections.
The new one you found is likely referencing the same base address of the player structure.
Inside that new injection you would declare and set the value of [player_ptr].

In my code, it compares the value you stored in [player_ptr] with ESI.
At this injection, ESI is holding the base address of the player structure.
If they equal, jump (JE) past the instruction which subtracts from the health value.
Then proceed to pop the value (unchanged) into the unit's health address.

If ESI and [player_ptr] do not equal, then it is an enemy, so we want to do the FSUB as normal.
Back to top
View user's profile Send private message
mouser
Advanced Cheater
Reputation: 0

Joined: 08 Mar 2015
Posts: 50

PostPosted: Sat Mar 26, 2016 12:30 pm    Post subject: Reply with quote

Thanks for the explanation, I happen to found a youtube video from another forum member that is basically exactly displaying what you have described.

https://www.youtube.com/watch?v=kpSRUJfaT1o

Very cool, I kinda still lack the creativity to write scripts in different ways, I need more practise Very Happy
Back to top
View user's profile Send private message
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