capa icon indicating copy to clipboard operation
capa copied to clipboard

dotnet: detect OS

Open mike-hunhoff opened this issue 2 years ago • 11 comments

Research and implement if its possible to determine OS for .NET file; these should all be PEs so my best guess without further research is focusing on statically detecting the CLR

Maybe start with exploring TargetFrameworkAttribute?

mike-hunhoff avatar Feb 17 '23 23:02 mike-hunhoff

we need to update the rule format documentation to describe OS_ANY, too:

https://github.com/mandiant/capa-rules/blob/b035bb8d90e556f412b6ee9ef738ce6c68bbd9cd/doc/format.md#os

williballenthin avatar Feb 18 '23 20:02 williballenthin

we should definitely get (1) working as intended.

agree that we should do the research for (2). that's probably a #good-first-issue. then, once we know if it's possible and what to look for, we can tweak the behavior of the .NET feature extractor.

williballenthin avatar Feb 18 '23 20:02 williballenthin

we need to update the rule format documentation to describe OS_ANY, too:

https://github.com/mandiant/capa-rules/blob/b035bb8d90e556f412b6ee9ef738ce6c68bbd9cd/doc/format.md#os

see #1324

mike-hunhoff avatar Feb 23 '23 18:02 mike-hunhoff

Hello @mike-hunhoff @williballenthin, it's Colton, one of the FLARE interns from last summer! Do you mind if I take a crack at this one?

colton-gabertan avatar Mar 15 '23 22:03 colton-gabertan

Hello @colton-gabertan! Absolutely, go for it! Please let us know if you have any questions

mike-hunhoff avatar Mar 15 '23 22:03 mike-hunhoff

Thanks for the chance!

Off the bat, after looking into detecting the CLR statically, I think that for the purpose of purely detecting the OS via looking for the specific CLR's may not be the best route (at least while CAPA is statically analyzing the binaries ;) ). I say this because, yes the CLR's are platform-specific, but it's more or less the CLR's job to locate the assembly to be ran and not the other way around...at least to my understanding.

I did dig more into Attributes from there, and found something that may be pretty interesting. Microsoft released a platform compatibility analyzer that helps developers check whether or not their applications would be able to be ran cross-platform/OS. The way it does it is that specific .NET core libraries and api calls are now labeled with attributes that indicate what platform they are for.

These attributes may be seen as:

  • OSPlatformAttribute
  • ObsoletedOSPlatformAttribute
  • SupportedOSPlatformAttribute
  • SupportedOSPlatformGuardAttribute
  • UnsupportedOSPlatformAttribute
  • UnsupportedOSPlatformGuardAttribute

Example via documentation:

[SupportedOSPlatform("windows"),...]
public class apiClass
{
}

With this in mind, if we can figure out specifically which functions are labeled with which attributes, it could be one way to help detect the OS that the binaries were designed for. I can try to create a nursery rule for this as a Proof of Concept, but after looking at the CAPA repo, it might be more suited to go into the lib namespace if designed this way.

Any thoughts on this approach?

My reading:

  • https://learn.microsoft.com/en-us/dotnet/api/system.runtime.versioning?view=net-7.0
  • https://learn.microsoft.com/en-us/dotnet/standard/analyzers/platform-compat-analyzer
  • https://learn.microsoft.com/en-us/dotnet/standard/class-libraries?source=recommendations

colton-gabertan avatar Mar 17 '23 00:03 colton-gabertan

Thanks for all of your research @colton-gabertan! 🚀

Ideally we can identify a solution that works for all .NET files processed by capa.

My initial concern with your approach is that it is unclear if the attributes you describe are present in all .NET files. Do you have additional insight here? Also, capa does not process .NET attributes so there is no way presently to write a rule to detect use of specific attributes. This is a feature I've considered adding in the past but it may be a significant undertaking as a I do not believe dnfile supports attribute parsing, yet.

What are your thoughts on using TargetFrameworkAttribute to detect specific operating systems? I've come across this in the past but did not dig very deep. I'm interested to hear your thoughts based on the attribute research you've done here.

mike-hunhoff avatar Mar 17 '23 14:03 mike-hunhoff

@mike-hunhoff

I've taken a deeper dive into TargetFrameworkAttribute and it seems to only provide useful info for assemblies compiled against .NET 4+ in terms of the specific framework, anything below will return a general result i.e. 2, 3, or 3.5. However, this article, provides a bit of C# code that can be used as an extension method to extract this information. With framework info we can cross-check against OS's that support those versions; however, I still feel that this would allow us to only make educated guesses at best as multiple OS's may support the same versions.

The source code for the TargetFrameworkAttribute class shows that the info is literally two string members of the class, but doesn't go into much detail as to how those strings are assigned when ran against an assembly. Based on how attributes work, they're an extension of a pefile's metadata. So, in this light, I'm hoping that the info is parse-able from somewhere within the metadata tables of the pefiles.

In the code from the article above, there is a call to GetCustomAttributes(), which I found the source code for in order to see how it parses the file for it. However, the code itself is a bit ambiguous. If my theory is correct, then pulling version info should be relatively easy to integrate into CAPA, just using the pefile/dnfile module. I've also confirmed that the layout of the tables is currently undocumented in ECMA-335, unfortunately.

So, my solution for now would probably just to essentially pull any "unmanaged" imports and try cross-reference them with any from the Windows/Linux/MacOS apis to determine the OS. This task sounds very tedious, though.

colton-gabertan avatar Mar 18 '23 02:03 colton-gabertan

did dig more into Attributes from there, and found something that may be pretty interesting. Microsoft released a platform compatibility analyzer that helps de

On that note, a wider solution would be if we see the .NET file try to dynamically import specifically a .dll we may be able to label it as Windows, if it tries to import a .so.* or a .dylib that may be indicative of a linux-based system. However, the downfalls are that CAPA will only even attempt this if the binary tries to import things, and any cross-platform-functional binaries will be labeled as working on all.

colton-gabertan avatar Mar 18 '23 02:03 colton-gabertan

@mike-hunhoff

As per our email discussion, this enhancement is likely to evolve into a larger project. Unassigning myself from the issue for now.

colton-gabertan avatar Mar 28 '23 01:03 colton-gabertan

I can't find any documentation stating whether the OS attributes (OSPlatformAttribute, ObsoletedOSPlatformAttribute, etc.) are in the method header, method body, or a MetaDataTable. Given the various string values I am seeing in examples, I suspect it is in neither a MetaDataTable nor the method header. If you know of some other .NET parsing program that is able to identify these guard conditions then let me know, either by creating an Issue on dnfile or just @ me in this thread.

I am working on method header parsing in a branch on dnfile, but it has turned into a lot more work than I initially anticipated

malwarefrank avatar Jul 14 '23 02:07 malwarefrank