2

I tried googling but couldn't find any good source that explains the structure of memory access instructions like ldstr and call instructions

for example based on experience, the last byte of API/library call instructions is always 0x0A (let me know if I'm wrong), but why? what are the structure of the 4 bytes of call operands? what about operands of ldstr instructions?

because they are different from native apps, they are not raw offsets, they seem to be offsets into a table but i cannot find any post that explains this in detail?

the best thing i found is this :

https://www.red-gate.com/simple-talk/blogs/anatomy-of-a-net-assembly-clr-metadata-1/

but it still doesn't explain many things

4

the last byte of API/library call instructions is always 0x0A

It's because calls needs to have method (ref) as a parameter and methods are defined in the table that has an id of 0x0A.

Having bytes of the call like this 280600000A let's go one by one.

  • 0x28 - is the value for opcode 'call' and it takes one operand.
  • the rest of the opcode is the metadata token so basically the information which method should be called

But why 0x0A is at the end? It should be read as a little-endian so the value should be 0x0A000006. But what are the bytes?

From Wikipedia:

When CIL code uses metadata it does so through a metadata token. This is a 32-bit value where the top 8 bits identify the appropriate metadata table, and the remaining 24 bits give the index of the metadata in the table.

So the first value is the table id - and as I've mentioned the id of member's ref table is value 0x0A. And the rest is an index in the table (in our case 0x6).

More about the tables? Those are basically part of .NET metadata information, that can be seen when you open one in i.e. dnSpy

enter image description here

As one can see 0x0A is assigned to the MemberRef (containing both methods and fields references)

what about operands of ldstr instructions?

In this instance, the instruction has the following structure 72XXXX0070 and 0x70 indicates different stream - namely User defined strings or #US. The rest (again interpreted as a little-ending 32-bit val) is the offset (in bytes) in #US table.

Generally dnSpy is a great tool to verifying those values as one can metadata tables.

The linked article (and the whole series is a great resource) it does explain (I think) the structure but maybe indirectly - just find the information about metadata token.

We can induce from it the whole structure of a metadata token.

| improve this answer | |
  • Thanks for the great explanation, do you happen to know any other good reference or even a book that explains everything about structure of .NET files/IL instructions in a very detailed manner? what is the most detailed reference? – OneAndOnly Sep 6 at 14:46
  • Not sure if I can provide one reference. It is something I acquired by reading & exploring multiple sources. – Paweł Łukasik Sep 8 at 16:08
  • Multiple sources are fine too, would appreciate if you can share them. – OneAndOnly Sep 9 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.