PE CheckSum algorithm << Back



If you ever want to calculate the CheckSum field for a Portable Executable, you can use the Win32 API CheckSumMappedFile or MapFileAndCheckSum from ImageHlp.dll, or you can calculate it yourself.

DWORD ShowCheckSum(LPCTSTR lpszFile, IMAGE_DOS_HEADER* dosHeader, DWORD dwFileSize)
{
	PIMAGE_NT_HEADERS32 pNTHeader;
	pNTHeader = (PIMAGE_NT_HEADERS32)MakePtr(dosHeader, dosHeader->e_lfanew);
	WORD* pCheckSum1 = (WORD*)&pNTHeader->OptionalHeader.CheckSum;
	DWORD dwCheckSum = 0;
	WORD* pFile = (WORD*)dosHeader;
	DWORD dwCount = dwFileSize;
	while (dwCount)
	{
		if (pFile == pCheckSum1)
		{
			pFile += 2;
			dwCount -= 4;
			continue;
		}
		if (dwCount == 1)
		{ 
			dwCheckSum += *((PBYTE)pFile);
			dwCount = 0;
		}
		else 
		{
			dwCheckSum += *pFile;
			dwCount -= 2;
			pFile++;
		}
		if (dwCheckSum > 0xffff)
			dwCheckSum = (dwCheckSum & 0xffff) + (dwCheckSum >> 16);
	}
	dwCheckSum += dwFileSize;
	return dwCheckSum;
}

While the structure IMAGE_NT_HEADERS32 is different than the structure IMAGE_NT_HEADERS64, the relative memory locations of the CheckSum field are the same in both structures.
  1. Map the entire PE into memory. The starting memory location is also the start of IMAGE_DOS_HEADER
  2. Process 2 bytes (as in a WORD) at a time. Sum all the WORD (excluding the CheckSum field) into a DWORD
  3. If the file size happens to be an odd number (which I have never seen one), then just add the last BYTE to the DWORD
  4. After each sum, if the DWORD exceeds the max size of the WORD (which is 0xffff), then we take the lower 16 bits of the DWORD and add 1 to it
  5. At the end, add the file size to the DWORD





Free Web Hosting