.NET detection - false negative for .NET Core / .NET 5.0 and later
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.