diff options
author | Dmitry Kuzkin <bio@ktaspb.ru> | 2012-07-11 10:10:55 +0000 |
---|---|---|
committer | Dmitry Kuzkin <bio@ktaspb.ru> | 2012-07-11 10:10:55 +0000 |
commit | 6e4a285f3b2d6a4f8a29ac0004e31e5b22993001 (patch) | |
tree | 9106e58f4164fee0feff548e7e10a131e3431305 /tools/checksum/checksum.cpp | |
parent | db3992b55d0616896da4f616dfd09fac6642b292 (diff) |
version 2.0
+ exclude from calculation debug information and timestamps in debug and export entries
+ print to stdout only filename+hash
+ support for wildcards and stdin input
+ remove mir_core.dll dependency
git-svn-id: http://svn.miranda-ng.org/main/trunk@898 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'tools/checksum/checksum.cpp')
-rw-r--r-- | tools/checksum/checksum.cpp | 370 |
1 files changed, 248 insertions, 122 deletions
diff --git a/tools/checksum/checksum.cpp b/tools/checksum/checksum.cpp index 1dce5c3052..13d13eb9ae 100644 --- a/tools/checksum/checksum.cpp +++ b/tools/checksum/checksum.cpp @@ -1,21 +1,12 @@ // Checksum Tool
-// Version 1.0
// By Bio (C) 2012
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define _VERSION_ "2.0"
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <windows.h>
-
-#include <m_core.h>
-
-#define DEBUG_MSGS 1
-#define DEBUG_ARCH 1
-// #define DEBUG_SECTIONS 1
+#include "commonheaders.h"
+//#define DEBUG_SECTIONS 1
// Return codes
#define RESULT_OK 0
@@ -27,16 +18,16 @@ #define RESULT_NONE 100
-int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16])
+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;
+ int res = RESULT_OK;
+ DWORD filesize;
+ DWORD hsize = 0;
- WORD machine = 0;
+ WORD machine = 0;
DWORD sections = 0;
hFile = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
@@ -46,30 +37,29 @@ int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16]) }
// check minimum and maximum size
- size = GetFileSize(hFile, &hsize);
+ filesize = GetFileSize( hFile, &hsize );
- if ( !size || size == INVALID_FILE_SIZE || hsize )
+ if ( !filesize || filesize == INVALID_FILE_SIZE || hsize )
{
CloseHandle( hFile );
- return RESULT_INVALID;
+ return RESULT_INVALID;
}
- if ( size < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) )
+ if ( filesize < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) )
{
CloseHandle( hFile );
- return RESULT_NOTPE;
+ return RESULT_NOTPE;
}
- hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
+ hMap = CreateFileMapping( hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL );
- if (hMap)
- ptr = (PBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0 ,0);
+ if ( hMap )
+ ptr = (PBYTE)MapViewOfFile( hMap, FILE_MAP_COPY, 0, 0 ,0 );
- if (ptr)
+ if ( ptr )
{
PIMAGE_DOS_HEADER pIDH = 0;
PIMAGE_NT_HEADERS pINTH = 0;
- PIMAGE_SECTION_HEADER pISH = 0;
pIDH = (PIMAGE_DOS_HEADER)ptr;
@@ -79,7 +69,7 @@ int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16]) if ( !pINTH)
res = RESULT_NOTPE;
else
- if ( (PBYTE)pINTH + sizeof(IMAGE_NT_HEADERS) >= ptr + size )
+ if ( (PBYTE)pINTH + sizeof(IMAGE_NT_HEADERS) >= ptr + filesize )
res = RESULT_CORRUPTED;
else
if ( pINTH->Signature != IMAGE_NT_SIGNATURE )
@@ -87,68 +77,152 @@ int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16]) 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) ");
+/*
+ switch(machine)
+ {
+ case IMAGE_FILE_MACHINE_I386:
+ _ftprintf( stderr, _T("(x86) ") );
+ break;
+ case IMAGE_FILE_MACHINE_AMD64:
+ _ftprintf( stderr, _T("(x64) ") );
+ break;
+ case IMAGE_FILE_MACHINE_IA64:
+ _ftprintf( stderr, _T("(IA64 :-) ") );
break;
- }
-#endif
+ default:
+ _ftprintf( stderr, _T("(unknown) ") );
+ break;
+ }
+*/
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);
+ PIMAGE_DATA_DIRECTORY pIDD = 0;
+ DWORD dbgsize = 0;
+ DWORD dbgvaddr = 0;
+ DWORD expsize = 0;
+ DWORD expvaddr = 0;
+
+ 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 ) );
+ }
+ else
+ if ( ( machine == IMAGE_FILE_MACHINE_AMD64 ) &&
+ ( pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER64) ) &&
+ ( pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ) )
+ {
- while ( idx < sections )
+ pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory ) );
+ }
+ 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;
+ }
+
+ if ( res == RESULT_OK )
{
- 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);
+ 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);
+
+ 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);
+
+ {
+ 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
+ // erase timestamp and debug information
+ if (( dbgsize >= sizeof( IMAGE_DEBUG_DIRECTORY ) ) &&
+ ( dbgvaddr >= pISH->VirtualAddress ) &&
+ ( 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 );
+#endif
+ if ( pDBG->SizeOfData > 0 &&
+ ( pDBG->PointerToRawData >= pISH->PointerToRawData ) &&
+ ( pDBG->PointerToRawData + pDBG->SizeOfData <= pISH->PointerToRawData + pISH->SizeOfRawData ) )
+ {
+ ZeroMemory( ptr + pDBG->PointerToRawData, pDBG->SizeOfData );
+ }
+
+ //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;
+#ifdef DEBUG_SECTIONS
+ _ftprintf( stderr, _T("found export section entry %08X\n"), pISH->PointerToRawData + shift );
#endif
- mir_md5_append( &pms, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );
+ }
- idx++;
- }
+ mir_md5_append( &pms, ptr + pISH->PointerToRawData, pISH->SizeOfRawData );
- if ( res == RESULT_OK )
- mir_md5_finish( &pms, digest );
+ idx++;
+ }
+ if ( res == RESULT_OK )
+ mir_md5_finish( &pms, digest );
+ }
}
}
}
@@ -167,66 +241,118 @@ int PEChecksum(TCHAR *filename, mir_md5_byte_t digest[16]) }
-int main( int argc, char** argv )
+TCHAR* trtrim( TCHAR *str )
+{
+ if ( str == NULL )
+ return NULL;
+
+ TCHAR* p = _tcschr( str, 0 );
+ while ( --p >= str )
+ {
+ switch ( *p )
+ {
+ case L' ': case L'\t': case L'\n': case L'\r':
+ *p = 0; break;
+ default:
+ return str;
+ }
+ }
+ return str;
+}
+
+
+int process(TCHAR *filename)
{
- mir_md5_byte_t digest[16] = {0};
- int res = 0;
+ int res;
+ mir_md5_byte_t digest[16] = {0};
+
+ res = PEChecksum( filename, digest);
+
+ switch(res)
+ {
+ case RESULT_NOTFOUND:
+ _ftprintf( stderr, _T("'%s'... not found!\n"), filename );
+ break;
+ case RESULT_READERROR:
+ _ftprintf( stderr, _T("'%s'... read error!\n"), filename );
+ break;
+ case RESULT_NOTPE:
+ _ftprintf( stderr, _T("'%s'... not PE type!\n"), filename );
+ break;
+ case RESULT_CORRUPTED:
+ _ftprintf( stderr, _T("'%s'... corrupted!\n"), filename );
+ break;
+ case RESULT_OK:
+ {
+ int i;
+ _ftprintf( stdout, _T("%s "), filename );
+ for ( i = 0; i < sizeof( digest ) / sizeof( digest[0] ); i++ )
+ _ftprintf( stdout, _T("%02X"), digest[i] );
+ _ftprintf( stdout, _T("\n") );
+ break;
+ }
+ default:
+ break;
+ }
+ return res;
+}
+
+
+int _tmain( int argc, TCHAR *argv[] )
+{
+ TCHAR buf[ MAX_PATH ];
+ int res = 0;
+ int cnt = 0;
+
+ _ftprintf( stderr, _T("* PE CHECKSUM TOOL * VERSION %s\n\n"), _VERSION_ );
if ( argc > 1 )
{
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+
+ _ftprintf( stderr, _T("Processing ... \n") );
+
for ( int i=1; i < argc; i++ )
{
-#ifdef DEBUG_MSGS
- fprintf( stdout, "Processing '%s'... ", argv[ i ] );
-#endif
- res = PEChecksum( argv[ i ], digest);
+ hFind = FindFirstFile( argv[i], &ffd );
- 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;
+ while( hFind != INVALID_HANDLE_VALUE )
+ {
+ if ( ! ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
+ {
+ res = process( ffd.cFileName );
+ cnt++;
}
-#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");
+ if ( !FindNextFile( hFind, &ffd ) )
break;
- }
}
+
+ FindClose( hFind );
}
+ _ftprintf( stderr, _T("%d file(s) processed.\n"), cnt );
}
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;
+ while ( _fgetts( buf, sizeof( buf ), stdin ) != NULL )
+ {
+ if ( !cnt )
+ _ftprintf( stderr, _T("Processing ... \n") );
+ trtrim( buf );
+ res = process( buf );
+ cnt++;
+ }
+
+ if ( cnt )
+ _ftprintf( stderr, _T("%d file(s) processed.\n"), cnt );
+ else
+ {
+ _ftprintf( stderr, _T("Usage: checksum.exe [*.dll] ... [*.exe]\n") );
+ _ftprintf( stderr, _T("Example: dir /b /s | checksum.exe > hashes.txt\n") );
+ res = RESULT_NONE;
+ }
}
return res;
-}
\ No newline at end of file +}
|