Update PE CheckSum

posted 13 Mar 2010, 11:57 by Delphi Basics   [ updated 13 Mar 2010, 16:31 ]
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.
Comments