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 


Having trouble with a reasonably simple AoB injection

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
GoreGrindGeek
How do I cheat?
Reputation: 0

Joined: 30 Apr 2017
Posts: 5

PostPosted: Sun Apr 30, 2017 6:44 am    Post subject: Having trouble with a reasonably simple AoB injection Reply with quote

G'day, everyone.

I've completed the CheatEngine tutorial a number of times, only referring to online sources for the very last step, and I've tried searching for a solution to my problem prior to registering here to bother other people. I've also wasted 6 hours trying to solve it, but either I'm too dumb or too tired. Years of "high-level" language experience haven't helped me much either. Could you please help me?

I am trying to construct a GodMode cheat for the Health and Psi values in a game called UnderRail which uses the current .NET technology, so addresses and pointers change on every start-up (and mid-game as well!). As far as I know, only AoB can help in this instance. I have located the line of code responsible for storing the changed Psi value (I've started off with Psi to move on to Health at a later stage), but it's an fstp instruction, so I can't simply remove it. I have no bloody idea what the rest of the code does, so I've tried some random fadd-ing and fmul-ling (Psi and Health are both floats), but that did nothing.

Code:
1B2C993C - 56                    - push esi
1B2C993D - 53                    - push ebx
1B2C993E - 83 EC 08              - sub esp,08 { 8 }
1B2C9941 - 8B F1                 - mov esi,ecx
1B2C9943 - D9 46 18              - fld dword ptr [esi+18]
1B2C9946 - D9 5D F0              - fstp dword ptr [ebp-10]
1B2C9949 - D9 45 08              - fld dword ptr [ebp+08]
>> 1B2C994C - D9 5E 18              - fstp dword ptr [esi+18]
1B2C994F - E8 5C1C6D52           - call mscorlib.ni.dll+B7B5B0

Bytes up until 5C1C6D52 are always the same whenever Psi Energy is expended (I have not paid too much attention to bytes before the push esi instruction though). Instruction writing the value (or whatever the hell it is fstp does - I certainly don't have a clue) is highlighted with a ">>".
How can I possibly affect the code so that the Psi value stays the same, and what exactly does the code do? I get lost in all the registers.

Thank you in advance.

Update: I've tried reading multiple manuals on the fld and fstp instructions, but I still have absolutely no idea of what it is they do. Are those things purposefully convoluted by backreferences to other functions and/or registers and/or predefined variables that make absolutely no sense? I cannot read the code if I cannot make sense of the manual on it :-\
How does the stack operate? How do I know and trace the values of the various st(N)'s? What are they? I've worked with stacks beforehand, but they were always clearly structured and easily traversable. I cannot afford reading an entire manual on assembly at the moment, especially when the cause is cheating at a computer game.
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

Joined: 06 Jul 2014
Posts: 1748
Location: Arcadian Suburbia

PostPosted: Sun Apr 30, 2017 9:25 am    Post subject: Reply with quote

The FPU is a collection of 8 registers that are accessed like a stack. You can push floats onto the FPU stack (henceforth just "stack") and pop them off in a LIFO manner. All 8 floats on the stack can be accessed individually by some instructions via the identifier ST(N), where N is an integer between 0 (top of the stack) and 7 (bottom of the stack).

Common instructions include:
  • fst - stores the top element of the stack into the specified memory address or stack position. The top element is not removed from the stack.
  • fstp - like fst, but pops the top element from the stack after the store.
  • fld - pushes a value onto the stack.

So, what these two instructions do is fairly simple:
Code:
1B2C9949 - D9 45 08  -  fld dword ptr [ebp+08]
1B2C994C - D9 5E 18  -  fstp dword ptr [esi+18]

The first instruction pushes the float at the address ebp+08 onto the stack, and the second stores that same value at the address esi+18 and pops it off of the stack.

In this case, the easiest way to nullify the effects of the fstp instruction would be to replace both it and fld instruction before it with NOP instructions.
Code:
1B2C9949:  // replace address w/ AoB scan
  db 90 90 90 90 90 90
  // 0x90 is the opcode for NOP


Sometimes, the fstp instruction is the only one that is easily modified. In those cases, the simplest way to nullify the effects of the store would be to replace the fstp with the instruction fstp st(0). That instruction will store the value at the top of the stack into st(0) and pop the value from the stack. Since st(0) is already the top of the stack, the store won't do anything, and the value will still be removed from the stack.

_________________
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
sbryzl
Advanced Cheater
Reputation: 3

Joined: 25 Jul 2016
Posts: 97

PostPosted: Sun Apr 30, 2017 9:25 am    Post subject: Reply with quote

fld loads a value on top of the fpu stack. fstp moves the value into a memory location and removes the value from the top of the fpu stack. If it were just fst then the value would remain on top of the fpu stack after it is moved to the memory location. ebp is a location in memory and it is a base pointer for another stack.

Anyway your code shows a value being loaded onto the fpu stack then moved into a memory location. It's basically using the fpu as an extra register. The fld and fstp instructions work in unison. If you preclude both with nops then there would be no change to your value. If you nop out only one then it will throw off the fpu stack. If you replace both with a mov immediate value to your memory location (esi+1Cool then you could put whatever you want there.
Back to top
View user's profile Send private message
GoreGrindGeek
How do I cheat?
Reputation: 0

Joined: 30 Apr 2017
Posts: 5

PostPosted: Sun Apr 30, 2017 6:25 pm    Post subject: Reply with quote

ParkourPenguin wrote:
The FPU is a collection of 8 registers that are accessed like a stack. You can push floats onto the FPU stack (henceforth just "stack") and pop them off in a LIFO manner. All 8 floats on the stack can be accessed individually by some instructions via the identifier ST(N), where N is an integer between 0 (top of the stack) and 7 (bottom of the stack).

Common instructions include:
  • fst - stores the top element of the stack into the specified memory address or stack position. The top element is not removed from the stack.
  • fstp - like fst, but pops the top element from the stack after the store.
  • fld - pushes a value onto the stack.
Thank you so much! I couldn't find any LIFO/FIFO information online, and that statement already has cleared things up immensely.

ParkourPenguin wrote:
In this case, the easiest way to nullify the effects of the fstp instruction would be to replace both it and fld instruction before it with NOP instructions.
Code:
1B2C9949:  // replace address w/ AoB scan
  db 90 90 90 90 90 90
  // 0x90 is the opcode for NOP


Sometimes, the fstp instruction is the only one that is easily modified. In those cases, the simplest way to nullify the effects of the store would be to replace the fstp with the instruction fstp st(0). That instruction will store the value at the top of the stack into st(0) and pop the value from the stack. Since st(0) is already the top of the stack, the store won't do anything, and the value will still be removed from the stack.
Yes, especially if it's not an x86 set of instructions where 0x90 is not an opcode for NOP (thankfully, in my case it is).
Your solution worked well, thank you. 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? Should I take a look at what ebp might be from [ebp+08]?

sbryzl wrote:
ebp is a location in memory and it is a base pointer for another stack.
How do you know and what exactly do you mean by "another stack"? So far, only FPU has been mentioned. Isn't ebp just a register?
sbryzl wrote:
If you nop out only one then it will throw off the fpu stack.
Crashing the game, yes.
sbryzl wrote:
If you replace both with a mov immediate value to your memory location [esi+18]. Cool then you could put whatever you want there.
Why not just the first one? I understand the error of my ways now though: I have been trying to set the latter instead of setting the first (that resulted in crashes as well).
----
Thank you!
How would I go about increasing your reputation? Or is that option only available after a certain period of time has passed after the registration?
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

Joined: 06 Jul 2014
Posts: 1748
Location: Arcadian Suburbia

PostPosted: Sun Apr 30, 2017 10:37 pm    Post subject: This post has 1 review(s) Reply with quote

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
GoreGrindGeek
How do I cheat?
Reputation: 0

Joined: 30 Apr 2017
Posts: 5

PostPosted: Mon May 01, 2017 4:41 am    Post subject: Reply with quote

ParkourPenguin wrote:
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.
I'm more than happy to add the Health/Psi value back after it has been subtracted (meaning that a hit resulting in more hitpoints than a character has would still kill him), but I couldn't really find the point of subtraction when looking at the code, and I would still need to figure out a way to differentiate between friend and foe.

ParkourPenguin wrote:
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
Unfortunately, that made my computer freeze, and I had to restart the system. I've tried setting a breakpoint on the previous instruction, but that had the same result.

ParkourPenguin wrote:
Expand pointers in the structures and try to find something there.
Did that before, did that again... Some of the pointers don't expand at all, and the expandable pointers point to the same values. Something tells me that I am using an incorrect offset though. Oh well. I've tried different offsets (going in 32-bit increments), but the structure makes no sense to me whatsoever, and I seriously doubt I am looking at it properly. The one in the tutorial was so much simpler.

ParkourPenguin wrote:
find an instruction that accesses an address in the same structure as the player's health and only that address
Like experience points? Because critters don't have them? I can't be certain if it's part of the same structure, but I'll take a look.

ParkourPenguin wrote:
This topic covers how to find a pointer and how to create that ancillary injection point.
Pointer scanning is the first thing I've tried. The pointers I found kept on ceasing to work or would start "twtching" (the address would change from XXXXXXXX to ???????? each second), which is when I've stumbled upon another tutorial by Rydian which mentioned that modern .NET games recompile on each location and/or restart of the game, so I've started looking into AoB injections instead. However, I have not tried scanning for a particular offset, so I'll give that method another go. Huh. This method narrowed my results down to 2 after just 2 scans! I would get hundreds after 4 scans beforehand. Wow. What do the different offsets represent in the pointer scan results? Mine are produced by the same .dll, and their offsets are the same except for Offset 0. Scan 3 returned no results at all, however. Silly XNA framework...
Oh well. Second method. The "unique" instruction for reading experience points (or whatever it is it does to them with a 1 millisecond timeout) is right after a jnl instruction and looks all weird:
Code:
a75::y4 - D9 81 3C010000        - fld dword ptr [ecx+0000013C]
I already knew the player array (?) had Health stored at offset 4, Psi Energy - at offset 18 and Experience - at offset 13C. Hmm. Apparently not. The structure found by deducting 13C from the Experience address is very different compared to the one I saw when performing a similar operation on Health. It still has hundreds of values and pointers in it, some of them unexpandable as well. The structures a lot of those pointers point to are identical (in terms of values stored). The results remind me a lot of code obfuscation (pointers called a, aa, ab, cc, etc.).
All the functions I found accessed a number of addresses with different values, so this method seems to not be applicable either. Maybe critters' stats are a single dynamic array in this game?
The third method in this manual looks very promising, actually, and very close to what I was searching for initially. Not sure I can read memory view all too well though: I have almost no idea what the column and row names stand for. No... I cannot find the base of the structure. The delta between Health and Psi seems to change after restart. I'm starting to lose interest in the game, to be honest, as I have spent the majority of my spare time in the same in-game locations the past few days, trying to figure this out.

ParkourPenguin wrote:
the current thread's stack
Does assembly support multithreading? I guess I really should not be a developer, given how much stuff I don't know (that I should).

ParkourPenguin wrote:
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
That's an excellent example, thank you. Why exactly is the number 4 subtracted from/added to esp? Is there something magical about it? Oh, read your next example, and, apparently, 4 is just the number of bytes allocated in this instance (no idea why allocation has such a weird syntactical structure, but I'll just go with it for the time being).

ParkourPenguin wrote:
Regardless, stack frames are a widely used convention, so they're important to know about.
So what exactly is a stack frame? Is it a pointer to a particular item within the stack? Wouldn't that make the stack... a linked list of some kind? I thought assembly was more primitive than that and didn't store any internal pointers within stacks. Or am I completely missing your point?

ParkourPenguin wrote:
The assembly the compiler produces could look like this
I am very grateful for the C example you've provided (finally, something I can read), but I'm not quite sure how you calculated the offsets for its assembly representation (I have never done anything more complex than implementing AES in terms of bitwise operations). These days they don't teach you what's happening behind the scenes, so my knowledge with regard to those computations is childlike at best.
So labels can actually be called like functions... Interesting.

ParkourPenguin wrote:
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.
I understand that, and that's why I said I didn't have time to read a book on assembly initially. Properly reading through your answer took me more than 2 hours, making it all sink in. Your examples are excellent, and I am very grateful to you for the time you invest in helping others. The 2 hours I've spent after work I've spent increasing my own potential, and you must have spent even more time and energy on composing your detailed response when there is no direct benefit to you. I can actually read some of the accursed code now and make sense of it. Thank you so much!

I had no idea you could view the call stack after setting a breakpoint. This is extremely helpful! However, my previous attempts at setting breakpoints have been failures.
I vaguely remember stumbling upon the call stack in some other place, but I couldn't find it again. I thought it was one of the right-click options in the main window, but I don't see it there anymore.

I've tried backtracing at the very start as well (it's a professional deformity), but reading 4 lines of assembly took me more time than reading a program in a never-before-seen "high-level" language normally does. It's actually quite depressing. Finding the actual subtraction would indeed be better, but I simply can't locate anything that'd even remotely resemble a sub or an fsub. I could give you the full instruction list and/or the installation file for the game itself, but that would be taking the burden off my shoulders and putting it onto yours. That's probably not right.

ParkourPenguin wrote:
don't make useless posts to increase post count
Dobby is a good elf. Dobby would never do that.

Update: after reading your answer once more and a thread from stackoverflow, I understand that I am dealing with a function call in the bit of code I have initially cited. This, however, is pretty much all that I understand at the moment. I even found a variable I think might be the actual start of the structure I am looking for, but finding its value in all those perturbations seems an impossible task (I've traversed about a 100 lines, but haven't arrived at the initial assignation yet).
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

Joined: 06 Jul 2014
Posts: 1748
Location: Arcadian Suburbia

PostPosted: Mon May 01, 2017 10:50 am    Post subject: Reply with quote

GoreGrindGeek wrote:
Unfortunately, [using a breakpoint] made my computer freeze...

What version of CE are you using? What's your debugger settings (Edit -> Settings -> Debugger Options)? What's your OS? Are you running CE as administrator? Is there other software that could be interfering (i.e. antiviruses)? How did you find those instructions in the first place if you can't use breakpoints?

GoreGrindGeek wrote:
Why exactly is the number 4 subtracted from/added to esp? Is there something magical about it? Oh, read your next example, and, apparently, 4 is just the number of bytes allocated in this instance (no idea why allocation has such a weird syntactical structure, but I'll just go with it for the time being).

To put it simply, that's a 32-bit process, so elements on the stack take up 32 bits (4 bytes). If that were a 64-bit process, every push/pop instruction would be subtracting/adding 8 bytes (64 bits).

I use the term "allocation" abstractly. Modifying esp isn't actually allocating any memory, because the stack's memory was already allocated when the thread started. I suppose "resizing" the stack would be better terminology.

GoreGrindGeek wrote:
So what exactly is a stack frame? Is it a pointer to a particular item within the stack? Wouldn't that make the stack... a linked list of some kind? I thought assembly was more primitive than that and didn't store any internal pointers within stacks. Or am I completely missing your point?

A stack frame is an abstract idea that represents a contiguous section of the stack that belongs to a particular subroutine.

Stack frames aren't too different from the idea of function scope. Functions have their own scope that belongs to them and not to their caller or callees. Similarly, functions have their own section of the stack (a stack frame) that belongs to them and not to any other function.

Stack frames are implemented similar to a singly linked list in that [ebp] (the value at the address ebp) is the beginning of the caller's stack frame. Just remember that this is a convention, and software isn't required to always use ebp in this way.

GoreGrindGeek wrote:
I'm not quite sure how you calculated the offsets for its assembly representation...
So labels can actually be called like functions... Interesting.

The only two numbers that were somewhat arbitrary were 10 in "sub esp,10" and -4 in "mov [ebp-04],eax". Everything else is determined by the instructions used. Also, a label is used to represent an address- no more, no less.

When dealing with functions and the stack, one important fact to know is that the call instruction pushes the return address onto the stack and jumps to the specified address, while the ret instruction pops that address off the stack and jumps to that address. Using the C example in my previous post, the order instructions are executed in could look like this:
Code:
address - instruction - stack (bottom -> top; hexadecimal; shown after instruction has executed)

// say the stack is "empty" right now; ebp == esp == 0160F71C
002A0000 - push 07              7
002A0002 - push 06              7   6   
002A0004 - call 002A0010        7   6   002A0009

// jump to foo:

002A0010 - push ebp             7   6   002A0009    0160F71C
002A0011 - mov ebp,esp          7   6   002A0009    0160F71C
002A0013 - sub esp,10           7   6   002A0009    0160F71C    ?   ?   ?   ?
002A0016 - mov edx,[ebp+08]     7   6   002A0009    0160F71C    ?   ?   ?   ?
002A0019 - mov eax,[ebp+0C]     7   6   002A0009    0160F71C    ?   ?   ?   ?
002A001C - add eax,edx          7   6   002A0009    0160F71C    ?   ?   ?   ?
002A001E - mov [ebp-04],eax     7   6   002A0009    0160F71C    D   ?   ?   ?
// other code...
002A0021 - mov esp,ebp          7   6   002A0009    0160F71C
002A0023 - pop ebp              7   6   002A0009
002A0024 - ret                  7   6

// return to main:

002A0009 - add esp,08           // stack is "empty" again

In the above code, after "mov ebp,esp" is executed:
    ebp = 0160F70C - the begging of the current stack frame
  • [ebp] = 0160F71C - the beginning of the caller's stack frame
  • [ebp+4] = 002A0009 - the address this function returns to
  • [ebp+8] = 6 - the first parameter
  • [ebp+C] = 7 - the second parameter

GoreGrindGeek wrote:
I've tried backtracing at the very start as well... but I simply can't locate anything that'd even remotely resemble a sub or an fsub.

If you're just scrolling up, you aren't going to find it. From the looks of it, the subroutine that instruction is a part of is only responsible for updating your health. Look at the two instructions again that are responsible for writing to your health:
Code:
1B2C9949 - D9 45 08  -  fld dword ptr [ebp+08]
1B2C994C - D9 5E 18  -  fstp dword ptr [esi+18]

The second instruction writes to your health using the value retrieved by the first. When backtracing, the next obvious question would be "Where is the first instruction getting the value from?" The answer - assuming this subroutine established its own stack frame (very likely) - would be that it was passed as the first argument to this subroutine by the caller ([ebp+08] is the first argument). The semantics of the function you're looking at could look something like this:
Code:
void update_health(float newhealth, ...)
{
    ...
    entity->health = newhealth;
    ...
}

If you want to find where the calculation is being done, you'd need to look at what called this subroutine, and the easiest way of doing that would be to use a breakpoint.

_________________
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
sbryzl
Advanced Cheater
Reputation: 3

Joined: 25 Jul 2016
Posts: 97

PostPosted: Mon May 01, 2017 12:46 pm    Post subject: Reply with quote

sbryzl wrote:
ebp is a location in memory and it is a base pointer for another stack.
GoreGrindGeek wrote:
How do you know and what exactly do you mean by "another stack"? So far, only FPU has been mentioned. Isn't ebp just a register?

ebp and esp are both always used as stack pointers that's just the normal procedure. They can also be used like the other registers, you could also use any other register as another stack pointer. ebp was mentioned as part of the stack relative address where the value is pulled from "fld dword ptr [ebp+08]"

sbryzl wrote:
If you replace both with a mov immediate value to your memory location [esi+18] then you could put whatever you want there.
GoreGrindGeek wrote:
Why not just the first one?

If you just replace one and leave the other then it will throw off the stack hence the crash you are talking about. More than likely though you would need some extra checks to be sure you only write to the particular address you want. This will also lead to crashes if it is writing to many different addresses.
Back to top
View user's profile Send private message
GoreGrindGeek
How do I cheat?
Reputation: 0

Joined: 30 Apr 2017
Posts: 5

PostPosted: Tue May 02, 2017 3:18 am    Post subject: Reply with quote

ParkourPenguin wrote:
What version of CE are you using? What's your debugger settings (Edit -> Settings -> Debugger Options)? What's your OS? Are you running CE as administrator? Is there other software that could be interfering (i.e. antiviruses)? How did you find those instructions in the first place if you can't use breakpoints?
6.6, the latest version. I can't give you a screenshot of my debugger settings, as I am not cool enough to post links (which is why I didn't post a link to the stackoverflow thread I have read in addition to your previous response), but they are basically default. The OS is Windows 8.1 with all the service packs. I am running CE as administrator now (not sure why I didn't have that compatibilty option checked before, but I'm known to be dumb on occasion). I don't use antiviruses. I found those instructions by locating the value for Psi and then attaching a debugger to it ("What writes to this address").
Running CE as administrator with the game open in windowed mode made the breakpoint do what you said it would. However, the game is unresponsive after that, and I would have to restart it were I to continue playing it (Update: wrong - I just needed to tell it to run the code after it stopped, by pressing F9).
I'll get back to your suggestion #1 and try it out anyway. What's a segment register, I wonder?
You've previously suggested copying the contents of the stack into notepad, but I can't seem to figure out a way to do that. I found a way to copy the values from within FPU, but there seem to be no options for copying the stack or the registers' values (even Ctrl+C is of no use). ST(0) holds the value before the update, and ST(7) holds the number by which to update ST(0). I can't place any of the other values within the context of the game or make any sense out of the stack/registers.
Hmm, I seem to have figured out how to use the debug tools and breakpoints. The values of the registers seem to have nothing of value (thankfully, CE highlights the registers that have changed since the instruction was run last). Even if they hold unique identifiers, those are different between restarts.

