Recently, in this question, I've asked how to get a raw memory address of class in C# (it is a crude unreliable hack and a bad practice, don't use it unless you really need it). I've succeeded, but then a problem arose: according to this article, first 2 words in the class raw memory representation should be pointers to SyncBlock and RTTI structures, and therefore the first field's address must be offset by 2 words [8 bytes in 32-bit systems, 16 bytes in 64-bit systems] from the beginning. However, when I dump first bytes from memory at the object location, first field's raw offset from the object's address is only 1 32-bit word (4 bytes), which doesn't make any sense for both types of systems. From the question I've linked:
class Program
{
class TestClass
{
uint a = 0xDEADBEEF;
}
static void Main(string[] args)
{
byte[] cls = new byte[16];
var t = new TestClass();
var ptr = Voodoo.getPtrToObject(t);
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(ptr.ToInt32()))); //This is the class raw address
Marshal.Copy(ptr,cls,0,16);
//Prints first 16 bytes from that address; note the field 'a' value!
Console.WriteLine(BitConverter.ToString(cls));
Console.ReadLine();
}
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73
That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/
Why is so? Maybe I've just got the address wrong, but how and why? And if I didn't, what could be wrong anyway? Maybe, if that article is wrong, I simply misunderstood what managed class header looks like? Or maybe it doesn't have that Lock pointer - but why and how is this possible?..
(These are, obviously, only a few possible options, and, while I'm still going to carefully check each one I can predict, wild guessing cannot compare in both time and accuracy to a correct answer.)
Thanks in advance!
Aucun commentaire:
Enregistrer un commentaire