1 2 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