ParkourPenguin wrote:
To put it simply, that's a 32-bit process, so elements on the stack take up 32 bits (4 bytes). If that were a 64-bit process, every push/pop instruction would be subtracting/adding 8 bytes (64 bits).

I use the term "allocation" abstractly. Modifying esp isn't actually allocating any memory, because the stack's memory was already allocated when the thread started. I suppose "resizing" the stack would be better terminology.
That explains it. Thank you kindly.

ParkourPenguin wrote:
A stack frame is an abstract idea that represents a contiguous section of the stack that belongs to a particular subroutine.

[...]
Thank you, I think I got it now. It is common for the compiler to use ebp to differentiate between portions of the stack relevant to a particular function. And I should remember this is only a convention, so that I don't interpret every ebp in the future as a sign of a function being called. Is that correct?

ParkourPenguin wrote:
Using the C example in my previous post, the order instructions are executed in could look like this
I think I understand this example fully. I don't exactly understand why the instructions follow this kind of logic in the first place, but I see the logic and I can follow and read it now, which wouldn't be possible without your help. Is there a reason why assembly is set up in such a, for the lack of a better word, "weird" way? Apart from memory management, which obviously was an issue when it was developed and standardised.

ParkourPenguin wrote:
If you're just scrolling up, you aren't going to find it.
But why? The debugger found ecx, so theoretically I should've been able to find it too.

ParkourPenguin wrote:
From the looks of it, the subroutine that instruction is a part of is only responsible for updating your health.
It's not just Health... The same instruction updates Psi and maybe some other values, for all critters, given that substituting those 2 lines with NOP's made everyone invincible and prevented the loss of Psi by all critters, not just the PC. I really can't think of a way that'd be set up at source level except through a multidimensional array, which seems to be dynamic, given that the offset between Health and Psi is different between restarts. So I'm thinking it's (almost) impossible to freeze the Health and Psi values for this game or produce persistent pointers to them. It might not even be an array but rather an object of a custom type or hold custom-type values, given that CE has trouble automatically creating a valid structure from the given base addresses. But I might be overthinking this and inventing laughable stories, for I am certainly not an expert here. I'm just trying to think through some of the possibilities.
Update: it's most likely a function that works with an associative array, which would explain both why it's only getting 1 value as input and how it's setting it for any type of critter?

ParkourPenguin wrote:
If you want to find where the calculation is being done, you'd need to look at what called this subroutine, and the easiest way of doing that would be to use a breakpoint.
Given that I have learnt how to use breakpoints in CE with your help, where would I place a breakpoint in this particular instance, why, and what should I look for?

sbryzl wrote:
ebp and esp are both always used as stack pointers that's just the normal procedure. They can also be used like the other registers, you could also use any other register as another stack pointer. ebp was mentioned as part of the stack relative address where the value is pulled from "fld dword ptr [ebp+08]"
Thank you! Please keep in mind that the only assembly knowledge that I have comes from playing TIS-100 and reading this thread, so I am not always even aware of what you are talking about, as I have never learnt assembly-specific terminology.

