Update PE CheckSum

Post date: Mar 13, 2010 7:57:12 PM

The CheckSumMappedFile function computes a new checksum for the file and returns it in the CheckSum parameter. This function is used by any application that creates or modifies an executable image. Checksums are required for kernel-mode drivers and some system DLLs. The linker computes the original checksum at link time. It is recommended that all images have valid checksums which is why this unit was created.

{

Unit: uUpdatePECheckSum

Author: steve10120

Description: Update a PE checksum using CheckSumMappedFile exported by imagehlp.dll

Reference: msdn.microsoft.com/en-us/library/ms679281(VS.85).aspx

Website: hackhound.org

History: First try

}

unit uUpdatePECheckSum;
interface
uses Windows, ImageHlp;
function IsCheckSumValid(szFile:string; bUpdate:Boolean):Boolean;
implementation
function UpdateChecksum(szFile:string; dwNewCheckSum:DWORD):Boolean;
var
  hFile:  DWORD;
  IDH:    TImageDosHeader;
  INH:    TImageNtHeaders;
  null:   DWORD;
begin
  Result := FALSE;
  hFile := CreateFile(PChar(szFile), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if hFile <> INVALID_HANDLE_VALUE then
  begin
    SetFilePointer(hFile, 0, nil, FILE_BEGIN);
    ReadFile(hFile, IDH, 64, null, nil);
    if IDH.e_magic = IMAGE_DOS_SIGNATURE then
    begin
      SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
      ReadFile(hFile, INH, 248, null, nil);
      if INH.Signature = IMAGE_NT_SIGNATURE then
      begin
        INH.OptionalHeader.CheckSum := dwNewCheckSum;
        SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
        WriteFile(hFile, INH, 248, null, nil);
        CloseHandle(hFile);
        Result := TRUE;
      end;
    end;
  end;
end;
function IsCheckSumValid(szFile:string; bUpdate:Boolean):Boolean;
var
  hFile:    DWORD;
  hMapping: DWORD;
  pMap:     Pointer;
  dwSize:   DWORD;
  dwOldSum: DWORD;
  dwNewSum: DWORD;
begin
  Result := TRUE;
  hFile := CreateFile(PChar(szFile), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if hFile <> INVALID_HANDLE_VALUE then
  begin
    dwSize := GetFileSize(hFile, nil);
    hMapping := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, dwSize, nil);
    if hMapping <> 0 then
    begin
      pMap := MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
      if pMap <> nil then
      begin
        CheckSumMappedFile(pMap, dwSize, @dwOldSum, @dwNewSum);
        CloseHandle(hFile);
        if dwOldSum <> dwNewSum then
        begin
          Result := FALSE;
          if bUpdate = TRUE then
            UpdateChecksum(szFile, dwNewSum);
        end;
        UnMapViewOfFile(pMap);
      end;
      CloseHandle(hMapping);
    end;
  end;
end;
end.