UPDATE! The community will be go into read-only on April 19, 8am Pacific in preparation for migration on April 21. Read more.
UPDATE! The community will be go into read-only on April 19, 8am Pacific in preparation for migration on April 21.Read more.

Determining Architecture Type of Windows Binary File

Absent Member.
Absent Member.
0 0 4,042
0 Likes
Most of the product developments are now focused towards 64bit Architecture. And in the process of porting from 16bit to 32bit and now on to 64bit we encounter many technical problems. We are addressing one such problem here. The problem is that when a single application which supports both 32bit(x86) and 64bit(AMD64,IA64) is installed in 64bit Operating System, then How to determine which flavor of application is actually installed. This is the case when such application won’t register its ARCH TYPE in windows registry.

The use case is that when another application wants to know which flavor of application-1 is been installed to proceed with their installation or other application specific task, then this information comes very handy for developers.

The code below will help you to determine Machine Type of given binary. You need to edit the value of pszPathname to point to binary file that you want to test.


//------------------------------------------------------------------
// GetMachineType.cpp - Get MachineType of Given Binary File
//------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>

// It’s done as vc++ 6.0 wint.h does not have the IMAGE_FILE_MACHINE_AMD64 declaration
#ifndef IMAGE_FILE_MACHINE_AMD64
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#endif

//------------------------------------------------------------------
LPVOID MapFile(char *szFileName, HANDLE *hFile, HANDLE *hMap);
DWORD GetMachineType(LPBYTE pIn);
void UnmapFile(HANDLE hFile, HANDLE hMap, LPVOID pMem);

// Start of the application………
int main(int)
{
HANDLE hFile, hMap;
LPVOID pIn;
DWORD Stat;

char *pszPathname = "Enter Path To Your Binary File"; // C:\\directory\\novell\\binary.exe

// Make a (memory) file mapping for the binary
if ((pIn = MapFile(pszPathname, &hFile, &hMap)) == NULL) {
printf("Error: couldn't open or map %s\n", pszPathname);
return ERROR_OPEN_FAILED;
}

if ((Stat = GetMachineType((LPBYTE)pIn)) != NO_ERROR) {

switch(Stat)
{
case IMAGE_FILE_MACHINE_I386:
printf("MachineType of %s is = %s\n", pszPathname, "I386 (x86)");
break;

case IMAGE_FILE_MACHINE_IA64:
printf("MachineType of %s is = %s\n", pszPathname, "IA64 (Intel IPF)");
break;

case IMAGE_FILE_MACHINE_AMD64:
printf("MachineType of %s is = %s\n", pszPathname, "AMD64 (x64)");
break;

default:
printf("Unknown MachineType\n");
}
}


// Unmap it, memory changes will be written to the image
UnmapFile(hFile, hMap, pIn);

return NO_ERROR;
}

// Get the memory mapping of windows binary file …..
LPVOID MapFile(char *szFile, HANDLE *hFile, HANDLE *hMap)
{
// Create a memory mapping for the specified file
DWORD Size;

*hFile = *hMap = NULL;
if ((*hFile = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) ==
INVALID_HANDLE_VALUE) {
return NULL;
}

Size = GetFileSize(*hFile, NULL);

if ((*hMap = CreateFileMapping(*hFile, NULL, PAGE_READWRITE, 0,
Size, NULL)) == NULL) {
CloseHandle(hFile);
return NULL;
}
return MapViewOfFile(*hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
}

// This will return dword machine type of the binary…..
DWORD GetMachineType(LPBYTE pIn)
{
long lPeStart;
IMAGE_NT_HEADERS *pNtHdr;

// See where the PE image header is located
if ((((IMAGE_DOS_HEADER *)pIn)->e_magic
!= IMAGE_DOS_SIGNATURE) ||
((lPeStart = ((IMAGE_DOS_HEADER *)pIn)->e_lfanew) == 0L)) {
return ERROR_BAD_EXE_FORMAT;
};

pNtHdr = (IMAGE_NT_HEADERS *)(pIn + lPeStart);

if(pNtHdr->FileHeader.Machine != 0 )
{
return pNtHdr->FileHeader.Machine;
}

return NO_ERROR;
}

// Unload mapped memory…… cleanup …!!!!
void UnmapFile(HANDLE hFile, HANDLE hMap, LPVOID pMem)
{
if (pMem != NULL)
UnmapViewOfFile(pMem);

if (hMap != NULL)
CloseHandle(hMap);

if (hFile != NULL)
CloseHandle(hFile);

return ;
}



Here what we have done in above program:


  • Get the binary filename from user.


  • The Portable Executable (PE) format is a file format for executables, object code, and DLLs, used in 32-bit and 64-bit versions of Windows operating systems. In MapFile(…) function we are getting image of binary file in PE format that is basically a data structure.

    For more information on PE Format refer to http://en.wikipedia.org/wiki/Portable_Executable


  • GetMachineType(..) function will go through the structure and return the structure element i.e Machine. We compare this return values to predefined set of architecture type to determine string equivalent of machine type of binary file.


  • Finally we need to cleanup mapped memory using UnmapFile() function.



The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.