简体   繁体   English

exe的md5没有给出预期的摘要

[英]md5 for an exe does not give the expected digest

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. 我创建了一个c ++应用程序,用于在此链接中的microsoft实现之后为文件计算MD5哈希摘要http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx case是md5哈希摘要对于任何类型文件与任何计算md5摘要的现成工具进行比较时都是正确的。 except when the file in hands is an executable like cmd.exe. 除非手中的文件是像cmd.exe这样的可执行文件。 the hash digest is different and depends on the location of the exe. 哈希摘要是不同的,取决于exe的位置。 if you move the cmd.exe to another location then the digest becomes different again. 如果将cmd.exe移动到另一个位置,则摘要将再次变为不同。 so I went on implementing the same functionality using openssl library to face the same problem. 所以我继续使用openssl库实现相同的功能来面对同样的问题。 I noticed that the hash digest from microsoft implementation and openssl is the same. 我注意到微软实现和openssl的哈希摘要是一样的。 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? 我尝试使用win API中的“createfile”和“fopen”来读取文件以得到相同的结果......所以请帮助我,我缺少什么?

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" 此代码计算哈希“59a1d4facd7b333f76c4142cd42d3aba”另一方面“数字火山哈希工具”和“md5和sha校验和实用程序v2.1”计算哈希“fc0b4a626881d7c5980d757214db2d25”

Your code is correct! 你的代码是正确的! You've run into an idiosyncrasy of Windows. 你遇到了Windows的特质。

The file you're reading is inside the C:\\Windows\\System32 directory. 您正在阅读的文件位于C:\\Windows\\System32目录中。

On 64-bit Windows, if a 32-bit application attempts to access that directory it gets redirected to C:\\Windows\\SysWow64 . 在64位Windows上,如果32位应用程序尝试访问该目录, 则会将其重定向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. 由于C:\\Windows\\System32C:\\Windows\\SysWow64中都有cmd.exe文件,但它们是不同的版本,因此不同的哈希值,检查C:\\Windows\\System32\\cmd.exe哈希的程序将会根据它们是32位还是64位给出不同的结果。

You can see this for yourself by building your example program both 32-bit and 64-bit and observing that they give different answers. 您可以通过构建32位和64位的示例程序来自己看到这一点,并观察它们给出不同的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM