Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32 API to tell whether a given binary (EXE or DLL) is x86, x64, or ia64

I am trying to find a programmatic way to tell if a binary is x86, x64, or ia64.

Platform: Windows. Language: c/c++.

Background: Before trying to load a third-party dll, I need to find out its bitness.

Appreciate any pointers.

like image 812
user15071 Avatar asked Jun 09 '09 18:06

user15071


2 Answers

For EXEs

use GetBinaryType(...)

Here is same question for manged exe.

For DLLs (and EXEs)

Use the ImageNtHeader(...) to get the PE data of the file and then check the IMAGE_FILE_HEADER.Machine field.

Here is some code I found using Google Code Search

No Cleanup and NO error checking

// map the file to our address space
// first, create a file mapping object
hMap = CreateFileMapping( 
  hFile, 
  NULL,           // security attrs
  PAGE_READONLY,  // protection flags
  0,              // max size - high DWORD
  0,              // max size - low DWORD      
  NULL );         // mapping name - not used

// next, map the file to our address space
void* mapAddr = MapViewOfFileEx( 
  hMap,             // mapping object
  FILE_MAP_READ,  // desired access
  0,              // loc to map - hi DWORD
  0,              // loc to map - lo DWORD
  0,              // #bytes to map - 0=all
  NULL );         // suggested map addr

peHdr = ImageNtHeader( mapAddr );
like image 86
Shay Erlichmen Avatar answered Oct 05 '22 22:10

Shay Erlichmen


I open-sourced a project on Github that checks for VC++ redistributable DLLs specifically and there's a code snippet I created based off of the function in Shay's answer that successfully finds, loads, and inspects DLLs for x86 / x64 compatibility.

Full code snippet below:

/******************************************************************
Function Name:  CheckProductUsingCurrentDirectory
Description:    Queries the current working directory for a given binary.
Inputs:         pszProductFolderToCheck - the product name to look up.
pBinaryArchitecture - the desired processor architecture
of the binary (x86, x64, etc..).
Results:        true if the requested product is installed
false otherwise
******************************************************************/
bool CheckProductUsingCurrentDirectory(const LPCTSTR pszProductBinaryToCheck, Architecture pBinaryArchitecture){
        bool bFoundRequestedProduct = false;

        //Get the length of the buffer first
        TCHAR currentDirectory[MAX_PATH];
        DWORD currentDirectoryChars = GetCurrentDirectory(MAX_PATH, currentDirectory);

        //exit if couldn't get current directory
        if (currentDirectoryChars <= 0) return bFoundRequestedProduct;

        TCHAR searchPath[MAX_PATH];
        //exit if we couldn't combine the path to the requested binary
        if (PathCombine(searchPath, currentDirectory, pszProductBinaryToCheck) == NULL) return bFoundRequestedProduct;

        WIN32_FIND_DATA FindFileData;
        HANDLE hFind= FindFirstFile(searchPath, &FindFileData);

        //exit if the binary was not found
        if (hFind == INVALID_HANDLE_VALUE) return bFoundRequestedProduct;

        HANDLE hFile = CreateFile(searchPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
        if (hFile == INVALID_HANDLE_VALUE) goto cleanup;

        HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, pszProductBinaryToCheck);
        if (hMapping == INVALID_HANDLE_VALUE) goto cleanup;

        LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
        if (addrHeader == NULL) goto cleanup; //couldn't memory map the file

        PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader);
        if (peHdr == NULL) goto cleanup; //couldn't read the header

        //Found the binary, AND its architecture matches. Success!
        if (peHdr->FileHeader.Machine == pBinaryArchitecture){
                bFoundRequestedProduct = true;
        }

cleanup: //release all of our handles
        FindClose(hFind);
        if (hFile != INVALID_HANDLE_VALUE)
                CloseHandle(hFile);
        if (hMapping != INVALID_HANDLE_VALUE)
                CloseHandle(hMapping);
        return bFoundRequestedProduct;
}

This question and Shay's answer were helpful to me while I was creating this, so I thought I'd post the project here.

like image 34
Aaronontheweb Avatar answered Oct 05 '22 23:10

Aaronontheweb