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

后端 未结 3 797
花落未央
花落未央 2020-12-17 01:31

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 thir

相关标签:
3条回答
  • 2020-12-17 01:57

    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 );
    
    0 讨论(0)
  • 2020-12-17 02:02

    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.

    0 讨论(0)
  • 2020-12-17 02:19

    You can check the PE header yourself to read the IMAGE_FILE_MACHINE field. Here's a C# implementation that shouldn't be too hard to adapt to C++.

    0 讨论(0)
提交回复
热议问题