789 lines
17 KiB
C
789 lines
17 KiB
C
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// FILE : selfmac.c //
|
||
|
// DESCRIPTION : Code to do self MACing //
|
||
|
// AUTHOR : //
|
||
|
// HISTORY : //
|
||
|
// Nov 04 1999 jeffspel Added provider type checking //
|
||
|
// Mar 2000 kschutz Added stuff to make it work in kernel //
|
||
|
// //
|
||
|
// Copyright (C) 1999 Microsoft Corporation All Rights Reserved //
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <zwapi.h>
|
||
|
#include <windows.h>
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
#include <ntosp.h>
|
||
|
#else
|
||
|
#include <imagehlp.h>
|
||
|
#endif // KERNEL_MODE
|
||
|
|
||
|
#include <des.h>
|
||
|
#include <modes.h>
|
||
|
|
||
|
// MAC in file
|
||
|
typedef struct _MAC_STRUCT
|
||
|
{
|
||
|
ULONG CoolMac[2];
|
||
|
ULONG dwMACStructOffset;
|
||
|
UCHAR rgbMac[DES_BLOCKLEN];
|
||
|
ULONG dwImageCheckSumOffset;
|
||
|
} MAC_STRUCT;
|
||
|
|
||
|
#define MAC_STRING "COOL MAC "
|
||
|
|
||
|
static LPSTR g_pszMAC = MAC_STRING;
|
||
|
static MAC_STRUCT *g_pMACStruct;
|
||
|
|
||
|
// The function MACs the given bytes.
|
||
|
VOID
|
||
|
MACBytes(
|
||
|
IN DESTable *pDESKeyTable,
|
||
|
IN UCHAR *pbData,
|
||
|
IN ULONG cbData,
|
||
|
IN OUT UCHAR *pbTmp,
|
||
|
IN OUT ULONG *pcbTmp,
|
||
|
IN OUT UCHAR *pbMAC,
|
||
|
IN BOOLEAN fFinal
|
||
|
)
|
||
|
{
|
||
|
ULONG cb = cbData;
|
||
|
ULONG cbMACed = 0;
|
||
|
|
||
|
while (cb)
|
||
|
{
|
||
|
if ((cb + *pcbTmp) < DES_BLOCKLEN)
|
||
|
{
|
||
|
memcpy(pbTmp + *pcbTmp, pbData + cbMACed, cb);
|
||
|
*pcbTmp += cb;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(pbTmp + *pcbTmp, pbData + cbMACed, DES_BLOCKLEN - *pcbTmp);
|
||
|
CBC(des, DES_BLOCKLEN, pbMAC, pbTmp, pDESKeyTable,
|
||
|
ENCRYPT, pbMAC);
|
||
|
cbMACed = cbMACed + (DES_BLOCKLEN - *pcbTmp);
|
||
|
cb = cb - (DES_BLOCKLEN - *pcbTmp);
|
||
|
*pcbTmp = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define CSP_TO_BE_MACED_CHUNK 512
|
||
|
|
||
|
// Given hFile, reads the specified number of bytes (cbToBeMACed) from the file
|
||
|
// and MACs these bytes. The function does this in chunks.
|
||
|
NTSTATUS
|
||
|
MACBytesOfFile(
|
||
|
IN HANDLE hFile,
|
||
|
IN ULONG cbToBeMACed,
|
||
|
IN DESTable *pDESKeyTable,
|
||
|
IN UCHAR *pbTmp,
|
||
|
IN ULONG *pcbTmp,
|
||
|
IN UCHAR *pbMAC,
|
||
|
IN BOOLEAN fNoMacing,
|
||
|
IN BOOLEAN fFinal
|
||
|
)
|
||
|
{
|
||
|
UCHAR rgbChunk[CSP_TO_BE_MACED_CHUNK];
|
||
|
ULONG cbRemaining = cbToBeMACed, cbToRead, cbBytesRead;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
#ifdef KERNEL_MODE
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
#endif // END KERNEL/USER MODE CHECK
|
||
|
|
||
|
//
|
||
|
// loop over the file for the specified number of bytes
|
||
|
// updating the hash as we go.
|
||
|
//
|
||
|
|
||
|
while (cbRemaining > 0)
|
||
|
{
|
||
|
if (cbRemaining < CSP_TO_BE_MACED_CHUNK)
|
||
|
cbToRead = cbRemaining;
|
||
|
else
|
||
|
cbToRead = CSP_TO_BE_MACED_CHUNK;
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
Status = ZwReadFile(hFile,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
rgbChunk,
|
||
|
cbToRead,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (cbToRead != IoStatusBlock.Information)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
cbBytesRead = cbToRead;
|
||
|
#else // USER MODE
|
||
|
if(!ReadFile(hFile,
|
||
|
rgbChunk,
|
||
|
cbToRead,
|
||
|
&cbBytesRead,
|
||
|
NULL))
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (cbBytesRead != cbToRead)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
#endif // END KERNEL/USER MODE CHECK
|
||
|
|
||
|
if (!fNoMacing)
|
||
|
{
|
||
|
MACBytes(pDESKeyTable,
|
||
|
rgbChunk,
|
||
|
cbBytesRead,
|
||
|
pbTmp,
|
||
|
pcbTmp,
|
||
|
pbMAC,
|
||
|
fFinal);
|
||
|
}
|
||
|
|
||
|
cbRemaining -= cbToRead;
|
||
|
}
|
||
|
Ret:
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
static UCHAR rgbMACDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
|
||
|
|
||
|
NTSTATUS
|
||
|
MACTheFile(
|
||
|
LPCWSTR pszImage,
|
||
|
ULONG cbImageCheckSumOffset,
|
||
|
ULONG cbMACStructOffset,
|
||
|
UCHAR *pbMAC
|
||
|
)
|
||
|
{
|
||
|
ULONG cbFileLen = 0,cbHighPart, cbBytesToMac;
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
DESTable DESKeyTable;
|
||
|
BYTE rgbTmp[DES_BLOCKLEN];
|
||
|
DWORD cbTmp = 0;
|
||
|
MAC_STRUCT TmpMacStruct;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
UNICODE_STRING ObjectName;
|
||
|
OBJECT_ATTRIBUTES ObjectAttribs;
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
BOOLEAN fFileOpened = FALSE;
|
||
|
FILE_STANDARD_INFORMATION FileInformation;
|
||
|
#endif // END KERNEL/USER MODE CHECK
|
||
|
|
||
|
RtlZeroMemory(pbMAC, DES_BLOCKLEN);
|
||
|
RtlZeroMemory(rgbTmp, sizeof(rgbTmp));
|
||
|
RtlZeroMemory(&TmpMacStruct, sizeof(TmpMacStruct));
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
//
|
||
|
// get file length - kernel mode version
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory(&ObjectAttribs, sizeof(ObjectAttribs));
|
||
|
RtlInitUnicodeString( &ObjectName, pszImage );
|
||
|
|
||
|
InitializeObjectAttributes(
|
||
|
&ObjectAttribs,
|
||
|
&ObjectName,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
Status = ZwCreateFile(
|
||
|
&hFile,
|
||
|
SYNCHRONIZE | FILE_READ_DATA,
|
||
|
&ObjectAttribs,
|
||
|
&IoStatusBlock,
|
||
|
NULL,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
FILE_SHARE_READ ,
|
||
|
FILE_OPEN,
|
||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
fFileOpened = TRUE;
|
||
|
|
||
|
Status = ZwQueryInformationFile(
|
||
|
hFile,
|
||
|
&IoStatusBlock,
|
||
|
&FileInformation,
|
||
|
sizeof(FILE_STANDARD_INFORMATION),
|
||
|
FileStandardInformation
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
cbFileLen = FileInformation.EndOfFile.LowPart;
|
||
|
|
||
|
#else // USER MODE
|
||
|
|
||
|
//
|
||
|
// get file length - user mode version
|
||
|
//
|
||
|
|
||
|
if ((hFile = CreateFileW(
|
||
|
pszImage,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL)) == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
cbFileLen = GetFileSize(hFile, &cbHighPart);
|
||
|
|
||
|
#endif // END KERNEL/USER MODE CHECK
|
||
|
|
||
|
if (cbFileLen < sizeof(MAC_STRUCT))
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// init the key table
|
||
|
deskey(&DESKeyTable, rgbMACDESKey);
|
||
|
|
||
|
// MAC the file the following way:
|
||
|
// - MAC from start to image check sum
|
||
|
// - skip over the image check sum
|
||
|
// - mac from after the image check sum to the mac struct
|
||
|
// - skip over the mac struct
|
||
|
// - mac the rest of the file
|
||
|
|
||
|
// MAC from the start to the image check sum offset
|
||
|
Status = MACBytesOfFile(
|
||
|
hFile,
|
||
|
cbImageCheckSumOffset,
|
||
|
&DESKeyTable,
|
||
|
rgbTmp,
|
||
|
&cbTmp,
|
||
|
pbMAC,
|
||
|
FALSE,
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// Skip over the image checksum
|
||
|
Status = MACBytesOfFile(
|
||
|
hFile,
|
||
|
sizeof(DWORD),
|
||
|
&DESKeyTable,
|
||
|
rgbTmp,
|
||
|
&cbTmp,
|
||
|
pbMAC,
|
||
|
TRUE,
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// MAC from after the image checksum to the MAC struct offset
|
||
|
cbBytesToMac = cbMACStructOffset - sizeof(DWORD) - cbImageCheckSumOffset;
|
||
|
Status = MACBytesOfFile(
|
||
|
hFile,
|
||
|
cbBytesToMac,
|
||
|
&DESKeyTable,
|
||
|
rgbTmp,
|
||
|
&cbTmp,
|
||
|
pbMAC,
|
||
|
FALSE,
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// skip over the mac struct
|
||
|
Status = MACBytesOfFile(
|
||
|
hFile,
|
||
|
sizeof(MAC_STRUCT),
|
||
|
&DESKeyTable,
|
||
|
rgbTmp,
|
||
|
&cbTmp,
|
||
|
pbMAC,
|
||
|
TRUE,
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// MAC data after the MAC struct
|
||
|
cbBytesToMac = cbFileLen - cbMACStructOffset - sizeof(MAC_STRUCT);
|
||
|
Status = MACBytesOfFile(
|
||
|
hFile,
|
||
|
cbBytesToMac,
|
||
|
&DESKeyTable,
|
||
|
rgbTmp,
|
||
|
&cbTmp,
|
||
|
pbMAC,
|
||
|
FALSE,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
Ret:
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
if (fFileOpened)
|
||
|
{
|
||
|
ZwClose(hFile);
|
||
|
}
|
||
|
#else
|
||
|
if (INVALID_HANDLE_VALUE != hFile)
|
||
|
{
|
||
|
CloseHandle(hFile);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
// **********************************************************************
|
||
|
// SelfMACCheck performs a DES MAC on the binary image of this DLL
|
||
|
// **********************************************************************
|
||
|
NTSTATUS
|
||
|
SelfMACCheck(
|
||
|
IN LPWSTR pszImage
|
||
|
)
|
||
|
{
|
||
|
UCHAR rgbMac[DES_BLOCKLEN];
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
g_pMACStruct = (MAC_STRUCT*) g_pszMAC;
|
||
|
|
||
|
Status = MACTheFile(
|
||
|
pszImage,
|
||
|
g_pMACStruct->dwImageCheckSumOffset,
|
||
|
g_pMACStruct->dwMACStructOffset,
|
||
|
rgbMac
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (RtlCompareMemory(
|
||
|
rgbMac,
|
||
|
g_pMACStruct->rgbMac,
|
||
|
sizeof(rgbMac)) != sizeof(rgbMac))
|
||
|
{
|
||
|
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
Ret:
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
#ifndef KERNEL_MODE
|
||
|
|
||
|
//
|
||
|
// Find the offset to the MAC structure
|
||
|
//
|
||
|
NTSTATUS
|
||
|
FindTheMACStructOffset(
|
||
|
LPWSTR pszImage,
|
||
|
ULONG *pcbMACStructOffset
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
ULONG cbRemaining, cbBytesRead, cbHighPart, cbFileLen, cbCompare = 0;
|
||
|
UCHAR b;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
*pcbMACStructOffset = 0;
|
||
|
|
||
|
// Load the file
|
||
|
if ((hFile = CreateFileW(
|
||
|
pszImage,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL)) == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
cbFileLen = GetFileSize(hFile, &cbHighPart);
|
||
|
cbRemaining = cbFileLen;
|
||
|
|
||
|
// read file to the correct location
|
||
|
while (cbRemaining > 0)
|
||
|
{
|
||
|
if(!ReadFile(hFile,
|
||
|
&b,
|
||
|
1,
|
||
|
&cbBytesRead,
|
||
|
NULL))
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (cbBytesRead != 1)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
if (b == g_pszMAC[cbCompare])
|
||
|
{
|
||
|
cbCompare++;
|
||
|
if (cbCompare == 8)
|
||
|
{
|
||
|
*pcbMACStructOffset = (cbFileLen - (cbRemaining + 7)) ;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cbCompare = 0;
|
||
|
}
|
||
|
|
||
|
cbRemaining--;
|
||
|
}
|
||
|
|
||
|
if (cbCompare != 8)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
Ret:
|
||
|
if (INVALID_HANDLE_VALUE != hFile)
|
||
|
{
|
||
|
CloseHandle(hFile);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
GetImageCheckSumOffset(
|
||
|
LPWSTR pszImage,
|
||
|
ULONG *pcbImageCheckSumOffset
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
HANDLE hFileMap = INVALID_HANDLE_VALUE;
|
||
|
ULONG cbHighPart;
|
||
|
ULONG cbFileLen;
|
||
|
PBYTE pbFilePtr = NULL;
|
||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||
|
PIMAGE_NT_HEADERS pImageNTHdrs;
|
||
|
DWORD OldCheckSum;
|
||
|
DWORD NewCheckSum;
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == (hFile = CreateFileW(
|
||
|
pszImage,
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL)))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// make sure the file is larger than the indicated offset
|
||
|
cbFileLen = GetFileSize(hFile, &cbHighPart);
|
||
|
|
||
|
// map the file to memory
|
||
|
if (NULL == (hFileMap = CreateFileMapping(
|
||
|
hFile,
|
||
|
NULL,
|
||
|
PAGE_READWRITE,
|
||
|
0,
|
||
|
0,
|
||
|
NULL)))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// get a memory view of the file
|
||
|
if (NULL == (pbFilePtr = (PBYTE) MapViewOfFile(
|
||
|
hFileMap,
|
||
|
FILE_MAP_ALL_ACCESS,
|
||
|
0,
|
||
|
0,
|
||
|
0)))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// get the pointer to the image checksum
|
||
|
if (NULL == (pImageNTHdrs = CheckSumMappedFile(
|
||
|
pbFilePtr, cbFileLen,
|
||
|
&OldCheckSum, &NewCheckSum))) {
|
||
|
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
*pcbImageCheckSumOffset =
|
||
|
(ULONG) ((PBYTE) &pImageNTHdrs->OptionalHeader.CheckSum - pbFilePtr);
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
|
||
|
Ret:
|
||
|
if (pbFilePtr) {
|
||
|
|
||
|
UnmapViewOfFile(pbFilePtr);
|
||
|
}
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hFileMap) {
|
||
|
|
||
|
CloseHandle(hFileMap);
|
||
|
}
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hFile)
|
||
|
{
|
||
|
CloseHandle(hFile);
|
||
|
}
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
// write the MAC information into the MAC struct in the file
|
||
|
NTSTATUS
|
||
|
WriteMACToTheFile(
|
||
|
LPWSTR pszImage,
|
||
|
MAC_STRUCT *pMacStructOriginal,
|
||
|
ULONG cbMACStructOffset,
|
||
|
UCHAR *pbMac
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
HANDLE hFileMap = INVALID_HANDLE_VALUE;
|
||
|
PBYTE pbFilePtr = NULL;
|
||
|
MAC_STRUCT TmpMacStruct;
|
||
|
ULONG cbWritten = 0, cbRemaining = cbMACStructOffset;
|
||
|
ULONG cbToRead, cbBytesRead, cbHighPart,cbFileLen;
|
||
|
UCHAR rgbChunk[CSP_TO_BE_MACED_CHUNK];
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
DWORD OldCheckSum, NewCheckSum;
|
||
|
PIMAGE_NT_HEADERS pImageNTHdrs;
|
||
|
|
||
|
RtlCopyMemory(&TmpMacStruct, pMacStructOriginal, sizeof(TmpMacStruct));
|
||
|
|
||
|
// Load the file
|
||
|
if ((hFile = CreateFileW(
|
||
|
pszImage,
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL)) == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// make sure the file is larger than the indicated offset
|
||
|
cbFileLen = GetFileSize(hFile, &cbHighPart);
|
||
|
|
||
|
if (cbFileLen < cbMACStructOffset)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// map the file to memory
|
||
|
if ((hFileMap = CreateFileMapping(
|
||
|
hFile,
|
||
|
NULL,
|
||
|
PAGE_READWRITE,
|
||
|
0,
|
||
|
0,
|
||
|
NULL)) == NULL)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// get a memory view of the file
|
||
|
if ((pbFilePtr = (PBYTE) MapViewOfFile(
|
||
|
hFileMap,
|
||
|
FILE_MAP_ALL_ACCESS,
|
||
|
0,
|
||
|
0,
|
||
|
0)) == NULL)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// get the pointer to the image checksum
|
||
|
if (NULL == (pImageNTHdrs = CheckSumMappedFile(
|
||
|
pbFilePtr, cbFileLen,
|
||
|
&OldCheckSum, &NewCheckSum))) {
|
||
|
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// set up and write the MAC struct
|
||
|
TmpMacStruct.dwImageCheckSumOffset =
|
||
|
(ULONG) ((PBYTE) &pImageNTHdrs->OptionalHeader.CheckSum - pbFilePtr);
|
||
|
TmpMacStruct.dwMACStructOffset = cbMACStructOffset;
|
||
|
RtlCopyMemory(TmpMacStruct.rgbMac, pbMac, sizeof(TmpMacStruct.rgbMac));
|
||
|
|
||
|
// now copy the new mac struct back to the view
|
||
|
RtlCopyMemory(pbFilePtr + cbMACStructOffset, &TmpMacStruct, sizeof(TmpMacStruct));
|
||
|
|
||
|
// compute a new checksum
|
||
|
if (NULL == (pImageNTHdrs = CheckSumMappedFile(
|
||
|
pbFilePtr, cbFileLen,
|
||
|
&OldCheckSum, &NewCheckSum))) {
|
||
|
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// and copy the new checksum back to the header
|
||
|
CopyMemory(&pImageNTHdrs->OptionalHeader.CheckSum, &NewCheckSum, sizeof(DWORD));
|
||
|
|
||
|
Ret:
|
||
|
if (pbFilePtr) {
|
||
|
|
||
|
UnmapViewOfFile(pbFilePtr);
|
||
|
}
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hFileMap) {
|
||
|
|
||
|
CloseHandle(hFileMap);
|
||
|
}
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hFile)
|
||
|
{
|
||
|
CloseHandle(hFile);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
// **********************************************************************
|
||
|
// MACTheBinary performs a MAC on the binary and writes the value into
|
||
|
// the g_pMACStruct
|
||
|
// **********************************************************************
|
||
|
NTSTATUS
|
||
|
MACTheBinary(
|
||
|
IN LPWSTR pszImage
|
||
|
)
|
||
|
{
|
||
|
UCHAR rgbMAC[DES_BLOCKLEN];
|
||
|
ULONG cbMACStructOffset = 0, cbImageCheckSumOffset = 0;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
g_pMACStruct = (MAC_STRUCT*) g_pszMAC;
|
||
|
|
||
|
// Find the offset to the MAC structure
|
||
|
Status = FindTheMACStructOffset(
|
||
|
pszImage,
|
||
|
&cbMACStructOffset
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// Get the offset of the image checksum
|
||
|
Status = GetImageCheckSumOffset(
|
||
|
pszImage,
|
||
|
&cbImageCheckSumOffset
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// MAC the file
|
||
|
Status = MACTheFile(
|
||
|
pszImage,
|
||
|
cbImageCheckSumOffset,
|
||
|
cbMACStructOffset,
|
||
|
rgbMAC
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
// write the MAC information into the MAC struct in the file
|
||
|
Status = WriteMACToTheFile(
|
||
|
pszImage,
|
||
|
g_pMACStruct,
|
||
|
cbMACStructOffset,
|
||
|
rgbMAC
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
goto Ret;
|
||
|
}
|
||
|
|
||
|
Ret:
|
||
|
return Status;
|
||
|
}
|
||
|
#endif // NOT IN KERNEL_MODE
|
||
|
|