@echo off ::######################################################################### :: script for obtaining md5,sha256 and tiger hashsums for a file or for :: all files in a given directory. :: :: Output printed in a format required for import into :: Shalla Secure Services (compare http://md5.shalla.de) :: hash database :: :: written 10/2009 by Joerg Helmert (joerg.helmert(at)gmx.de) :: be aware: emails to this account read rather seldom... ::######################################################################### ::========================================================================= :: Initialization. Set some variables and perform some checks ::========================================================================= :: enable some functionality in cmd.exe and limit variables to local context ::------------------------------------------------------------------------- setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION ::------------------------------------------------------------------------- :: Boolean switches. Set to some value (e.g. 1) or unset with "set =" :: Switches will be tested by "if DEFINED" or "if NOT DEFINED" ::------------------------------------------------------------------------- :: default: Debug disabled set debug= :: default: Batch disabled set batch= :: default: Recursion disabled set recursive= :: default: use filever.exe to get windows file properties set withfilever=1 ::------------------------------------------------------------------------- :: Set some constant values ::------------------------------------------------------------------------- set ERR_PARAMETER_MISSING=10 set ERR_UNKNOWN_OPTION=11 set ERR_FILENAME_MISSING=12 set ERR_TOO_MANY_PARAMS=13 set ERR_HASHPROG_MISSING=14 set ERR_PROG_MISSING=19 set WARN_TEMP_MISSING=20 set WARN_HASHPROG_MISSING=24 set myCall=%0 %* set myName=%~n0 set WorkDir=%~dp0 set hashprg=c:\bin\hashdeep.exe set filever=c:\bin\filever.exe ::------------------------------------------------------------------------- :: Initialize some variables ::------------------------------------------------------------------------- set ERR=0 set param= set object2hash= call :SETTIMESTAMP set tempfile=%myName%.tmp.%timestamp% set temppath= set annotation= ::------------------------------------------------------------------------- :: Read parameters from CMD-Line ::------------------------------------------------------------------------- :: check, if we have some parameters... if "%1"=="" ( set ERR=%ERR_PARAMETER_MISSING% if NOT DEFINED batch ( echo ERROR: You did not give me parameters... call :USAGE ) goto :END ) :: Read parameters in a loop and set some control values :READPARAM :: we have to use a certain name, cause string operation does not work on parameter variables like %1 set param=%1 :: sorry, no case/switch statement in batches. We have to use if/else/goto constructs if "%param:~0,1%"=="-" ( if /I "%1"=="-d" ( set debug=1 goto :ENDREADPARAM ) if /I "%1"=="-b" ( set batch=1 goto :ENDREADPARAM ) if /I "%1"=="-r" ( set recursive=1 goto :ENDREADPARAM ) if /I "%1"=="-a" ( set annotation=%2 shift /1 goto :ENDREADPARAM ) set ERR=%ERR_UNKNOWN_OPTION% if NOT DEFINED batch ( echo ERROR: You gave me an unknown option... call :USAGE ) goto :END ) else ( if not defined object2hash ( set object2hash=%1 ) else ( set ERR=%ERR_TOO_MANY_PARAMS% if NOT DEFINED batch ( echo ERROR: You gave me to much parameters... call :USAGE ) goto :END ) ) :ENDREADPARAM :: shift parameters and loop again, if a parameter is left. shift /1 if not "%1"=="" goto :READPARAM ::------------------------------------------------------------------------- :: Check, if we have all information to do our work ::------------------------------------------------------------------------- if NOT DEFINED object2hash ( set ERR=%ERR_FILENAME_MISSING% if NOT DEFINED batch ( echo ERROR: You did not give me an object to calculate hashes of... call :USAGE ) goto :END ) :: search for hash program if NOT EXIST %hashprg% ( set ERR=%WARN_HASHPROG_MISSING% if NOT DEFINED batch ( echo WARNING: configured hash program not found... echo I'll try to find hashdeep in the searchpath and continue... ) call :FIND-PROG hashdeep.exe if "%ERR%" == "%ERR_PROG_MISSING" ( set ERR=%ERR_HASHPROG_MISSING% if NOT DEFINED batch ( echo ERROR: unable to find hash program... ) ) ) :: search for filever.exe. if NOT EXIST %filever% ( call :FIND-PROG filever.exe if "%ERR%" == "%ERR_PROG_MISSING" ( set withfilever= ) ) :: check existance of standard temp direcories. Prefer "temp" over "tmp" if DEFINED tmp ( if EXIST %tmp% ( set temppath=%tmp% ) ) if DEFINED temp ( if EXIST %temp% ( set temppath=%temp% ) ) if NOT DEFINED temppath ( set ERR=%WARN_TEMP_MISSING% if NOT DEFINED batch ( echo WARNING: no tempdirectory found. echo using workdirectory for temporary files... ) set temppath=%WorkDir% ) set lastchar=%temppath:~-1% if "%lastchar%" == "\" ( set tempfile=%temppath%%tempfile% ) else ( set tempfile=%temppath%\%tempfile% ) ::========================================================================= :: Main Program ::========================================================================= :MAIN :: create hash command set hashcmd=%hashprg% -c md5,sha256,tiger if DEFINED recursive ( set hashcmd=%hashcmd% -r ) set hashcmd=%hashcmd% %object2hash% :: Print information used for current run if DEFINED debug ( call :DEBUG-HEADER ) :: execute hash command %hashcmd% > %tempfile% set ERR=%ERRORLEVEL% if "%ERR%" NEQ "0" ( echo ERROR: An error occured while calculating the hashes... goto :ERRORWHILEHASHING ) :: generating output :: skips first 5 lines, splits at commas, reads 5 tokens per line :: 1 -> size, 2 -> md5, 3 -> sha256, 4 -> tiger, 5 -> rest of line (path\filename) for /f "skip=5 tokens=1-5* delims=," %%i in (%tempfile%) do ( set size=%%i set md5=%%j set sha256=%%k set tiger=%%l set file=%%m if DEFINED withfilever ( for /f "tokens=1-9* delims= " %%I in ('filever !file!') do ( set attr=%%I set head=%%J set ftype=%%K set lang=%%L set fver=%%M set stype=%%N set fdate=%%P ) :: do not print values for files of size "0". They all have the same checksums... if "!size!" NEQ "0" ( echo !md5!^|!sha256!^|!tiger!^|!file!^|!size!^|-^|!ftype!^|%annotation%Windows File Properties: attributes=!attr! fileheader=!head! language=!lang! version=!fver! shippingtype=!stype! filedate=!fdate! ) ) else ( echo !md5!^|!sha256!^|!tiger!^|!file!^|!size!^|-^|-^|%annotation% ) ) :ERRORWHILEHASHING :: Print resulting errorlevel if DEFINED debug ( call :DEBUG-FOOTER ) :END if NOT DEFINED debug ( del %tempfile% ) exit /b %ERR% ::========================================================================= :: Functions and subroutines ::========================================================================= :: SUB USAGE: Print short helpmessage to stdout :USAGE echo. echo Usage: %~n0 [Options] ^ echo. echo Options: echo ======== echo -a "": sets annotation text. echo -r: recurse through subdirectories echo -d: print debug output, while executing echo -b: ommit pretty error and result messages echo. echo Parameters: echo =========== echo ^: Filename or directory to calculate hash of echo. goto :EOF :: SUB DEBUG-HEADER: Print information used for current run :DEBUG-HEADER echo. echo I was called this way: %myCall% echo. echo I'm using following information for this run: echo. echo - debug is enabled if defined batch ( echo - batch is enabled ) else ( echo - batch is disabled ) if defined recursive ( echo - directory recursion is enabled ) else ( echo - directory recursion is disabled ) echo - I use following hash program: %hashprg% echo - I shall hash: %object2hash% echo - Hash command: %hashcmd% echo. echo executing...................................................... echo. goto :EOF :: SUB DEBUG-FOOTER: Print resulting errorlevel :DEBUG-FOOTER echo. echo. echo .......................................................finished echo. echo Errorlevel at end of execution of %~n0: %ERR% echo. echo --- Please keep in mind, that you are responsible for --- echo --- deleting temporary files, while debugging --- echo. echo Tempfile of this run: echo %tempfile% goto :EOF :: SUB FIND-PROG: search for a program within searchpath :FIND-PROG set fullname=%~$PATH:1% if not defined fullname ( set ERR=%ERR_PROG_MISSING% if NOT DEFINED batch ( echo ERROR: I'm unable to find a program %1... ) ) goto :EOF :: SUB SETTIMESTAMP: read current date and time and set variable timestamp :: format: YYYYMMDDhhmmss :SETTIMESTAMP for /f "tokens=1-3 delims=." %%i in ("%DATE%") do set day=%%k%%j%%i for /f "tokens=1-3 delims=:," %%i in ("%TIME%") do set hour=%%i%%j%%k set timestamp=%day%%hour% :: replace spaces by zero. leeding zeroes in time and date are expressed as space. :: thus one o clock in the night is " 1:00:00,00". This leeds to spaces in timestamps. :: 1:05:11,22 at 10/01/2009 gives "20091001 10511" instead of "20091001010511" set timestamp=%timestamp: =0% goto :EOF