PESecurity icon indicating copy to clipboard operation
PESecurity copied to clipboard

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

Open blincoln-bf opened this issue 2 weeks ago • 0 comments

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.

blincoln-bf avatar Jan 12 '26 18:01 blincoln-bf