P.S. I think I've learnt enough from this thread to be able to go and take a look at how the 2 cheat tables I've found for this game are set up (none of them worked and none of them had Health or Psi references, but maybe their authors have managed to find something I didn't).
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

Joined: 06 Jul 2014
Posts: 1748
Location: Arcadian Suburbia

PostPosted: Tue May 02, 2017 10:17 am    Post subject: Reply with quote

GoreGrindGeek wrote:
Update: wrong - I just needed to tell it to run the code after it stopped, by pressing F9
Have you used a debugger in a higher-level language before? It's pretty similar to what CE allows. Toggle breakpoints, step in, step out, continue, etc.

GoreGrindGeek wrote:
What's a segment register, I wonder?
The segment registers are a collection of 16-bit registers that can be used to address memory locations. They were useful when everything was 16-bit, but they're obsolete nowadays (for the most part). In documentation, if you see text that says something like "an offset relative to the segment base," assume the default segment base is 0 unless you see reason to believe otherwise (e.g. mov fs:[0],esp - you should not write code like this unless you have a reason to).

GoreGrindGeek wrote:
You've previously suggested copying the contents of the stack into notepad, but I can't seem to figure out a way to do that.
Yeah, that's a shortcoming on CE's part. Hopefully that feature will be added eventually.
As I said before, you can go to the hex view (bottom half of memory viewer; left of the stacktrace window), go to whatever ESP is, and copy the bytes from there. Make sure the game is paused on a breakpoint while doing this; otherwise, that area of memory will probably be changing quite rapidly.

GoreGrindGeek wrote:
It is common for the compiler to use ebp to differentiate between portions of the stack relevant to a particular function. And I should remember this is only a convention, so that I don't interpret every ebp in the future as a sign of a function being called. Is that correct?
Yes. There are other implications ebp can have (e.g. [ebp+X] is usually a parameter and [ebp-X] is usually a local variable), but it would be tedious to describe all of them.

GoreGrindGeek wrote:
Is there a reason why assembly is set up in such a, for the lack of a better word, "weird" way?
That's subjective. To me, it makes perfect sense, but that's because I've grown accustomed to this type of programming paradigm.

Assembly is the way it is because it's really just a system of mnemonics for the 0s and 1s the processor understands. To that end, it's very basic, consisting of only low-level instructions the processor knows how to execute. Higher-level concepts such as classes, objects, and functions are abstract- they exist only in theory. Even the call instruction doesn't have to adhere to the semantics its name implies. For example, if you want to push the address of the next instruction onto the stack, you can do so indirectly by using the call instruction:
Code:
db e8 00 00 00 00  // machine code; this will "call" the instruction after this one
pop eax
// eax now contains the address of the instruction "pop eax"

Assembly takes some time to get used to, especially if you're very accustomed with high-level languages.

GoreGrindGeek wrote:
ParkourPenguin wrote:
If you're just scrolling up, you aren't going to find it.
But why? The debugger found ecx, so theoretically I should've been able to find it too.
I was referring to the instructions responsible for subtracting from the health. The subroutine those instructions are in called the subroutine the write to the health belongs to. There is no guarantee those two subroutines are close to each other in memory. If you wanted to scroll through pages of assembly to find it, then yes, it is theoretically possible to find it after several years of searching (on average).

A better way of finding it would be to look at the code after an instruction that reads from your health, but there's no guarantee you'll find it quickly.

GoreGrindGeek wrote:
I really can't think of a way that'd be set up at source level...
There are a virtually infinite number of ways. This could be one of the simpler ones:
Code:
struct EntityAttribute
{
   float current_amount;
   float max;
   // other stuff...
};

struct Entity
{
   EntityAttribute health;
   EntityAttribute Psi;
   // other stuff...
};

void setEntityAttribute(EntityAttribute *attribute, float newvalue)
{
   attribute->current_amount = newvalue;
   // other code...
}


GoreGrindGeek wrote:
where would I place a breakpoint in this particular instance, why, and what should I look for?
Set a breakpoint on the write to your health so you can find out where the code returns to. The "break and trace" feature will be helpful (right click on an instruction to access it). See this topic for information on backtracing.
_________________
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
GoreGrindGeek
How do I cheat?
Reputation: 0

Joined: 30 Apr 2017
Posts: 5

PostPosted: Sat May 06, 2017 3:58 am    Post subject: Reply with quote

ParkourPenguin wrote:
Have you used a debugger in a higher-level language before? It's pretty similar to what CE allows.
Yes, sir. I was a C/C++ developer for a short while, but I've been doing web-development for a reasonably long time since then, so I got a bit out of touch. I am glad I got a chance to get a tad bit closer to the "roots".

ParkourPenguin wrote:
The segment registers are a collection of 16-bit registers that can be used to address memory locations. They were useful when everything was 16-bit, but they're obsolete nowadays (for the most part).
Hmm. The game occasionally has them equal to 1 (but never greater than 1). I'll have to dig up some more information, because I'm curious.

ParkourPenguin wrote:
As I said before, you can go to the hex view (bottom half of memory viewer; left of the stacktrace window), go to whatever ESP is, and copy the bytes from there.
Thank you - I forgot. There was a lot of new data for me to consider, and having it all sink in takes time.

ParkourPenguin wrote:
it would be tedious to describe all of them
Your previous examples did the job perfectly, and I'm very grateful.

ParkourPenguin wrote:
you can do so indirectly by using the call instruction
Hmm. I'll need some time to understand this one.

ParkourPenguin wrote:
A better way of finding it would be to look at the code after an instruction that reads from your health, but there's no guarantee you'll find it quickly.
I'm not sure it's even possible. A much more experienced person did a table for this game in the past, but even he had nothing that'd affect Health/Psi, and I think I saw a post somewhere mentioning to just "raise the corresponding stat" because of how futile it was to search for the code responsible.

ParkourPenguin wrote:
There are a virtually infinite number of ways. This could be one of the simpler ones
True. And a great example once more. Unfortunately, like I think you said before, my only hope was looking through the registers when in debug mode, but there was nothing of value there.

ParkourPenguin wrote:
Set a breakpoint on the write to your health so you can find out where the code returns to. The "break and trace" feature will be helpful (right click on an instruction to access it). See this topic for information on backtracing.
Thank you, kind sir. I'll read through it, but I'm not entirely sure when I'll manage to get back to my hopeless attempts at solving the initial problem. The game and the process of creating a table for it really burnt me out, and there's a ton of other things I have to do at work and in my spare time at the moment (which is why I haven't responded for a few days).

I can't thank you enough for your input and help.
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