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 


C# Dictionary Data in memory, 0/Unknown field offsets?

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

Joined: 23 May 2020
Posts: 3

PostPosted: Mon May 25, 2020 5:28 am    Post subject: C# Dictionary Data in memory, 0/Unknown field offsets? Reply with quote

So i have an interesting issue.

I used Mono's capabilities to find a class i am interested in. It contains some values, and some pointers and i found the exact instance i want to dissect.

I got a static pointer to the class instance, and copied it to make some direct references to the containing data i need. And that a pointer to a Dictionary that is String, Object. And i know the object is a struct with 2 int's from other reverse engineering efforts.

However, due to how dictionaries work, i can't really get the data from the dictionary. It looks like the strings are not even present in memory at all (instead they are probably stored as hashcodes in this dictionary?)

I found thought Mono dissector the layout of this dictionary. Which should clue me in on where the data is. It seems like the fields do not have the proper offsets.

I made an effort to try and figure out through the pointer that i KNOW is a dictionary like this, in which order or at what offset the different values might be. But since i know the "count" and none of the values actually reflect the count as i expect it to be, and the pointers are even harder to confirm. I do not know where to go from here.

How does one dissect this?
And why does Mono dissector not find the proper offsets for these fields on it's own?



FOzw0[1].png
 Description:
 Filesize:  12.87 KB
 Viewed:  1912 Time(s)

FOzw0[1].png


Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Mon May 25, 2020 11:39 am    Post subject: Reply with quote

The dictionary should work like:
Code:

given item entry [KEY,VALUE]
get HASH of KEY
find BUCKET of HASH in buckets <ie. BUCKET is an element of buckets>, eg. BUCKET = buckets[ HASH mod size-of-buckets ] as array element
-- since multiple KEY can give same HASH, BUCKET itself may be a pointer to a container, said a linked list <note: not structural fixed offset locatable>
Then the elements of BUCKET may have 2 pointers to KEY and VALUE, (and some other field for how the container work, eg NEXT pointer for a linked list )
It then enumerate through the BUCKET elements to find the EXACT KEY by comparer/equalityCheck,
then either there existed [KEY,VALUE] and location is found, or (get) return no value, (set) need to create new item


Now you don't know how hashing exactly work, and how buckets structure, so you can't tell which BUCKET in buckets for an item located.
The same go for BUCKET's sub structure, as mention in above possible linked list (good in dynamic allocate/deallocte memory).

Both are not likely a structure using fixed offset.

Even sometime pointer scanner may return seemly consistent offsets, they are still not reliable.

@And why does Mono dissector not find the proper offsets for these fields on it's own?
You are looking at a GENERIC class, the field may be determined until made instantiated with concrete sub types.
But mono dissector may not display the whole class structure, but only as a supplemented info/name beside some fields that derived from the generic class .

_________________
- Retarded.
Back to top
View user's profile Send private message
bacontaskmaster
How do I cheat?
Reputation: 0

Joined: 23 May 2020
Posts: 3

PostPosted: Mon May 25, 2020 3:00 pm    Post subject: Reply with quote

Ok, so buckets are not going to help me if i understand you correctl. But an ENTRIES things, should be an array of "Entry" types, which should just be a chain of all the entries in a linear-ish way.

Again the Mono dissector tells me this contains:
hashcode (int32)
next (int32)
key (int32 or String?, TKey)
value (Struct(int32,int32), TValue)

Which are basically the actual container values to set up the content of the buckets, no?

But since i can not find the strings i know it had as input in any of the pointers from the dictionary, i assume the Key's are not actually found as strings since CE can't find the string or i can't find a reference to a string.

If i understood you correctly. could the offsets of the parameters change per statup of the app as well? That would kinda ruin the party as well.

EDIT: Forgot to mention that this is all originally C# code that got IL2CPP treatment. It's a C# dictionary, not a C++ variant or whatever, if that was no unclear.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Mon May 25, 2020 5:33 pm    Post subject: Reply with quote

No, you probably right, if you found the VALUE your own way.

Using Pointer probably still not reliable, but if the structure is known, you may find it.

Try a decompiler like dnspy, justdecompile. If it is not il2cpp, the source can be reveal, even il2cpp should be possible if you familiar with some advance debug tool.
Btw, the version I check for Dictionary use Link (linked-list) instead of buckers (as name), so the internal structure may be different in different version of unity.

Then it need programming, using Lua may be a bit better controlled than using assembler (should be still posible in il2cpp?), given that all operation is read only (so thread safe?)

eg. not sure in your version, the bool TryGetValue(Key, out ptr ^Value) function may be what you interested .

Yet, the VALUE found may be obsolete when the item changed.

_________________
- Retarded.
Back to top
View user's profile Send private message
bacontaskmaster
How do I cheat?
Reputation: 0

Joined: 23 May 2020
Posts: 3

PostPosted: Tue May 26, 2020 4:21 am    Post subject: Reply with quote

Ok, so i think i got a bit lucky. Due to how this dictionary was used. All values were always at a fixed offset of the definition of the Dictionary.

They initialize it, then fill it, and before they re-fill it they Clear() it. Causing the actual elements to just be a little further in memory than expected, but seemingly at a fixed offset in a fixed order. So that works for me! It was all just 1 pointer away and it didn't spot it.

Thanks for helping out!
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