Skip to content

.NET detection - false negative for .NET Core / .NET 5.0 and later #25

@blincoln-bf

Description

@blincoln-bf

Hi.

The method you're using to determine if a binary is .NET does not work correctly for .exe files that target .NET Core (at least not .NET Core 3.1, which is the only version I have the targeting package for), or .NET 5.0 and later (as opposed to .NET Framework 4.x and earlier).

e.g.:

> Get-PESecurity -file "C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_Core_3.1\CSharpExample-DotNET_Core_3.1\bin\Debug\netcoreapp3.1\CSharpExample-DotNET_Core_3.1.exe"

FileName         : C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_Core_3.1\CSharpExample-DotNET_Core_3.1\bin\Debug\netcoreapp3.1\CSharpExample-DotNET_Core_3.1.exe
ARCH             : AMD64
DotNET           : False
ASLR             : True
DEP              : True
Authenticode     : False
StrongNaming     : N/A
SafeSEH          : N/A
ControlFlowGuard : True
HighentropyVA    : True

> Get-PESecurity -file "C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_9\CSharpExample-DotNET_9\bin\Debug\net9.0\CSharpExample-DotNET_9.exe"

FileName         : C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_9\CSharpExample-DotNET_9\bin\Debug\net9.0\CSharpExample-DotNET_9.exe
ARCH             : AMD64
DotNET           : False
ASLR             : True
DEP              : True
Authenticode     : False
StrongNaming     : N/A
SafeSEH          : N/A
ControlFlowGuard : True
HighentropyVA    : True

It does still seem to work for DLLs:

> Get-PESecurity -file "C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_Core_3.1\CSharpExample-DotNET_Core_3.1\bin\Debug\netcoreapp3.1\CSharpExample-DotNET_Core_3.1.dll"

FileName         : C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_Core_3.1\CSharpExample-DotNET_Core_3.1\bin\Debug\netcoreapp3.1\CSharpExample-DotNET_Core_3.1.dll
ARCH             : I386
DotNET           : True
ASLR             : True
DEP              : True
Authenticode     : False
StrongNaming     : False
SafeSEH          : N/A
ControlFlowGuard : N/A
HighentropyVA    : N/A

> Get-PESecurity -file "C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_9\CSharpExample-DotNET_9\bin\Debug\net9.0\CSharpExample-DotNET_9.dll"

FileName         : C:\Users\BenLincoln\source\repos\CSharpExample-DotNET_9\CSharpExample-DotNET_9\bin\Debug\net9.0\CSharpExample-DotNET_9.dll
ARCH             : I386
DotNET           : True
ASLR             : True
DEP              : True
Authenticode     : False
StrongNaming     : False
SafeSEH          : N/A
ControlFlowGuard : N/A
HighentropyVA    : N/A

I'd recommend seeing if you can implement a PowerShell equivalent of Microsoft's recommended way to determine if a file is a .NET assembly or not instead.

In case it helps, I built the default C# "Hello, World" code (and added a stub DLL if there wasn't one created by default) for the following .NET versions:

  • .NET Framework 2.0
  • .NET Framework 3.0
  • .NET Framework 4.0
  • .NET Framework 4.8
  • .NET Core 3.1
  • .NET 5.0
  • .NET 6.0
  • .NET 7.0
  • .NET 8.0
  • .NET 9.0

You can grab them here: https://www.beneaththewaves.net/CSharp_Examples-2025-01-12-01.zip

On a related note, do you know of any documentation indicating that the binary mitigation flags reported by this tool make sense in the context of a .NET assembly? I would think that because it's all bytecode, ASLR and DEP (in addition to SafeSEH, CFG, and High-Entropy VA) don't apply - that it would be the equivalent flags for the .NET interpreter binary installed on the system that matter - but I haven't been able to find solid information one way or the other.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions