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 


Help finding a pointer within a data structure

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
[email protected]
How do I cheat?
Reputation: 0

Joined: 21 Oct 2018
Posts: 5

PostPosted: Sun Oct 21, 2018 5:41 pm    Post subject: Help finding a pointer within a data structure Reply with quote

Hi there

I'm very new to the use of CheatEngine and I hope I don't fill your forum with an inane or unnecessary question but I've really tried very hard to find the answer to my own question on my own and I'm fresh out of ideas.

So I'm actually just using CheatEngine to find static pointers that I can use in an autosplitter I'm using for speed running a game called metal slug 3. Basically this autosplitter will monitor the pointers I give it and I can give it criteria so when I get to a certain part of the game it will flick my timer over for my speed run for me.

I've been able to find pointers to start my splitter and also reset it when I go back to the main menu but I've been really struggling with finding a pointer I can use so that when the bosses health hits zero it will split.

I can consistently find the bosses health in memory no problems, the issue I have is that when I then get a pointer for the bosses health it doesn't remain pointing at the right value even though its base is a static address. Also I'm not talking about it doesn't stay pointing at the right value when I close the game and open it up again. I'm talking about when you go back to the main menu with the game process still running and then go back into the game, get to the boss again and the pointer is no longer pointing at the right address.

Now after much experimentation I've found that the static base addresses that I've found and used in my pointers are the same every time I find them it's only the offset that changes. This leads me to believe that maybe the static addresses are pointing at the start of a data structure which has the health dynamically allocated somewhere inside it, and perhaps where inside it is calculated somewhere else. How I might find that somewhere else however is a complete mystery to me.

I've found the instruction that is the thing that changes the health each time I hit the boss and the instuction is
Code:
mov [eax+esi*2],dx
Now EAX is consistently the value that is in the static base address I found which I think is the start of my structure but ESI seems to be different with every boss load. I've tried searching for the hex value of ESI and then noting down the static addresses with those values in it with no luck. I've also tried leaving the list of matching values up whilst I went into the boss again to see which changed and checked the ones that changed against the new ESI offset but still none of the changed values matched

Obviously I've also done a lot of reading around this forum but I think my biggest problem right now is that I don't know what I don't know so it's difficult to know what to search for at this point. I don't expect anyone to spoon feed me if people want to help I'd greatly receive it but even if people could just shoot me some links to read through if this scenario sounds familiar then that would also be greatly appreciated.

Thanks in advance for your time.



Memory viewer at instruction.png
 Description:
Memory viewer around the instruction in case that helps
 Filesize:  62.91 KB
 Viewed:  8072 Time(s)

Memory viewer at instruction.png



Instructions that access.png
 Description:
Instructions that access the bosses health dynamic address. The start of the data structure is in EAX
 Filesize:  27.89 KB
 Viewed:  8072 Time(s)

Instructions that access.png



Cheat table.png
 Description:
Cheat table with memory addresses in it
 Filesize:  47.54 KB
 Viewed:  8072 Time(s)

Cheat table.png


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

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sun Oct 21, 2018 6:23 pm    Post subject: Reply with quote

Figuring out where ESI is coming from wouldn't be a bad place to start. Keep scrolling up in the disassembler until you find the instruction that writes to ESI. Dissect the code in mslug3.exe to more easily see conditional branches.

If you can't read x86 assembly, try searching for the offset via unknown initial value and increased/decreased scans. It looks like a 2-byte value that might be shifted left by one (i.e. multiplied by 2, maybe add 1).

The CE tutorial (under the "help" menu) may help.

_________________
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
[email protected]
How do I cheat?
Reputation: 0

Joined: 21 Oct 2018
Posts: 5

PostPosted: Mon Oct 22, 2018 2:29 am    Post subject: Reply with quote

Thanks for you reply ParkourPenguin. See, I had thought that this might be the answer. That I would have to find out what is writing to ESI however that just raises more questions that wonder if you might have the time to answer.

My main question is that if the value in ESI is the offset that I'm looking for and what is in ESI is dynamic then when I find the static base of what is in ESI how would I then write a pointer that points the the address that I'm looking for?

Thus far in all the literature that I've read to find a pointer people have been talking about building a pointer using a memory register with a static offset e.g. EAX+0C or EDX+0018 or whatever. This means that the pointer I would then want would be the value of EAX which would need to be a static memory address plus the offset. Because the memory address doesn't change the pointer will always be address+offset.

However in my case my offset appears to be dynamic in that the offset is calculated off ESI it's EAX+ESI*2. I've seen other questions suggesting that in these cases ESI might always be 0 but that isn't the case for me ESI is different each time I load the level 1 boss fight. Now I presume that would mean that once I have found the static memory address for ESI (which I will) then to get a pointer that points at EAX+ESI*2 I would need to create a pointer that is like [static address in EAX] + [pointer starting at static address of ESI plus whatever offsets needed to get to the value of ESI] * 2. So it would basically be a memory address that would be offset by the value of a pointer.

