Reputation: 63
I am new here, I hope I am doing this right.
I made a c++ application that computes MD5 hash digest for files following microsoft implementation in this link http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx the case is the md5 hash digest is correct for any type file when comparing it with any ready tool that computes the md5 digest. except when the file in hands is an executable like cmd.exe. the hash digest is different and depends on the location of the exe. if you move the cmd.exe to another location then the digest becomes different again. so I went on implementing the same functionality using openssl library to face the same problem. I noticed that the hash digest from microsoft implementation and openssl is the same. so I think there is something missing in reading the file before passing it to compute the digest. but I searched alot to find nothing. I tried reading the file using "createfile" from win API and "fopen" to give the same result... so please help me with this, what am I missing?
here is the source code
#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;
}
this code computes the hash "59a1d4facd7b333f76c4142cd42d3aba" on the other hand "digital volcano hash tool" and "md5 and sha checksum utility v2.1" computes the hash "fc0b4a626881d7c5980d757214db2d25"
Upvotes: 1
Views: 704
Reputation: 4052
Your code is correct! You've run into an idiosyncrasy of Windows.
The file you're reading is inside the C:\Windows\System32
directory.
On 64-bit Windows, if a 32-bit application attempts to access that directory it gets redirected to C:\Windows\SysWow64
.
As there are cmd.exe
files in both C:\Windows\System32
and C:\Windows\SysWow64
, but they're different builds and so different hashes, programs checking the hash of C:\Windows\System32\cmd.exe
will give different results depending on whether they're 32-bit or 64-bit.
You can see this for yourself by building your example program both 32-bit and 64-bit and observing that they give different answers.
Upvotes: 3