From bc5de7df3d29bc8afd8f757cccd0719f37aa4933 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzkin Date: Fri, 13 Jul 2012 18:53:40 +0000 Subject: - relocation tables processing for compatibility with rebaser (only for x86 builds) git-svn-id: http://svn.miranda-ng.org/main/trunk@953 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- tools/checksum/checksum.cpp | 252 +++++++++++++++++++++++++++++++++++--------- tools/checksum/checksum.exe | Bin 11264 -> 53760 bytes tools/checksum/make.bat | 3 +- 3 files changed, 203 insertions(+), 52 deletions(-) (limited to 'tools') 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 ); diff --git a/tools/checksum/checksum.exe b/tools/checksum/checksum.exe index 50ba53f7af..6b9e9ef7ea 100644 Binary files a/tools/checksum/checksum.exe and b/tools/checksum/checksum.exe differ diff --git a/tools/checksum/make.bat b/tools/checksum/make.bat index 07e3402278..d4da86645f 100644 --- a/tools/checksum/make.bat +++ b/tools/checksum/make.bat @@ -1 +1,2 @@ -@cl /MD /O2 /GL /Fe../../bin10/checksum.exe md5.cpp checksum.cpp /link /filealign:512 +rem @cl /MT /O2 /GL /Fe../../bin10/checksum.exe md5.cpp checksum.cpp /link /filealign:512 +@cl /MT /O2 /GL /Fe./checksum.exe md5.cpp checksum.cpp /link /filealign:512 \ No newline at end of file -- cgit v1.2.3