用c判断exe是32位还是64位的?

wula0010 2019-05-23 06:29:33
现在写一个程序,要判断exe文件为32位还是64位,好做不同处理,我的程序本事可以32位,也可以64位,该怎么判断?

参考:https://blog.csdn.net/perry_xiao/article/details/7930577,行不通,随便找几个exe文件测试,我发现imageNtHeaders.FileHeader.Machine =0,未知的机器类型,也没看到IMAGE_FILE_MACHINE_IA64 和 IMAGE_FILE_MACHINE_I386。

参考:https://blog.csdn.net/reversalc/article/details/8022977,想根据NT头的OptionalHeader大小来判断,发现不行。如果我的程序是64位的,NT头的OptionalHeader大小是240,如果是32位的,NT头的OptionalHeader大小是224,就是说这个NT头的大小是根据我的程序来的,而不是目标程序来的,如果我是32位程序,读64位的NT头,肯定错误,如果我是64位的程序,读32位程序的NT头也是错误的。


所以,谁有办法通过c程序判断一个程序是32位还是64位?
...全文
364 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
God4 2019-10-22
  • 打赏
  • 举报
回复
主要代码如下:

// 获取机器标志码
// -1 打开文件失败
// -2 读取文件失败
// -3 文件格式错误
// 0 任何处理器
// 0x14c x86处理器
// 0x8664 x64处理器
// 0x166 MIPS处理器
// 0x1C0 ARM处理器
INT GetMachine(const TCHAR * szFilePath)
{
// _tprintf(TEXT("%s\n"), szFilePath);

// 打开文件
FILE * fp = _tfopen(szFilePath, TEXT("rb"));
if( fp == NULL )
{
return -1;
}

// 获取文件长度
long len = filelength(fileno(fp));
if( len < 0 )
{
fclose(fp);
return -1;
}

// 文件格式错误
if( len < 0x40 )
{
fclose(fp);
return -3;
}

WORD buf;

// 读取MZ文件头
if( fread(&buf, 1, 2, fp) != 2 )
{
fclose(fp);
return -2;
}

// 文件格式错误
if( buf != 0x5A4D )
{
fclose(fp);
return -3;
}

// 移到PE头偏移
if( fseek(fp, 0x3C, SEEK_SET) )
{
fclose(fp);
return -2;
}

// 读取PE头偏移
if( fread(&buf, 1, 2, fp) != 2 )
{
fclose(fp);
return -2;
}

// 文件格式错误
if( len < buf + 6 )
{
fclose(fp);
return -3;
}

// 移到PE头
if( fseek(fp, buf, SEEK_SET) )
{
fclose(fp);
return -2;
}

// 读取PE头
if( fread(&buf, 1, 2, fp) != 2 )
{
fclose(fp);
return -2;
}

// 文件格式错误
if( buf != 0x4550 )
{
fclose(fp);
return -3;
}

// 移到机器码
if( fseek(fp, 2, SEEK_CUR) )
{
fclose(fp);
return -2;
}

// 读取机器码
if( fread(&buf, 1, 2, fp) != 2 )
{
fclose(fp);
return -2;
}

fclose(fp);
return buf;
}

  如果要检测64位系统System32目录下的文件,需要把文件重定向关闭:

