Article

Determining Architecture Type of Windows Binary File

article
Reads:

2231

Score:
5
5
1
 
Comments:

0

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.




User Comments

© 2009 Novell, Inc. All Rights Reserved.