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 


Cheat Engine Forum Index
PostGo back to topic
ParkourPenguin
I post too much
Reputation: 138
Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sun Apr 30, 2017 10:37 pm    Post subject:

GoreGrindGeek wrote:
However, it also made every critter invincible and not just the PC. I've tried dissecting the data structures for different critters, but they are identical except for Health and Psi values. What would the next step be if that is the case?

The first step would be to try to find another suitable injection point. Unfortunately, your goal seems to be to make the player incapable of taking damage, which means that single injection point is likely the only suitable one. Another injection point can still be used indirectly, but there are simpler solutions to try first.

The second solution would be to try to use the values in the registers when that instruction is executed. To check this, set a breakpoint on that instruction, do something in the game to trigger the breakpoint, and look at the registers to the right of the disassembler (top half of memory viewer). There might be something that can be used to differentiate players from enemies. For example, perhaps ecx is always 3 when the player takes damage, but it's something else when another entity takes damage. If something like this does exist, make sure it's consistent: changing levels, restarting the game, or rebooting your computer can change what values the game uses for some things.

The next step I would recommend for you, which you've partially done, would be to compare the values in the player's health structure against the values in other instances of that structure. I assume you've looked through the data in the structure itself and haven't found anything that can differentiate players from enemies. There isn't always something there, but there can be something in another region of memory being pointed to by a pointer in the structure (strings are pretty common). Expand pointers in the structures and try to find something there.

If you absolutely can't find anything, another solution would be to find the address of the player's health some other way and compare the address currently being accessed against it. A pointer to the player's health can be used, but finding a good pointer isn't always feasible. Instead, find an instruction that accesses an address in the same structure as the player's health and only that address. That instruction can be used as an ancillary injection point to acquire the address of the player's health, which can then be used in the main injection point. This topic covers how to find a pointer and how to create that ancillary injection point.


The previous solution should work in the vast majority of circumstances. The next two are a little more complicated and would work less frequently, but they involve a topic you didn't know that much about: the stack. Not the FPU stack, but the current thread's stack. It's important to know what that is before moving on.

With regards to assembly, the term "the stack" generally refers to an area of memory that is accessed like a stack (LIFO). The instructions push and pop respectively push a value onto the stack and pop a value off of the stack. The esp register always points to the top of the stack such that [esp] is the value on the top of the stack. The stack grows downward, meaning pushing a value onto the stack subtracts from esp and popping a value from the stack adds to esp. This may seem strange at first, but it's actually simpler than if it were the other way around. The following assembly code depicts this behaviour:
Code:
push eax
// is equivalent to:
sub esp,4
mov [esp],eax

pop eax
// is equivalent to:
mov eax,[esp]
add esp,4


By convention, the ebp register is used to point to the beginning of the current stack frame. Stack frames are used by functions (aka methods, procedures, or subroutines) to simplify accessing certain areas of the stack. Functions usually establish a stack frame at the beginning of the function and will tear down that stack frame when it returns. The concept of a stack frame is fundamentally high-level (relative to assembly), and there are no formal rules enforcing their use. As such, programs are free to use the ebp register for other purposes. This is common to see in smaller subroutines where establishing a stack frame wouldn't do anything significant. Regardless, stack frames are a widely used convention, so they're important to know about.

One feature of stack frames is that they standardize the way a function accesses parameters that are passed to it through the stack. Because the function will not modify ebp after establishing the stack frame, the parameters will always be a certain distance away from ebp. Take this C code for example:
Code:
void foo(int a, int b)
{
   int c = a + b;
   // other code...
}

int main(int argc, char *argv[])
{
   foo(6,7);
   return 0;
}

The assembly the compiler produces could look like this:
Code:
// x86 architecture; cdecl calling convention

foo:
  push ebp          // back up old stack frame
  mov ebp,esp       // establish new stack frame
  sub esp,10        // allocate space on the stack
  mov edx,[ebp+08]  // get first parameter (int a)
  mov eax,[ebp+0C]  // get second parameter (int b)
  add eax,edx       // add them together
  mov [ebp-04],eax  // store result on the stack
  // other code...
  mov esp,ebp       // tear down stack frame
  pop ebp           // restore old stack frame
  ret               // return

main:
  ...
  push 7      // push arguments in reverse order
  push 6      // ^
  call foo    // call function
  add esp,8   // clean up arguments from stack (cdecl calling convention)
  ...

A comprehensive overview of the stack, stack frames, and functions would take a fair bit of time, but I hope this terse description is an adequate introduction.

With regards to the original problem of differentiating the player from other entities, the stack could be checked like the registers were. Set a breakpoint on the instruction, do something in the game to trigger it, and copy the data in the stack into notepad or something. Do this for the player and several other entities, and check to see what's different. Once a breakpoint has been triggered, the stack can be viewed in the bottom right corner of the memory viewer by right clicking on the listview and selecting "Full stack." CE also gives a guess as to what the value type could be and the corresponding value at that address. The data can easily be copied by going to the address in the hex view (bottom half of memory viewer; left of the stack view) and copying the bytes. I'd only check the first few hundred bytes- after that, you probably won't find anything relevant.

Finally, backtracing is an option. I would've recommended this earlier if you were more experienced with assembly, but that doesn't seem to be the case. There might be a better injection point in a caller. For example, if one call is responsible for the player taking damage but not other entities, nullifying it will make the player not take damage without affecting other entities.

All of the above is just a few ways to solve this problem. I'm sure there are many others if you know enough and are creative enough.

PS: rep is restricted by post count IIRC. Don't worry about it. (and don't make useless posts to increase post count)
_________________
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
Post reviews:   Approve 1
Author Review
++METHOS
Review: Approve
Post reference:
ReviewPosted: Sun Apr 30, 2017 10:48 pm

Just because.
Back to top
View user's profile Send private message
Display:  
Cheat Engine Forum Index


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites