summaryrefslogtreecommitdiff
path: root/tools/checksum/checksum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/checksum/checksum.cpp')
-rw-r--r--tools/checksum/checksum.cpp252
1 files changed, 201 insertions, 51 deletions
diff --git a/tools/checksum/checksum.cpp b/tools/checksum/checksum.cpp
index 13d13eb9ae..744805a694 100644
--- a/tools/checksum/checksum.cpp
+++ b/tools/checksum/checksum.cpp
@@ -2,11 +2,13 @@
// Checksum Tool
// By Bio (C) 2012
-#define _VERSION_ "2.0"
+#define _VERSION_ "2.99"
#include "commonheaders.h"
+
//#define DEBUG_SECTIONS 1
+//#define DEBUG_REALLOCS 1
// Return codes
#define RESULT_OK 0
@@ -18,6 +20,9 @@
#define RESULT_NONE 100
+#define DEFAULT_BASE 0x10000000
+
+
int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
{
HANDLE hFile = INVALID_HANDLE_VALUE;
@@ -77,23 +82,24 @@ int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
else
{
machine = pINTH->FileHeader.Machine;
-/*
+
+#ifdef DEBUG_SECTIONS
switch(machine)
{
case IMAGE_FILE_MACHINE_I386:
- _ftprintf( stderr, _T("(x86) ") );
+ _ftprintf( stderr, _T("Build: x86\n") );
break;
case IMAGE_FILE_MACHINE_AMD64:
- _ftprintf( stderr, _T("(x64) ") );
+ _ftprintf( stderr, _T("Build: x64\n") );
break;
case IMAGE_FILE_MACHINE_IA64:
- _ftprintf( stderr, _T("(IA64 :-) ") );
+ _ftprintf( stderr, _T("Build: IA64 :-)\n") );
break;
default:
- _ftprintf( stderr, _T("(unknown) ") );
+ _ftprintf( stderr, _T("Build: unknown :-(\n") );
break;
}
-*/
+#endif
sections = pINTH->FileHeader.NumberOfSections;
if ( !sections )
@@ -105,12 +111,21 @@ int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
DWORD dbgvaddr = 0;
DWORD expsize = 0;
DWORD expvaddr = 0;
-
+ PBYTE pRealloc = 0;
+ DWORD realvaddr = 0;
+ DWORD realsize = 0;
+ DWORD offset;
+ __int64 base = 0;
+
+ // try to found correct offset independent of architectures
+ offset = pIDH->e_lfanew + pINTH->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_OPTIONAL_HEADER);
+
if ( ( machine == IMAGE_FILE_MACHINE_I386 ) &&
( pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER32) ) &&
( pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC ) )
{
pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory ) );
+ base = *(DWORD*)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS32, OptionalHeader.ImageBase ) );
}
else
if ( ( machine == IMAGE_FILE_MACHINE_AMD64 ) &&
@@ -118,10 +133,15 @@ int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
( pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ) )
{
- pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory ) );
+ pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory ) );
+ base = *(__int64*)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.ImageBase ) );
}
else
res = RESULT_CORRUPTED;
+
+#ifdef DEBUG_REALLOCS
+ _ftprintf( stderr, _T("Image base is 0x%I64x \n"), base );
+#endif
if ( pIDD )
{
@@ -132,64 +152,39 @@ int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
// Export information entry
expvaddr = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
expsize = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- }
-
- if ( res == RESULT_OK )
- {
- PIMAGE_SECTION_HEADER pISH = 0;
- DWORD offset;
- DWORD idx = 0;
- mir_md5_state_t pms;
-
- mir_md5_init( &pms );
- // try to found correct offset independent of architectures
- offset = pIDH->e_lfanew + pINTH->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_OPTIONAL_HEADER);
+ // Reallocation information entry
+ realvaddr = pIDD[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ realsize = pIDD[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if ( dbgsize || expsize || realsize )
+ {
+ DWORD idx = 0;
+ PIMAGE_SECTION_HEADER pISH = 0;
while ( idx < sections )
{
pISH = (PIMAGE_SECTION_HEADER)( ptr + offset + idx * sizeof(IMAGE_SECTION_HEADER) );
- if ( (PBYTE)pISH + sizeof(IMAGE_SECTION_HEADER) > ptr + filesize )
- {
- res = RESULT_CORRUPTED;
- break;
- }
-
- if ( pISH->PointerToRawData + pISH->SizeOfRawData > filesize )
- {
- res = RESULT_CORRUPTED;
- break;
- }
-
-#ifdef DEBUG_SECTIONS
- _ftprintf( stderr, _T("%s - %08X - %d "), pISH->Name, pISH->PointerToRawData, pISH->SizeOfRawData);
-
+ if ( ( (PBYTE)pISH + sizeof(IMAGE_SECTION_HEADER) > ptr + filesize ) || ( pISH->PointerToRawData + pISH->SizeOfRawData > filesize ) )
{
- int i;
- mir_md5_byte_t digest2[16];
- mir_md5_state_t pms2;
-
- mir_md5_init( &pms2 );
- mir_md5_append( &pms2, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );
- mir_md5_finish( &pms2, digest2 );
-
- for ( i = 0; i < sizeof( digest2 ) / sizeof( digest2[0] ); i++ )
- _ftprintf( stderr, _T("%02X"), digest2[i] );
- _ftprintf( stderr, _T("\n") );
+ res = RESULT_CORRUPTED;
+ break;
}
-#endif
+
// erase timestamp and debug information
if (( dbgsize >= sizeof( IMAGE_DEBUG_DIRECTORY ) ) &&
( dbgvaddr >= pISH->VirtualAddress ) &&
- ( dbgvaddr + dbgsize <= pISH->VirtualAddress + pISH->SizeOfRawData ) )
+ ( dbgvaddr + dbgsize <= pISH->VirtualAddress + pISH->SizeOfRawData )
+ )
{
DWORD shift = dbgvaddr - pISH->VirtualAddress;
PIMAGE_DEBUG_DIRECTORY pDBG = (PIMAGE_DEBUG_DIRECTORY)( ptr + shift + pISH->PointerToRawData );
pDBG->TimeDateStamp = 0;
#ifdef DEBUG_SECTIONS
- _ftprintf( stderr, _T("found debug section entry %08X ( %d ), data %08X ( %d ) \n"), pISH->PointerToRawData + shift, dbgsize, pDBG->PointerToRawData, pDBG->SizeOfData );
+ _ftprintf( stderr, _T("Found debug section entry at 0x%08X (%d), data at 0x%08X (%d)\n"), pISH->PointerToRawData + shift, dbgsize, pDBG->PointerToRawData, pDBG->SizeOfData );
#endif
if ( pDBG->SizeOfData > 0 &&
( pDBG->PointerToRawData >= pISH->PointerToRawData ) &&
@@ -211,9 +206,164 @@ int PEChecksum( TCHAR *filename, mir_md5_byte_t digest[16] )
pEXP->TimeDateStamp = 0;
#ifdef DEBUG_SECTIONS
- _ftprintf( stderr, _T("found export section entry %08X\n"), pISH->PointerToRawData + shift );
+ _ftprintf( stderr, _T("Found export section entry at 0x%08X\n"), pISH->PointerToRawData + shift );
+#endif
+ }
+
+ // find realocation table
+ if (( realsize >= sizeof( IMAGE_BASE_RELOCATION ) ) &&
+ ( realvaddr >= pISH->VirtualAddress ) &&
+ ( realvaddr + realsize <= pISH->VirtualAddress + pISH->SizeOfRawData ) )
+ {
+ DWORD shift = realvaddr - pISH->VirtualAddress;
+ pRealloc = ptr + shift + pISH->PointerToRawData;
+#ifdef DEBUG_SECTIONS
+ _ftprintf( stderr, _T("Found reallocation table entry at 0x%08X (%d)\n"), pISH->PointerToRawData + shift, realsize );
+#endif
+
+ // correct base address
+ base = DEFAULT_BASE - base;
+#ifdef DEBUG_REALLOCS
+ if ( base >= 0)
+ _ftprintf( stderr, _T("Image base correction 0x%I64x\n"), base );
+ else
+ _ftprintf( stderr, _T("Image base correction -0x%I64x\n"), -base );
+#endif
+ }
+
+ idx++;
+ }
+
+ }
+
+ if ( res == RESULT_OK )
+ {
+ PIMAGE_SECTION_HEADER pISH = 0;
+ DWORD idx = 0;
+
+ INT64 rebase = DEFAULT_BASE - base;
+
+ mir_md5_state_t pms;
+
+ mir_md5_init( &pms );
+
+ while ( idx < sections )
+ {
+ pISH = (PIMAGE_SECTION_HEADER)( ptr + offset + idx * sizeof(IMAGE_SECTION_HEADER) );
+
+ if ( ( (PBYTE)pISH + sizeof(IMAGE_SECTION_HEADER) > ptr + filesize ) || ( pISH->PointerToRawData + pISH->SizeOfRawData > filesize ) )
+ {
+ res = RESULT_CORRUPTED;
+ break;
+ }
+
+ // Rebase to default address
+ if ( pRealloc )
+ {
+ PIMAGE_BASE_RELOCATION pIBR = 0;
+
+ DWORD blocklen = realsize;
+ PWORD pw;
+ DWORD type;
+ int len;
+ PBYTE pAddr;
+ DWORD shift;
+ DWORD addr;
+
+ pIBR = (PIMAGE_BASE_RELOCATION)pRealloc;
+
+ while( pIBR )
+ {
+ if ( ( pIBR->VirtualAddress >= pISH->VirtualAddress ) &&
+ ( pIBR->VirtualAddress < pISH->VirtualAddress + pISH->SizeOfRawData ) &&
+ ( pIBR->SizeOfBlock <= blocklen ) )
+ {
+ shift = pIBR->VirtualAddress - pISH->VirtualAddress + pISH->PointerToRawData;
+
+ len = pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION);
+
+ pw = (PWORD)( (PBYTE)pIBR + sizeof(IMAGE_BASE_RELOCATION) );
+#ifdef DEBUG_REALLOCS
+ _ftprintf( stderr, _T("Realloc block at %08X (%d)\n"), pIBR->VirtualAddress, pIBR->SizeOfBlock );
+#endif
+
+ while( len > 0 )
+ {
+ type = *pw >> 12;
+
+ addr = ( *pw & 0x0FFF );
+
+ pAddr = ptr + shift + addr;
+
+ switch( type )
+ {
+ case IMAGE_REL_BASED_HIGHLOW:
+ if ( addr + pIBR->VirtualAddress + sizeof(DWORD) >= pISH->VirtualAddress + pISH->SizeOfRawData )
+ {
+ len = 0;
+ break;
+ }
+ *(PDWORD)pAddr = (DWORD)( (__int64)(*(PDWORD)pAddr) + base );
+ break;
+
+
+ case IMAGE_REL_BASED_DIR64:
+#ifdef DEBUG_REALLOCS
+ _ftprintf( stderr, _T("REL_BASED_DIR64\n"));
+#endif
+ // FIXME
+ break;
+
+ case IMAGE_REL_BASED_ABSOLUTE:
+ // stop processing
+ len = 0;
+ break;
+
+ case IMAGE_REL_BASED_HIGH:
+ case IMAGE_REL_BASED_LOW:
+ case IMAGE_REL_BASED_HIGHADJ:
+#ifdef DEBUG_REALLOCS
+ _ftprintf( stderr, _T("Unexpected block type %d\n"), type );
+#endif
+ break;
+
+ default:
+#ifdef DEBUG_REALLOCS
+ _ftprintf( stderr, _T("Unknown block type %d\n"), type );
#endif
+ break;
+ }
+
+
+ len -= sizeof(WORD);
+ pw++;
+ }
+ }
+
+ blocklen -= pIBR->SizeOfBlock;
+ if ( blocklen > sizeof(IMAGE_BASE_RELOCATION) )
+ pIBR = (PIMAGE_BASE_RELOCATION)( (PBYTE)pIBR + pIBR->SizeOfBlock );
+ else
+ break;
+ }
}
+#ifdef DEBUG_SECTIONS
+ _ftprintf( stderr, _T("%s - %08X - %d "), pISH->Name, pISH->PointerToRawData, pISH->SizeOfRawData);
+
+ {
+ int i;
+ mir_md5_byte_t digest2[16];
+ mir_md5_state_t pms2;
+
+ mir_md5_init( &pms2 );
+ mir_md5_append( &pms2, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );
+ mir_md5_finish( &pms2, digest2 );
+
+ for ( i = 0; i < sizeof( digest2 ) / sizeof( digest2[0] ); i++ )
+ _ftprintf( stderr, _T("%02X"), digest2[i] );
+ _ftprintf( stderr, _T("\n") );
+ }
+#endif
mir_md5_append( &pms, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );