Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out if a exe file is a .Net exe or regular exe?

This is not a duplicate off following SO question: How do I tell if a win32 application uses the .NET runtime.

How can I find out programatically if a given exe file is a .net exe file or a regular WIN32/WIN64 exe file?

The question is not about interrogating a running process but it's about an exe file and as the tags suggest, a solution written in VB.net or C# is not required.

I need a function with a signature such as:

// return true if filename is a exe file for .Net
bool IsExeFileDotNet(LPCTSTR filename)
{
   ...
}
like image 659
Jabberwocky Avatar asked Apr 12 '16 09:04

Jabberwocky


People also ask

How do I find the exe file of an application?

First, locate a shortcut that points to the application whose EXE you need to find, because you will need to open its properties window. If the shortcut is on your desktop, right-click it and select “Properties.”

How to check if an EXE file is safe?

5 simple ways to check if an .exe file is safe. 1 Check it with Windows itself 2 Upload the file to VirusTotal 3 Who is the publisher? 4 Run it in Windows Sandbox 5 Check the .exe’s network activity for suspicious behavior

How to check the exe file with Windows Defender?

How to check the .exe file with Windows Defender These days all Windows versions come with Windows Security (formerly Microsoft Defender), and Windows Security has a built in easy way to scan specific .exe files. If the file is on your desktop right click it and choose “scan with Microsoft Defender”.

How do I scan an EXE file in Windows?

If you found the .exe you want to scan in the Windows task manager and you're not sure of its location, then right click it and choose “open file location”. The file should then automatically be highlighted. Now right click the file once and scan it. If it's marked as safe, then it's probably safe to be on your PC.


Video Answer


2 Answers

One approach is to interrogate the PE header etc. for the correct flags. There are several links for further reading; here and here (and an older MSDN article here).

MS documentation on the PE header is available (with a license agreement).

The easiest may just be to list the dependent dlls (since this is for the main exe only) and look for the presence of mscoree.dll. The import table will include mscoree.dll and include and entry for the function _CorExeMain (from mscoree.dll). More links on this can be found here on SO and here on GitHub, that appears to be an extensive sample, and this article (on CodeGuru) with code for a function with the signature BOOL IsManaged(LPTSTR lpszImageName) that you require (license seems to restrict re-publishing).

like image 193
Niall Avatar answered Oct 22 '22 20:10

Niall


The olden standby was to read the target runtime version from the file with GetFileVersion(). It will fail with ERROR_BAD_FORMAT when the executable file does not contain the CLR header. Works in any bitness and any target architecture of the assembly. You'll have to use it like this:

#define USE_DEPRECATED_CLR_API_WITHOUT_WARNING
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
#include <assert.h>

bool IsExeFileDotNet(LPCWSTR filename)
{
    WCHAR buf[16];
    HRESULT hr = GetFileVersion(filename, buf, 16, NULL);
    assert(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
    return hr == S_OK;
}

Do note the use of USE_DEPRECATED_CLR_API_WITHOUT_WARNING to suppress a deprecation error, the MSCorEE api is liable to disappear in a future major release of .NET.

The non-deprecated way is to use ICLRMetaHost::GetFileVersion(), disadvantage is that it can only work when the machine has .NET 4 installed. Not exactly a major problem today. Looks like this:

#include <Windows.h>
#include <metahost.h>
#include <assert.h>
#pragma comment(lib, "mscoree.lib")

bool IsExeFileDotNet(LPCWSTR filename)
{
    ICLRMetaHost* host;
    HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (void**)&host);
    assert(SUCCEEDED(hr));
    if (hr == S_OK) {
        WCHAR buf[16];
        DWORD written;
        hr = host->GetVersionFromFile(filename, buf, &written);
        assert(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
        host->Release();
    }
    return SUCCEEDED(hr);
}

Other techniques that poke the executable file directly to look for the CLR header in the file are mentioned in this Q+A. How future-proof they may be is very hard to guess.

like image 27
Hans Passant Avatar answered Oct 22 '22 19:10

Hans Passant