| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 
 | /*
Note: GetBinaryType() and SHGetFileInfo(SHGFI_EXETYPE) always fail on DLLs.
ImageLoad() and the artisanal code work on both EXEs and DLLs,
and bitness of the program or examined module doesn't influence this part.
*/
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <tchar.h>
 
/*
A PE file contains an IMAGE_DOS_HEADER that contains the offset of an IMAGE_NT_HEADERS(32/64) structure.
The IMAGE_NT_HEADERS(32/64) structure, in turn, contains:
	A 4-byte signature "PE\0\0"
	A bitness-independent IMAGE_FILE_HEADER structure that contains the "machine" field we want,
		as well as the linker timestamp (which we want in another code).
	An IMAGE_OPTIONAL_HEADER(32/64) structure.
 
This function returns 0 if successful and -1  if it fails.
*/
static int ReadPEFileMachine(FILE *pfIn, WORD *pMachine, BOOL bVerbose)
{
	IMAGE_DOS_HEADER imageDosHeader = {0};
	size_t nRead = 0;
 
	if(pfIn == NULL || pMachine==NULL)
	{
		errno = EINVAL;
		return -1;
	}
 
 
	nRead = fread(&imageDosHeader, sizeof(imageDosHeader), 1, pfIn);
	if(nRead != 1)
	{
		if(bVerbose)
			_ftprintf(stderr, _T("fread(IMAGE_DOS_HEADER) returned %d (Error: C %d)\n"), nRead, errno);
		return -1;
	}
 
	{
		LONG offsetPE = imageDosHeader.e_lfanew;
		DWORD signaturePE = 0;
		IMAGE_FILE_HEADER imageFileHeaderPE = {0};
		int seeked;
 
		/*if(bVerbose)
			_ftprintf(stderr, _T("IMAGE_DOS_HEADER contains offset %ld to the PE header\n"), offsetPE);*/
		seeked = fseek(pfIn, offsetPE, SEEK_SET);
		if(seeked != 0)
		{
			if(bVerbose)
				_ftprintf(stderr, _T("fseek returned %d (Error: C %d)\n"), seeked, errno);
			return -1;
		}
 
		nRead = fread(&signaturePE, sizeof(signaturePE), 1, pfIn);
		if(nRead != 1)
		{
			if(bVerbose)
				_ftprintf(stderr, _T("fread(signature) returned %d (Error: C %d)\n"), nRead, errno);
			return -1;
		}
 
		nRead = fread(&imageFileHeaderPE, sizeof(imageFileHeaderPE), 1, pfIn);
		if(nRead != 1)
		{
			if(bVerbose)
				_ftprintf(stderr, _T("fread(IMAGE_FILE_HEADER) returned %d (Error: C %d)\n"), nRead, errno);
			return -1;
		}
 
		/*_ftprintf(stderr, _T("fread(IMAGE_FILE_HEADER) succeeded (Machine: 0x%04X)\n"), imageFileHeaderPE.Machine);*/
		*pMachine = imageFileHeaderPE.Machine;
		return 0;
	}
}
 
static int GetPEFileMachine(LPCTSTR filePath, WORD *pMachine, BOOL bVerbose)
{
	FILE* pfIn = _tfopen(filePath, _T("rb"));
	int ret = -1;
	if(pfIn == NULL)
	{
		if(bVerbose)
			_ftprintf(stderr, _T("fopen_s failed (Error: C %d)\n"), errno);
		return -1;
	}
 
	ret = ReadPEFileMachine(pfIn, pMachine, bVerbose);
	fclose(pfIn);
	return ret;
}
 
int ReadAndPrintBitness(LPCTSTR filePath)
{
	/*Note: From winnt.h:
		#define IMAGE_FILE_MACHINE_I386              0x014c  // Intel 386.
		#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
	*/
 
	WORD machine = (WORD)-1;
 
	_tprintf(_T("ThisProcesBitness: %d - FileToTest: %s\n"), (int)(sizeof(void*)*CHAR_BIT), filePath);
 
	if(GetPEFileMachine(filePath, &machine, TRUE) == 0)
	{
		_tprintf(_T("GetPEFileMachine succeeded (Type: 0x%04X)\n"), machine);
		switch(machine)
		{
		case IMAGE_FILE_MACHINE_I386: _tprintf(_T("%s is a 32-bit executable."), filePath); break;
		case IMAGE_FILE_MACHINE_AMD64: _tprintf(_T("%s is a 64-bit executable."), filePath); break;
		default: _putts(_T("Unknown executable type.")); break;
		}
		return 0;
	}
	else
		return -1;
}
 
int _tmain(int argc, _TCHAR *argv[])
{
	if(argc < 2)
	{
		_putts(_T("Usage: GetBitness <filePath>"));
		return EXIT_FAILURE;
	}
 
	if(ReadAndPrintBitness(argv[1]))
		return EXIT_FAILURE;
	return EXIT_SUCCESS;
} | 
Partager