mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
7.6 KiB
303 lines
7.6 KiB
#include <afxwin.h>
|
|
|
|
#include "imagehlp.h"
|
|
|
|
//... PROTOTYPES
|
|
|
|
USHORT ChkSum(
|
|
|
|
DWORD PartialSum,
|
|
PUSHORT Source,
|
|
DWORD Length);
|
|
|
|
static PIMAGE_NT_HEADERS MyRtlImageNtHeader(
|
|
|
|
PVOID pBaseAddress);
|
|
|
|
static PIMAGE_NT_HEADERS CheckSumMappedFile(
|
|
|
|
LPVOID BaseAddress,
|
|
DWORD FileLength,
|
|
LPDWORD HeaderSum,
|
|
LPDWORD CheckSum);
|
|
|
|
static BOOL TouchFileTimes(
|
|
|
|
HANDLE FileHandle,
|
|
LPSYSTEMTIME lpSystemTime);
|
|
|
|
|
|
//...........................................................................
|
|
|
|
|
|
DWORD QuitA( DWORD err, LPCSTR, LPSTR )
|
|
{
|
|
return err;
|
|
}
|
|
|
|
DWORD FixCheckSum( LPCSTR ImageName)
|
|
{
|
|
HANDLE FileHandle;
|
|
HANDLE MappingHandle;
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
PVOID BaseAddress;
|
|
ULONG CheckSum;
|
|
ULONG FileLength;
|
|
ULONG HeaderSum;
|
|
ULONG OldCheckSum;
|
|
|
|
|
|
FileHandle = CreateFileA( ImageName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if ( FileHandle == INVALID_HANDLE_VALUE )
|
|
{
|
|
QuitA( 1, ImageName, NULL);
|
|
}
|
|
|
|
MappingHandle = CreateFileMapping( FileHandle,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
0,
|
|
NULL);
|
|
|
|
if ( MappingHandle == NULL )
|
|
{
|
|
CloseHandle( FileHandle );
|
|
QuitA( 22, ImageName, NULL);
|
|
}
|
|
else
|
|
{
|
|
BaseAddress = MapViewOfFile( MappingHandle,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0);
|
|
CloseHandle( MappingHandle );
|
|
|
|
if ( BaseAddress == NULL )
|
|
{
|
|
CloseHandle( FileHandle );
|
|
QuitA( 23, ImageName, NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the length of the file in bytes and compute the checksum.
|
|
//
|
|
|
|
FileLength = GetFileSize( FileHandle, NULL );
|
|
|
|
//
|
|
// Obtain a pointer to the header information.
|
|
//
|
|
|
|
NtHeaders = MyRtlImageNtHeader( BaseAddress);
|
|
|
|
if ( NtHeaders == NULL )
|
|
{
|
|
CloseHandle( FileHandle );
|
|
UnmapViewOfFile( BaseAddress );
|
|
QuitA( 17, ImageName, NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Recompute and reset the checksum of the modified file.
|
|
//
|
|
|
|
OldCheckSum = NtHeaders->OptionalHeader.CheckSum;
|
|
|
|
(VOID) CheckSumMappedFile( BaseAddress,
|
|
FileLength,
|
|
&HeaderSum,
|
|
&CheckSum);
|
|
|
|
NtHeaders->OptionalHeader.CheckSum = CheckSum;
|
|
|
|
if ( ! FlushViewOfFile( BaseAddress, FileLength) )
|
|
{
|
|
QuitA( 24, ImageName, NULL);
|
|
}
|
|
|
|
if ( NtHeaders->OptionalHeader.CheckSum != OldCheckSum )
|
|
{
|
|
if ( ! TouchFileTimes( FileHandle, NULL) )
|
|
{
|
|
QuitA( 25, ImageName, NULL);
|
|
}
|
|
}
|
|
UnmapViewOfFile( BaseAddress );
|
|
CloseHandle( FileHandle );
|
|
}
|
|
}
|
|
}
|
|
return( 0);
|
|
}
|
|
|
|
//.........................................................................
|
|
|
|
static PIMAGE_NT_HEADERS MyRtlImageNtHeader( PVOID pBaseAddress)
|
|
{
|
|
IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pBaseAddress;
|
|
|
|
return( pDosHeader->e_magic == IMAGE_DOS_SIGNATURE
|
|
? (PIMAGE_NT_HEADERS)(((PBYTE)pBaseAddress) + pDosHeader->e_lfanew)
|
|
: NULL);
|
|
}
|
|
|
|
|
|
/*.........................................................................
|
|
|
|
CheckSumMappedFile
|
|
|
|
Routine Description:
|
|
|
|
This functions computes the checksum of a mapped file.
|
|
|
|
Arguments:
|
|
|
|
BaseAddress - Supplies a pointer to the base of the mapped file.
|
|
|
|
FileLength - Supplies the length of the file in bytes.
|
|
|
|
HeaderSum - Suppllies a pointer to a variable that receives the checksum
|
|
from the image file, or zero if the file is not an image file.
|
|
|
|
CheckSum - Supplies a pointer to the variable that receive the computed
|
|
checksum.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
..........................................................................*/
|
|
|
|
static PIMAGE_NT_HEADERS CheckSumMappedFile (
|
|
|
|
LPVOID BaseAddress,
|
|
DWORD FileLength,
|
|
LPDWORD HeaderSum,
|
|
LPDWORD CheckSum)
|
|
{
|
|
|
|
PUSHORT AdjustSum;
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
USHORT PartialSum;
|
|
|
|
//... Compute the checksum of the file and zero
|
|
//... the header checksum value.
|
|
*HeaderSum = 0;
|
|
PartialSum = ChkSum( 0, (PUSHORT)BaseAddress, (FileLength + 1) >> 1);
|
|
|
|
//... If the file is an image file, then
|
|
//... subtract the two checksum words in the
|
|
//... optional header from the computed checksum
|
|
//... before adding the file length, and set the
|
|
//... value of the header checksum.
|
|
|
|
__try
|
|
{
|
|
NtHeaders = MyRtlImageNtHeader( BaseAddress);
|
|
}
|
|
__except( EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
NtHeaders = NULL;
|
|
}
|
|
|
|
if ( (NtHeaders != NULL) && (NtHeaders != BaseAddress) )
|
|
{
|
|
*HeaderSum = NtHeaders->OptionalHeader.CheckSum;
|
|
AdjustSum = (PUSHORT)(&NtHeaders->OptionalHeader.CheckSum);
|
|
PartialSum -= (PartialSum < AdjustSum[0]);
|
|
PartialSum -= AdjustSum[0];
|
|
PartialSum -= (PartialSum < AdjustSum[1]);
|
|
PartialSum -= AdjustSum[1];
|
|
}
|
|
//... Compute the final checksum value as the
|
|
//... sum of the paritial checksum and the file
|
|
//... length.
|
|
|
|
*CheckSum = (DWORD)PartialSum + FileLength;
|
|
|
|
return( NtHeaders);
|
|
}
|
|
|
|
|
|
//............................................................................
|
|
|
|
static BOOL TouchFileTimes(
|
|
|
|
HANDLE FileHandle,
|
|
LPSYSTEMTIME lpSystemTime)
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
FILETIME SystemFileTime;
|
|
|
|
if ( lpSystemTime == NULL )
|
|
{
|
|
lpSystemTime = &SystemTime;
|
|
GetSystemTime( lpSystemTime);
|
|
}
|
|
|
|
if ( SystemTimeToFileTime( lpSystemTime, &SystemFileTime) )
|
|
{
|
|
return( SetFileTime( FileHandle, NULL, NULL, &SystemFileTime));
|
|
}
|
|
else
|
|
{
|
|
return( FALSE);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compute a partial checksum on a portion of an imagefile.
|
|
|
|
Arguments:
|
|
|
|
PartialSum - Supplies the initial checksum value.
|
|
|
|
Sources - Supplies a pointer to the array of words for which the
|
|
checksum is computed.
|
|
|
|
Length - Supplies the length of the array in words.
|
|
|
|
Return Value:
|
|
|
|
The computed checksum value is returned as the function value.
|
|
|
|
--*/
|
|
|
|
USHORT ChkSum(
|
|
|
|
ULONG ulPartialSum,
|
|
PUSHORT usSource,
|
|
ULONG ulLength)
|
|
{
|
|
//
|
|
// Compute the word wise checksum allowing carries to occur into the
|
|
// high order half of the checksum longword.
|
|
//
|
|
|
|
while ( ulLength-- )
|
|
{
|
|
ulPartialSum += *usSource++;
|
|
ulPartialSum = (ulPartialSum >> 16) + (ulPartialSum & 0xffff);
|
|
}
|
|
|
|
//
|
|
// Fold final carry into a single word result and return the resultant
|
|
// value.
|
|
//
|
|
|
|
return( (USHORT)(((ulPartialSum >> 16) + ulPartialSum) & 0xffff));
|
|
}
|