So then my question is, is it possible for me to create a pointer that looks like that? Or am I completely misunderstanding what the pointer would look like. Would it in fact be the static address of EAX + the static address of ESI + the static address of ESI?

I'm ok with going and finding ESI I'm just wanting to make sure that if I go to the effort of doing so that I will end up with a pointer that I can actually use to consistently get back to the memory address I want.

Also, I have completed all the tutorials within the help of Cheat engine before posting the question but maybe I'm not making the connection between the content and my problem here. Is there a particular step of the tutorial which is relevant here? I have successfully found pointers with static offsets (i.e. eax+0C etc) as the tutorial teaches but this whole thing with the dynamic offsets has really thrown me through a loop.

Thanks for your help thus far.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Mon Oct 22, 2018 10:11 am    Post subject: Reply with quote

TinfoilSaint wrote:
My main question is that if the value in ESI is the offset that I'm looking for and what is in ESI is dynamic then when I find the static base of what is in ESI how would I then write a pointer that points the the address that I'm looking for?

... I would need to create a pointer that is like [static address in EAX] + [pointer starting at static address of ESI plus whatever offsets needed to get to the value of ESI] * 2. So it would basically be a memory address that would be offset by the value of a pointer.

So then my question is, is it possible for me to create a pointer that looks like that?
Sure. All the ways I can think of would involve Lua. You could also use AA, but then code injection would be preferable to pointers.

In the address list, use Lua to read the offset yourself. e.g. copy/paste this into the offset ESI would be at:
Code:
2 * readSmallInteger'[game.exe+D464]+1E4'


In Lua, you can traverse the pointer path manually:
Code:
local addr = getAddress'[[[game.exe+823C]+DF8]+34]'

local esi = readSmallInteger'[game.exe+D464]+1E4'

local health = readSmallInteger(addr + 2 * esi)

Alternatively, I wrote some code a while ago (link) that hooks CE's symbol lookup function to allow for this AA-like syntax:
Code:
local health = readSmallInteger'[[[game.exe+823C]+DF8]+34] + 2 * word_ptr[[game.exe+D464]+1E4]'


TinfoilSaint wrote:
Thus far in all the literature that I've read to find a pointer people have been talking about building a pointer using a memory register with a static offset e.g. EAX+0C or EDX+0018 or whatever. This means that the pointer I would then want would be the value of EAX which would need to be a static memory address plus the offset.
Minor note: the address (i.e. EAX) doesn't need to be static. If it changes, then that just means you found a node in a pointer path and not the base address.

TinfoilSaint wrote:
Because the memory address doesn't change the pointer will always be address+offset.

However in my case my offset appears to be dynamic in that the offset is calculated off ESI...
That's fine. It's nice when all the offsets are static and don't change, but offsets that change can be used too. You'll just need to figure out how to calculate it. Hopefully it's stored somewhere you can read it easily; however, it could be something more advanced like a hash function.


There are other ways to get to addresses. The pointer scanner can be used to find other pointer paths that aren't accessed as often, and code injection can copy the health's address. There's a pretty old topic (link) that covers this.

_________________
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
[email protected]
How do I cheat?
Reputation: 0

Joined: 21 Oct 2018
Posts: 5

PostPosted: Mon Oct 22, 2018 12:13 pm    Post subject: Reply with quote

That's really excellent! Thanks so much for your time and wisdom. I'll take everything you've said there and see if I can't work this out from here. I've also started watching a youtube series to up my ASM lang game so hopefully that will help.

Of course if anyone else drops by and thinks there is anything they can add to this I'll be glad to take further advice but for now I think that might be enough for me to take another step towards my answer.

Thanks.
Back to top
View user's profile Send private message
[email protected]
How do I cheat?
Reputation: 0

Joined: 21 Oct 2018
Posts: 5

PostPosted: Sat Oct 27, 2018 6:04 pm    Post subject: Reply with quote

OK, so I've gone away and found a recording of a university course on x86 and started learning assembly I'm about 7 or 8 hours in and I'm feeling a lot more confident. I certainly understand how the offset is being calculated but I'm still not able to find where the offset begins.

I have worked out that the ESI is being set to the value in ECX when the function begins. But my problem now is that I can't find where ECX is being set before hand higher up in the call stacck.

Once I've found the offset I'm able to get the code to break when ESI is set to the correct offset and I can then work out from there what ECX is so I can break at the start of the function when the ECX value is correct.

The problem I'm having is I can't get a break point to fire based on that same ECX value from the call instruction that sends the code to the function I'm looking in. It just won't break. Also I find that when the function returns ECX has changed!

