exe 的 md5 没有给出预期的摘要
md5 for an exe does not give the expected digest
我是新来的,希望我做对了。
我制作了一个 c++ 应用程序来计算以下文件的 MD5 哈希摘要
此 link http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx 中的 Microsoft 实现
情况是,当将 md5 哈希摘要与任何计算 md5 摘要的现成工具进行比较时,它对于任何类型的文件都是正确的。除非手中的文件是 cmd.exe 这样的可执行文件。哈希摘要不同,取决于 exe 的位置。如果您将 cmd.exe 移动到另一个位置,那么摘要将再次变得不同。所以我继续使用 openssl 库实现相同的功能来面对同样的问题。我注意到微软实现和 openssl 的哈希摘要是相同的。所以我认为在传递文件以计算摘要之前读取文件时缺少一些东西。但我搜索了很多却一无所获。
我尝试使用来自 win API 和 "fopen" 的 "createfile" 读取文件,得到相同的结果...所以请帮助我,我错过了什么?
这里是源代码
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
LPCWSTR filename=L"C:\Windows\System32\cmd.exe";
// Logic to check usage goes here.
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwStatus = GetLastError();
printf("Error opening file %s\nError: %d\n", filename,
dwStatus);
return dwStatus;
}
// Get handle to the crypto provider
if (!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE,
&cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
{
dwStatus = GetLastError();
printf("CryptHashData failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
}
if (!bResult)
{
dwStatus = GetLastError();
printf("ReadFile failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
cbHash = MD5LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
printf("MD5 hash of file %s is: ", filename);
for (DWORD i = 0; i < cbHash; i++)
{
printf("%c%c", rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
}
printf("\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;
return 0;
}
此代码计算哈希“59a1d4facd7b333f76c4142cd42d3aba”
另一方面 "digital volcano hash tool" 和 "md5 and sha checksum utility v2.1" 计算散列 "fc0b4a626881d7c5980d757214db2d25"
您的代码正确!您 运行 有 Windows 的特质。
您正在阅读的文件位于 C:\Windows\System32
目录中。
在 64 位 Windows 上,如果 32 位应用程序试图访问该目录 it gets redirected 到 C:\Windows\SysWow64
。
由于 C:\Windows\System32
和 C:\Windows\SysWow64
中都有 cmd.exe
个文件,但它们的构建不同,因此散列不同,检查 C:\Windows\System32\cmd.exe
散列的程序将根据它们是 32 位还是 64 位给出不同的结果。
您可以通过构建 32 位和 64 位示例程序并观察它们给出不同的答案来亲眼看到这一点。
我是新来的,希望我做对了。
我制作了一个 c++ 应用程序来计算以下文件的 MD5 哈希摘要 此 link http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx 中的 Microsoft 实现 情况是,当将 md5 哈希摘要与任何计算 md5 摘要的现成工具进行比较时,它对于任何类型的文件都是正确的。除非手中的文件是 cmd.exe 这样的可执行文件。哈希摘要不同,取决于 exe 的位置。如果您将 cmd.exe 移动到另一个位置,那么摘要将再次变得不同。所以我继续使用 openssl 库实现相同的功能来面对同样的问题。我注意到微软实现和 openssl 的哈希摘要是相同的。所以我认为在传递文件以计算摘要之前读取文件时缺少一些东西。但我搜索了很多却一无所获。 我尝试使用来自 win API 和 "fopen" 的 "createfile" 读取文件,得到相同的结果...所以请帮助我,我错过了什么?
这里是源代码
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
LPCWSTR filename=L"C:\Windows\System32\cmd.exe";
// Logic to check usage goes here.
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwStatus = GetLastError();
printf("Error opening file %s\nError: %d\n", filename,
dwStatus);
return dwStatus;
}
// Get handle to the crypto provider
if (!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE,
&cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
{
dwStatus = GetLastError();
printf("CryptHashData failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
}
if (!bResult)
{
dwStatus = GetLastError();
printf("ReadFile failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
cbHash = MD5LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
printf("MD5 hash of file %s is: ", filename);
for (DWORD i = 0; i < cbHash; i++)
{
printf("%c%c", rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
}
printf("\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;
return 0;
}
此代码计算哈希“59a1d4facd7b333f76c4142cd42d3aba” 另一方面 "digital volcano hash tool" 和 "md5 and sha checksum utility v2.1" 计算散列 "fc0b4a626881d7c5980d757214db2d25"
您的代码正确!您 运行 有 Windows 的特质。
您正在阅读的文件位于 C:\Windows\System32
目录中。
在 64 位 Windows 上,如果 32 位应用程序试图访问该目录 it gets redirected 到 C:\Windows\SysWow64
。
由于 C:\Windows\System32
和 C:\Windows\SysWow64
中都有 cmd.exe
个文件,但它们的构建不同,因此散列不同,检查 C:\Windows\System32\cmd.exe
散列的程序将根据它们是 32 位还是 64 位给出不同的结果。
您可以通过构建 32 位和 64 位示例程序并观察它们给出不同的答案来亲眼看到这一点。