- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 546
- Reaction score
- 7
Digging into Unity applications always brings up the same headache: dealing with the managed heap. If you are coming from a pure C++ background, the way .NET handles objects can feel like a maze of dynamic allocations that break the moment you restart the process.
The Problem
Getting a pointer to a simple array like int[] is one thing, but once you start hunting for Dictionary, HashSet, or specific ManagedType[], the complexity spikes. These aren't just raw buffers in memory — they are full-blown managed objects with their own internal headers and metadata references. Finding a pointer that works for one session is easy, but without finding the static root or the right offsets from GameAssembly.dll (in IL2CPP) or mono.dll, you will be chasing your tail forever.
Current Situation
Troubleshooting Checklist
Are you guys using a custom scanner to find these, or are you manually tracing the static instances from the module base? Drop your methods for dealing with dynamic base addresses below.
The Problem
Getting a pointer to a simple array like int[] is one thing, but once you start hunting for Dictionary, HashSet, or specific ManagedType[], the complexity spikes. These aren't just raw buffers in memory — they are full-blown managed objects with their own internal headers and metadata references. Finding a pointer that works for one session is easy, but without finding the static root or the right offsets from GameAssembly.dll (in IL2CPP) or mono.dll, you will be chasing your tail forever.
Current Situation
- Using dnSpy to analyze the assembly and locate the classes.
- Successful pointer acquisition for generic object arrays.
- Pointers invalidate immediately after a restart (ASLR/GC movement).
- Struggling to find the base for complex types like Dictionaries.
Unity uses either Mono or IL2CPP. If it's Mono, you need to traverse the MonoDomain and MonoAssembly to find the static fields. If it is IL2CPP, everything is baked into GameAssembly.dll. You should be looking for the metadata registration or using a tool like Il2CppDumper to get the script-relative offsets.
For a Dictionary, remember that the pointer you get is to the object header. The actual data is usually inside a entries field. You need to calculate the offset from the class base to the field itself rather than just scanning for a temporary address in the heap.
For a Dictionary, remember that the pointer you get is to the object header. The actual data is usually inside a entries field. You need to calculate the offset from the class base to the field itself rather than just scanning for a temporary address in the heap.
Troubleshooting Checklist
- Identify if the target is Mono or IL2CPP (check for GameAssembly.dll vs Assembly-CSharp.dll).
- Locate the Static class instance. You cannot rely on heap addresses; you need a pointer path starting from a static module base.
- Check the class layout in dnSpy or IL2CppInspector to see the exact field offsets.
- Remember that generic types like Dictionary<K, V> have different memory footprints depending on the types they hold.
Are you guys using a custom scanner to find these, or are you manually tracing the static instances from the module base? Drop your methods for dealing with dynamic base addresses below.