BOOL DisableWow64FsRedirection()
{
typedef BOOL (WINAPI* WOW64DISABLEWOW64FSREDIRECTION)(PVOID *OldValue);
WOW64DISABLEWOW64FSREDIRECTION Wow64DisableWow64FsRedirection;

HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32.dll"));
if( hKernel32 == NULL )
{
return FALSE;
}

Wow64DisableWow64FsRedirection = (WOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(hKernel32, "Wow64DisableWow64FsRedirection");
if( Wow64DisableWow64FsRedirection == NULL )
{
return TRUE;
}

PVOID OldValue = NULL;
if( Wow64DisableWow64FsRedirection(&OldValue) == FALSE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
{
return FALSE;
}

return TRUE;
}
God4 2019-10-22
  • 打赏
  • 举报
回复
https://www.cnblogs.com/God4/articles/11721559.html
关于exe或dll等PE格式文件32位还是64位的检测

代码很简单,工具审核通过后传上去。
636f6c696e 2019-05-27
  • 打赏
  • 举报
回复
https://blog.csdn.net/jiangqin115/article/details/45562161?utm_source=blogxgwz8
wula0010 2019-05-27
  • 打赏
  • 举报
回复
查winnt.h #define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian #define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian #define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP #define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian #define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 #define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian #define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian #define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5 #define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian #define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian #define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian #define IMAGE_FILE_MACHINE_AM33 0x01d3 #define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian #define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 #define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 #define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS #define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS #define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 #define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon #define IMAGE_FILE_MACHINE_CEF 0x0CEF #define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) #define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian #define IMAGE_FILE_MACHINE_CEE 0xC0EE 从这个定义看,只是处理器的类型而已,不能作为判断程序是32位还是64位,还有IMAGE_FILE_MACHINE_UNKNOWN这样的值呢........
wula0010 2019-05-27
  • 打赏
  • 举报
回复
希望谁能有更好的办法,或者指出我的程序的错误在哪里....................
wula0010 2019-05-27
  • 打赏
  • 举报
回复
在32位程序里调用hLibrary = LoadLibrary(szFileName); 如果是32位程序,hLibrary肯定不为空,64为程序hLibrary肯定为空。程序如下,编译成32位的,找个大家都能下载的程序,360杀毒64位.exe,hLibrary为空,说明是64位程序,但是wWord1 为276(x10b),说明64位程序的Magic不一定是0x2xx。现在我程序就用hLibrary = LoadLibrary(szFileName) 来判断了.........

#include "stdafx.h"
#include <Windows.h>


int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hFile;
	DWORD dwFileSize;
	//char szFileName[] = "D:\\Windows技术详解\\Result\\X64Test\\Debug\\X64Test1.exe"; 
	char szFileName[] = "D:\\Windows技术详解\\Result\\X64Test\\Debug\\360杀毒64位.exe"; 
	BOOL bRet = FALSE;
	BOOL bFileX64 = FALSE;
	HMODULE hLibrary;

	hLibrary = LoadLibrary(szFileName);

	if (NULL != hLibrary)
	{
		FreeLibrary(hLibrary);
		bFileX64 = FALSE;
	}
	else
	{
		bFileX64 = TRUE;
	}

	hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	dwFileSize = GetFileSize(hFile, 0);

	BYTE *pData = new BYTE[dwFileSize];
	if (NULL == pData)
	{
		return bRet;
	}
	DWORD dwBytesRead = 0;
	ReadFile(hFile, pData, dwFileSize, &dwBytesRead, NULL);
	CloseHandle(hFile);

	WORD wWord = *(WORD*)(pData + 0x3c);

	wWord = wWord + 0x18;

	WORD wWord1 = *(WORD*)(pData + wWord);

	return 0;
}
lv12138 2019-05-27
  • 打赏
  • 举报
回复
给我个下载码给我个下载码给我个下载码
wula0010 2019-05-27
  • 打赏
  • 举报
回复
引用 22 楼 stherix 的回复:
[quote=引用 20 楼 wula0010 的回复:] 这个word是imageNtHeaders.FileHeader.Machine ,我还是不认为通过这个可以判断程序是32位还是64位的,看我上面贴的winnt.h里的定义,这个只是处理器的类型。 我最后还是通过LoadLibrary来判断的,.......
我给你的方法,并不是读文件头里的imageNtHeaders.FileHeader.Machine,这个有可能不准确 而是读可选头的Magic字,这两者不是同一个东西![/quote] 是我搞错了,你是对的
stherix 2019-05-27
  • 打赏
  • 举报
回复
引用 20 楼 wula0010 的回复:
这个word是imageNtHeaders.FileHeader.Machine ,我还是不认为通过这个可以判断程序是32位还是64位的,看我上面贴的winnt.h里的定义,这个只是处理器的类型。 我最后还是通过LoadLibrary来判断的,.......
我给你的方法,并不是读文件头里的imageNtHeaders.FileHeader.Machine,这个有可能不准确 而是读可选头的Magic字,这两者不是同一个东西!
wula0010 2019-05-27
  • 打赏
  • 举报
回复
还是我搞错了, 把imageNtHeaders.FileHeader.Machine 和 OptionalHeader.Magic搞混了,根据OptionalHeader.Magic应该是可以的。
wula0010 2019-05-27
  • 打赏
  • 举报
回复
引用 19 楼 stherix 的回复:
[quote=引用 18 楼 wula0010 的回复:] [quote=引用 17 楼 stherix 的回复:] [quote=引用 13 楼 wula0010 的回复:] 希望谁能有更好的办法,或者指出我的程序的错误在哪里....................
我下了个360 64位的 它的安装程序是32位的,并不是64的 不要混淆安装程序和运行程序[/quote] 真是32位么?你按我说的方法试试,在32位程序里调用hLibrary = LoadLibrary(szFileName); 这样能加载么????[/quote] 你用64位的程序去 LoadLibrary看下? 加载不成功有很多因素,未必是32/64不匹配[/quote] 我搞错了,32位的可以加载成功 “360杀毒64位.exe”,这个是32位的安装程序。 这个word是imageNtHeaders.FileHeader.Machine ,我还是不认为通过这个可以判断程序是32位还是64位的,看我上面贴的winnt.h里的定义,这个只是处理器的类型。 我最后还是通过LoadLibrary来判断的,.......
stherix 2019-05-27
  • 打赏
  • 举报
回复
引用 18 楼 wula0010 的回复:
[quote=引用 17 楼 stherix 的回复:] [quote=引用 13 楼 wula0010 的回复:] 希望谁能有更好的办法,或者指出我的程序的错误在哪里....................
我下了个360 64位的 它的安装程序是32位的,并不是64的 不要混淆安装程序和运行程序[/quote] 真是32位么?你按我说的方法试试,在32位程序里调用hLibrary = LoadLibrary(szFileName); 这样能加载么????[/quote] 你用64位的程序去 LoadLibrary看下? 加载不成功有很多因素,未必是32/64不匹配
wula0010 2019-05-27
  • 打赏
  • 举报
回复
引用 17 楼 stherix 的回复:
[quote=引用 13 楼 wula0010 的回复:] 希望谁能有更好的办法,或者指出我的程序的错误在哪里....................
我下了个360 64位的 它的安装程序是32位的,并不是64的 不要混淆安装程序和运行程序[/quote] 真是32位么?你按我说的方法试试,在32位程序里调用hLibrary = LoadLibrary(szFileName); 这样能加载么????
stherix 2019-05-27
  • 打赏
  • 举报
回复
引用 13 楼 wula0010 的回复:
希望谁能有更好的办法,或者指出我的程序的错误在哪里....................
我下了个360 64位的 它的安装程序是32位的,并不是64的 不要混淆安装程序和运行程序
stherix 2019-05-27
  • 打赏
  • 举报
回复
引用 12 楼 wula0010 的回复:
在32位程序里调用hLibrary = LoadLibrary(szFileName); 如果是32位程序,hLibrary肯定不为空,64为程序hLibrary肯定为空。程序如下,编译成32位的,找个大家都能下载的程序,360杀毒64位.exe,hLibrary为空,说明是64位程序,但是wWord1 为276(x10b),说明64位程序的Magic不一定是0x2xx。现在我程序就用hLibrary = LoadLibrary(szFileName) 来判断了.........
你建个64位程序,返回也可能为空的,你试下
stherix 2019-05-24
  • 打赏
  • 举报
回复
引用 8 楼 stherix 的回复:
[quote=引用 7 楼 wula0010 的回复:] [quote=引用 3 楼 stherix 的回复:] WORD wWord1 = *(pData + wWord) 不对 要 WORD wWord1 = *(WORD *)(pData + wWord)
这样修改后,32位和64位读出来的都是267,......................... 还有,我理解你这个读的数据,还是pe头里的数据,pe头里没这个数据应该..........................................[/quote] 267也就是0x10B,肯定是32位的[/quote] 这个WORD叫Magic,是可选头的最开始部分 10B则为32位程序,20B则是64位的 64位的exe读出来不可能是10B
stherix 2019-05-24
  • 打赏
  • 举报
回复
引用 7 楼 wula0010 的回复:
[quote=引用 3 楼 stherix 的回复:] WORD wWord1 = *(pData + wWord) 不对 要 WORD wWord1 = *(WORD *)(pData + wWord)
这样修改后,32位和64位读出来的都是267,......................... 还有,我理解你这个读的数据,还是pe头里的数据,pe头里没这个数据应该..........................................[/quote] 267也就是0x10B,肯定是32位的
wula0010 2019-05-24
  • 打赏
  • 举报
回复
引用 3 楼 stherix 的回复:
WORD wWord1 = *(pData + wWord) 不对 要 WORD wWord1 = *(WORD *)(pData + wWord)
这样修改后,32位和64位读出来的都是267,......................... 还有,我理解你这个读的数据,还是pe头里的数据,pe头里没这个数据应该..........................................
zwfgdlc 2019-05-24
  • 打赏
  • 举报
回复

IMAGE_DOS_HEADER DosHead = { 0 };
IMAGE_NT_HEADERS NtHead = { 0 };
IMAGE_SECTION_HEADER ImageSectionHeader = { 0 };
FILE* fp;
_wfopen_s(&fp, szFile, L"rb");
fread(&DosHead, sizeof(IMAGE_DOS_HEADER), 1, fp);
fseek(fp, DosHead.e_lfanew, SEEK_SET);
fread(&NtHead, sizeof(IMAGE_NT_HEADERS), 1, fp);
if (NtHead.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
{
	//32位
}
if (NtHead.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
{
	//64位
}
赵4老师 2019-05-24
  • 打赏
  • 举报
回复
//读0x3C WORD
//这个WORD加上0x18
//再Seek到这个位置,读WORD
//0x1xx就是32位
//0x2xx就是64位
#pragma warning(disable:4996) //开头加这句或项目、属性、配置属性、C/C++、预处理器、预处理器定义中添加“_CRT_SECURE_NO_WARNINGS”
typedef unsigned short int WORD;
#include <stdio.h>
FILE *f;
WORD w;
int main(int argc,char **argv) {
    if (argc==1) {
        printf("Usage:\n    %s filename.exe\nto show 32/64 bit program\n",argv[0]);
        return 1;
    }
    f=fopen(argv[1],"rb");
    if (NULL==f) {
        printf("Can not open file %s\n",argv[1]);
        return 2;
    }
    if (fseek(f,0x3C,SEEK_SET)) {
        printf("Can not seek to 0x3C\n");
        fclose(f);
        return 3;
    }
    if (1!=fread(&w,2,1,f)) {
        printf("Can not read a word at offset 0x3C\n");
        fclose(f);
        return 4;
    }
    if (fseek(f,w+0x18,SEEK_SET)) {
        printf("Can not seek to word ptr (0x3C)+0x18\n");
        fclose(f);
        return 5;
    }
    if (1!=fread(&w,2,1,f)) {
        printf("Can not read a word at offset word ptr (0x3C)+0x18\n");
        fclose(f);
        return 6;
    }
    fclose(f);
    w&=0xFF00;
         if (0x0100==w) printf("%s is a 32 bit program",argv[1]);
    else if (0x0200==w) printf("%s is a 64 bit program",argv[1]);
    else                printf("%s is a 32/64  program",argv[1]);
    return 0;
}
加载更多回复(6)

69,374

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