From 2d53eaf62b773e28f031c545f650ab47d535a52a Mon Sep 17 00:00:00 2001 From: Dmitry Kuzkin Date: Tue, 10 Jul 2012 14:35:42 +0000 Subject: Checksum tool - calculates MD5 of all PE sections in file git-svn-id: http://svn.miranda-ng.org/main/trunk@888 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- tools/checksum/checksum.cpp | 232 ++++++++++++++++++++++++++++++++++++++++++++ tools/checksum/make.bat | 1 + 2 files changed, 233 insertions(+) create mode 100644 tools/checksum/checksum.cpp create mode 100644 tools/checksum/make.bat diff --git a/tools/checksum/checksum.cpp b/tools/checksum/checksum.cpp new file mode 100644 index 0000000000..367c86507d --- /dev/null +++ b/tools/checksum/checksum.cpp @@ -0,0 +1,232 @@ + +// Checksum Tool +// Version 1.0 +// By Bio (C) 2012 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include +#include +#include + +#include "../../include/m_core.h" + +#define DEBUG_MSGS 1 +#define DEBUG_ARCH 1 +// #define DEBUG_SECTIONS 1 + + +// 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 + + +int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16]) +{ + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMap; + PBYTE ptr = 0; + int res = RESULT_OK; + DWORD size; + 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 + size = GetFileSize(hFile, &hsize); + + if ( !size || size == INVALID_FILE_SIZE || hsize ) + { + CloseHandle( hFile ); + return RESULT_INVALID; + } + + if ( size < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) ) + { + CloseHandle( hFile ); + return RESULT_NOTPE; + } + + hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); + + if (hMap) + ptr = (PBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0 ,0); + + if (ptr) + { + PIMAGE_DOS_HEADER pIDH = 0; + PIMAGE_NT_HEADERS pINTH = 0; + PIMAGE_SECTION_HEADER pISH = 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 + size ) + res = RESULT_CORRUPTED; + else + if ( pINTH->Signature != IMAGE_NT_SIGNATURE ) + res = RESULT_NOTPE; + else + { + machine = pINTH->FileHeader.Machine; + +#if defined(DEBUG_ARCH) && defined(DEBUG_MSGS) + switch(machine) + { + case IMAGE_FILE_MACHINE_I386: + fprintf( stdout, "(x86) "); + break; + case IMAGE_FILE_MACHINE_AMD64: + fprintf( stdout, "(x64) "); + break; + case IMAGE_FILE_MACHINE_IA64: + fprintf( stdout, "(IA64 :-) "); + break; + default: + fprintf( stdout, "(unknown) "); + break; + } +#endif + sections = pINTH->FileHeader.NumberOfSections; + + if ( !sections ) + res = RESULT_INVALID; + else + { + DWORD idx = 0; + mir_md5_state_t pms; + + mir_md5_init( &pms ); + +#if defined(DEBUG_SECTIONS) && defined(DEBUG_MSGS) + fprintf( stdout, "\n" ); +#endif + // try to found correct offset independent of architectures + DWORD offset = pIDH->e_lfanew + pINTH->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_OPTIONAL_HEADER); + + while ( idx < sections ) + { + pISH = (PIMAGE_SECTION_HEADER)( ptr + offset + idx * sizeof(IMAGE_SECTION_HEADER) ); + + if ( (PBYTE)pISH + sizeof(IMAGE_SECTION_HEADER) > ptr + size ) + { + res = RESULT_CORRUPTED; + break; + } + + if ( pISH->PointerToRawData + pISH->SizeOfRawData > size ) + { + res = RESULT_CORRUPTED; + break; + } + +#if defined(DEBUG_SECTIONS) && defined(DEBUG_MSGS) + fprintf( stdout, "%s - %d - %d \n", pISH->Name, pISH->PointerToRawData, pISH->SizeOfRawData); +#endif + mir_md5_append( &pms, ptr + pISH->PointerToRawData, pISH->SizeOfRawData ); + + idx++; + } + + if ( res == RESULT_OK ) + mir_md5_finish( &pms, digest ); + + } + } + } + else + res = RESULT_READERROR; + + if ( ptr ) + UnmapViewOfFile( ptr ); + + if ( hMap ) + CloseHandle( hMap ); + + CloseHandle( hFile ); + + return res; +} + + +int main( int argc, char** argv ) +{ + mir_md5_byte_t digest[16] = {0}; + int res = 0; + + if ( argc > 1 ) + { + for ( int i=1; i < argc; i++ ) + { +#ifdef DEBUG_MSGS + fprintf( stdout, "Processing '%s'... ", argv[ i ] ); +#endif + res = PEChecksum( argv[ i ], digest); + + switch(res) + { +#ifdef DEBUG_MSGS + case RESULT_NOTFOUND: + { + fprintf( stdout, "not found!\n"); + break; + } + case RESULT_READERROR: + { + fprintf( stdout, "read error!\n"); + break; + } + case RESULT_NOTPE: + { + fprintf( stdout, "not PE type!\n"); + break; + } + case RESULT_CORRUPTED: + { + fprintf( stdout, "corrupted\n"); + break; + } +#endif + case RESULT_OK: + { + int i; + for ( i = 0; i < sizeof(digest) / sizeof(digest[0]); i++ ) + fprintf( stdout, "%02X", digest[i] ); + } // no break + default: + { + fprintf( stdout, "\n"); + break; + } + } + } + + } + else + { + fprintf( stderr, "PE CHECKSUM TOOL v1.0\n\n" ); + fprintf( stderr, "Usage: checksum.exe [filename] ... [filename]\n"); + fprintf( stderr, "Output: MD5 checksum of all sections in PE file.\n"); + return RESULT_NONE; + } + + return res; +} \ No newline at end of file diff --git a/tools/checksum/make.bat b/tools/checksum/make.bat new file mode 100644 index 0000000000..ade2bb93d8 --- /dev/null +++ b/tools/checksum/make.bat @@ -0,0 +1 @@ +@cl /MD /Fe../../bin10/Release/checksum.exe checksum.cpp ../../bin10/lib/mir_core.lib /link /filealign:512 \ No newline at end of file -- cgit v1.2.3