 Welcome to MavAnalysis for Head Shocks. I'm currently implementing .NET into POTX Analyzer. So a lot of the things that I learned about .NET Metadata are quite useful for MavAnalysis if you are analyzing .NET malware. So I would like to share some of that knowledge with you, especially about the Metadata and Streams and how you can apply this to understand things you see in the Hex Editor. So let's check it out. The .NET file is a special portable executable file. So like every portable executable file, it has a .STUB and PEE headers that follow after. One part of the PEE headers are the data directories in the optional header. If you haven't watched it yet, check out my video in the PEE file format. The data directory has an entry called CLR Runtime header or COM Runtime, depending on the tool being used. For instance, in PEE Studio, it's called COM Runtime. This entry points to the header data structure for .NET, which resides in a section, typically the .text section. But it can really have any names and section names are made only for humans. This entry is the last in the data directory. It's at 10 hex or 16 decimal. The CLR header itself points, among others, to an important structure, the Metadata header. This structure starts with magic bytes, which are also the ASCII characters PSJB. This stands for the initials of the four CLR team founders. You can easily recognize this magic number in the hex editor. It is also called storage signature. Furthermore, we have the storage header and several stream headers. There are six named streams in .NET. Globally unique identifiers. Entries in the streams here have a fixed length of 16 bytes. The string stream contains method names, class names, and so on. The blob stream stores internal Metadata binary objects, such as before values and signatures. It's a heap. The US stream contains user-defined strings. These are strings referenced in the program as code. They are UTF-16 and coded. The last two streams are the optimized and unoptimized Metadata stream. One .NET file can only have one of those. The hash tilde is the optimized one, the hash minus the unoptimized one. These contain the Metadata tables and reference three of the other streams, blob, strings, and GUID. They also reference the actual IL code instructions, which in turn may reference user-defined strings on the US heap. In a hex editor, you can distinguish strings and US streams by checking whether the strings are UTF-8 or UTF-16. Now, let's see how Metadata is referencing certain parts of the assembly, for instance, a normal method. The Metadata stream, either compressed or uncompressed, contains among others a method table. The parameters of a method are referenced in the param table. Now, there are several different places where certain parts of the method are stored. The method name is stored UTF-8 in the string stream. The method signature is stored in the blob stream. The method body, which contains IL instructions, is stored somewhere in the file outside of streams. If the method body references any string constants like hello world, it does that by providing an offset to the US stream. Last but not least, the names of the parameters are also on the string stream. So we have at least five different places where method information is stored in the file. Why is this important to know? Because you can recognize some of those places merrily by looking at a file in a hex editor. If you were to write a signature to detect a malware file, you will quickly be able to put those areas and strings into context. For instance, this is a Metadata header for a .NET file. You see the magic bytes and the named stream headers. You see at first glance whether the Metadata stream is optimized or unoptimized. In this case, it is optimized. If you want to find the Metadata header, simply search for bsjb using the search function. The header also contains a version string of the CLR version. If you scroll a bit, you will find the string stream. The strings in here are UTF-8 and always zero-terminated. If you were to write a signature detection, you will include the zero-terminators front and back, since the heap is guaranteed to start with an empty string. If you see strings ending with k underscore underscore backing field, these are simply fields accessed by getters and setters. The actual name of the field is a portion before the k underscore underscore backing field. UTF-16 strings are part of blob or us. They are preceded by their lengths. Since this is a SHA1 string and preceded by nine. In signatures, you can include the length here as well. The US strings are not zero-terminated, though. Depending on their contents, they are followed by zero or one. To see the actual Metadata values, check CFFExplorer or dnspy. So as you can see, I changed the format a little bit, I pre-recorded everything I wanted to say instead of doing the explanations live. Let me know if that's better than before, I think it might be. So, something else I wanted to mention is that the PE resources, Portable Executable Resources and Imports and Exports are different than the .NET resources and Imports and Exports. So these are two different data structures and they are used at the same time. So if someone's talking about resources, what you see in resource hacker are the PE resources. What you see in dnspy, for instance, are the .NET resources. So two different things, don't confuse them. Yeah, and I think that's it already. If you have any questions, please put them below. I will probably post more videos about this topic because now I'm really diving deep into this. Ciao, see you next time!