I think that at this point probably what I've got in my static addresses in my cheat table is the pointer to the start of an Enemies array or something and the reason that the offset is different with each load is because throughout the course of the run up to the boss I've killed a different number of enemies each time. The problem is I just can't find that array index, it must exist somewhere in memory but I just can't find it.

Here's what I've tried looking for to try find it, maybe someone can give me some ideas on what else I could use to try and find the value I'm looking for.

I've tried:

- Searching for the ECX value that is set at the start of the function.
- Searching for the ECX value from when after the function has returned.
- Searching for the offset that lives in ESI
- Searching for the 2*ESI
- Searching for 2*ESI-1
- Starting with the start of the data structure that the value I'm looking for is always offset by and searching between that value and a reasonable sized top end memory address for both ESI and 2*ESI in case the pointer I'm looking for is within the actual structure itself

I've now probably sunk a good 8 hours studying and a further 10 or so looking for this damned value and I just feel like I'm getting no where. I'm not looking for sympathy I just wanted to say that so people know I'm not just wasting people's time, I'm trying really hard to do this myself but I'm just stuck.

I think what I need to know next is, given that I know the value of ECX at the start of the function I'm looking at, how would I create a breakpoint in the the function that my function returns to so that I could could keep chasing ECX up the call stack? It's probably work mention here as well this function I'm in looks like a pretty standard check the health function it gets called many 10's of times a second and not always with the values that I am looking for so just setting a breakpoint in my function or the one above without setting some criteria for the break won't give me the answers I'm looking for as the breakpoint get's hit for lots of different calls.

Also in case it gives anyone ideas for other things I could try. What I am basically looking for is I want to be able to find out when the bosses health drops to zero causing the level to end. Maybe I don't even need to find the health?



Parent function.png
 Description:
 Filesize:  82.51 KB
 Viewed:  7968 Time(s)

Parent function.png



Top of function.png
 Description:
 Filesize:  82.75 KB
 Viewed:  7968 Time(s)

Top of function.png



Break points.png
 Description:
 Filesize:  95.46 KB
 Viewed:  7968 Time(s)

Break points.png



Cheat table.png
 Description:
 Filesize:  45.82 KB
 Viewed:  7968 Time(s)

Cheat table.png


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

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sat Oct 27, 2018 8:37 pm    Post subject: Reply with quote

You can see the call destination in "Parent function.png" is 00457B40, not 0045AA60. Either that's not the top of the function or there's a tail call made from somewhere else.

Personally, I'd take the time to dissect the main module (Memory Viewer -> Tools -> Dissect code)- it might make looking at the code easier.

If you're lost, you could go to 00457B40 and set a break and trace somewhere near the start of the function (right click menu).

Have you tried searching for the index via unknown initial value and increased/decreased scans yet? Sure, it might take a while, but it's better than repeatedly trying different combinations of rules.

There's a book called "Reverse Engineering for Beginners" that might help if you know a little C / C++. There are plenty of videos too (e.g. crackmes), but finding good quality ones can be troublesome.

_________________
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
[email protected]
How do I cheat?
Reputation: 0

Joined: 21 Oct 2018
Posts: 5

PostPosted: Sun Oct 28, 2018 5:26 am    Post subject: Reply with quote

Wow! 1000 pages of free knowledge! That's great, thanks so much. In the interests of sharing, here is a link to the assembly content I was watching. Sounds like it might not teach you a lot that is new but at least if you're talking to other beginners then you might like to forward it on to them Wink https[colon-slash-slash]youtu.be/H4Z0S9ZbC0g (<-- apparently I can't post urls yet) It looks like that channel also have intro to reverse engineering videos which I guess I should watch once I've finished the intro to x86 playlist.

I had noticed that the call wasn't going to the address of my function but that is where I'm taken when I do "Execute til return". That is definitely the top of my function if you scroll above where I've screenshotted there its just a huge block of blanked out memory. I've done the dissect code and it shows that A HUGE amount of addresses call my function so I didn't find that all that useful.

I had gone to 00457B40 and had a look but it wasn't obvious where the code was going to get into my function, maybe I need to spend a little more time looking into that function and try and find my way down the call stack back to my function. That is a good idea, thanks for the suggestion.

I haven't tried the increased/decreased scans for the pointer yet. To be clear, I've found the health, in fact I've found it so many times that when I get into the boss fight I can find it within two scans Razz My problem with using unknown initial value scans is that I would guess that the pointer is initialised somewhere between the last part of the main level and the boss fight and to get to that point takes just over a minute a time so doing things that way could take a VERY long time. Also I'd be guessing and so I wouldn't learn as much. I think I'd prefer to take the approach of trying my best to really understand things before I start blindly poking at things. Having said that I do get that sometimes that's what I might just have to do so I'll keep the option open.

Thanks again for you patience and wisdom.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine 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