summaryrefslogtreecommitdiff
path: root/plugins/PluginUpdater/src/checksum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/PluginUpdater/src/checksum.cpp')
-rw-r--r--plugins/PluginUpdater/src/checksum.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/plugins/PluginUpdater/src/checksum.cpp b/plugins/PluginUpdater/src/checksum.cpp
new file mode 100644
index 0000000000..ae300a1f9b
--- /dev/null
+++ b/plugins/PluginUpdater/src/checksum.cpp
@@ -0,0 +1,290 @@
+
+// Checksum Tool
+// By Bio (C) 2012
+
+#include "common.h"
+
+// Return codes
+#define RESULT_OK 0
+#define RESULT_NOTFOUND 10
+#define RESULT_READERROR 20
+#define RESULT_NOTPE 30
+#define RESULT_CORRUPTED 40
+#define RESULT_INVALID 50
+#define RESULT_NONE 100
+
+#define DEBUG_SECTIONS 1
+#define DEBUG_REALLOCS 1
+
+int debug = 0;
+
+int CalculateModuleHash(const TCHAR *filename, char* szDest)
+{
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ HANDLE hMap;
+ PBYTE ptr = 0;
+ int res = RESULT_OK;
+ DWORD filesize;
+ DWORD hsize = 0;
+
+ WORD machine = 0;
+ DWORD sections = 0;
+
+ hFile = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
+
+ if ( hFile == INVALID_HANDLE_VALUE )
+ return RESULT_NOTFOUND;
+
+ // check minimum and maximum size
+ filesize = GetFileSize( hFile, &hsize );
+
+ if ( !filesize || filesize == INVALID_FILE_SIZE || hsize) {
+ CloseHandle( hFile );
+ return RESULT_INVALID;
+ }
+
+ if (filesize < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS)) {
+ CloseHandle( hFile );
+ return RESULT_NOTPE;
+ }
+
+ hMap = CreateFileMapping( hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL );
+ if ( hMap )
+ ptr = (PBYTE)MapViewOfFile( hMap, FILE_MAP_COPY, 0, 0 ,0 );
+
+ if ( ptr ) {
+ PIMAGE_DOS_HEADER pIDH = 0;
+ PIMAGE_NT_HEADERS pINTH = 0;
+
+ pIDH = (PIMAGE_DOS_HEADER)ptr;
+
+ if ( pIDH->e_magic == IMAGE_DOS_SIGNATURE )
+ pINTH = (PIMAGE_NT_HEADERS)( ptr + pIDH->e_lfanew );
+
+ if ( !pINTH)
+ res = RESULT_NOTPE;
+ else
+ if ((PBYTE)pINTH + sizeof(IMAGE_NT_HEADERS) >= ptr + filesize )
+ res = RESULT_CORRUPTED;
+ else
+ if ( pINTH->Signature != IMAGE_NT_SIGNATURE )
+ res = RESULT_NOTPE;
+ else {
+ machine = pINTH->FileHeader.Machine;
+ sections = pINTH->FileHeader.NumberOfSections;
+
+ if ( !sections )
+ res = RESULT_INVALID;
+ else {
+ PIMAGE_DATA_DIRECTORY pIDD = 0;
+ PIMAGE_DEBUG_DIRECTORY pDBG = 0;
+ DWORD dbgsize = 0;
+ DWORD dbgvaddr = 0;
+ DWORD expsize = 0;
+ DWORD expvaddr = 0;
+ PBYTE pRealloc = 0;
+ DWORD realvaddr = 0;
+ DWORD realsize = 0;
+ DWORD offset;
+ ULONGLONG 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 ) &&
+ ( pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER64)) &&
+ ( pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ))
+ {
+ pIDD = (PIMAGE_DATA_DIRECTORY)((PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory ));
+ base = *(ULONGLONG*)((PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.ImageBase ));
+ }
+ else res = RESULT_CORRUPTED;
+
+ if ( pIDD ) {
+ // Debugging information entry
+ dbgvaddr = pIDD[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ dbgsize = pIDD[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+
+ // Export information entry
+ expvaddr = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ expsize = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
+
+ // 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 ) || ( pISH->PointerToRawData + pISH->SizeOfRawData > filesize )) {
+ res = RESULT_CORRUPTED;
+ break;
+ }
+
+ // erase timestamp
+ if (( dbgsize >= sizeof( IMAGE_DEBUG_DIRECTORY )) &&
+ ( dbgvaddr >= pISH->VirtualAddress ) &&
+ ( dbgvaddr + dbgsize <= pISH->VirtualAddress + pISH->SizeOfRawData ))
+ {
+ DWORD shift = dbgvaddr - pISH->VirtualAddress;
+ pDBG = (PIMAGE_DEBUG_DIRECTORY)( ptr + shift + pISH->PointerToRawData );
+
+ pDBG->TimeDateStamp = 0;
+ //ZeroMemory( ptr + pISH->PointerToRawData + shift, dbgsize );
+ }
+
+ // erase export timestamp
+ if (( expsize >= sizeof( IMAGE_EXPORT_DIRECTORY )) &&
+ ( expvaddr >= pISH->VirtualAddress ) &&
+ ( expvaddr + expsize <= pISH->VirtualAddress + pISH->SizeOfRawData ))
+ {
+ DWORD shift = expvaddr - pISH->VirtualAddress;
+ PIMAGE_EXPORT_DIRECTORY pEXP = (PIMAGE_EXPORT_DIRECTORY)( ptr + shift + pISH->PointerToRawData );
+
+ pEXP->TimeDateStamp = 0;
+ }
+
+ // 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;
+ }
+
+ idx++;
+ }
+ }
+
+ if ( res == RESULT_OK )
+ {
+ PIMAGE_SECTION_HEADER pISH = 0;
+ DWORD idx = 0;
+
+ 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;
+ }
+
+ // erase debug information
+ if ( pDBG && ( pDBG->SizeOfData > 0 ) &&
+ ( pDBG->PointerToRawData >= pISH->PointerToRawData ) &&
+ ( pDBG->PointerToRawData + pDBG->SizeOfData <= pISH->PointerToRawData + pISH->SizeOfRawData ))
+ {
+ ZeroMemory( ptr + pDBG->PointerToRawData, pDBG->SizeOfData );
+ }
+
+ // rebase to zero 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));
+
+ 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)((*(PDWORD)pAddr) - (DWORD)base );
+ break;
+
+ case IMAGE_REL_BASED_DIR64:
+ if ( addr + pIBR->VirtualAddress + sizeof(ULONGLONG) >= pISH->VirtualAddress + pISH->SizeOfRawData ) {
+ len = 0;
+ break;
+ }
+ *(ULONGLONG*)pAddr = (ULONGLONG)((*(ULONGLONG*)pAddr) - base );
+ 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:
+ break;
+ }
+
+ len -= sizeof(WORD);
+ pw++;
+ }
+ }
+
+ blocklen -= pIBR->SizeOfBlock;
+ if ( blocklen > sizeof(IMAGE_BASE_RELOCATION))
+ pIBR = (PIMAGE_BASE_RELOCATION)((PBYTE)pIBR + pIBR->SizeOfBlock );
+ else
+ break;
+ }
+ }
+
+ mir_md5_append( &pms, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );
+
+ idx++;
+ }
+
+ if ( res == RESULT_OK ) {
+ BYTE digest[16];
+ mir_md5_finish(&pms, digest);
+
+ for (int i=0; i < sizeof(digest); i++)
+ sprintf(szDest + i*2, "%02x", digest[i]);
+ }
+ }
+ }
+ }
+ }
+ else res = RESULT_READERROR;
+
+ if ( ptr )
+ UnmapViewOfFile( ptr );
+
+ if ( hMap )
+ CloseHandle( hMap );
+
+ CloseHandle( hFile );
+
+ return res;
+}