1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
/*
* The Sleuth Kit
*
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
* Copyright (c) 2011-2012 Basis Technology Corporation. All Rights
* reserved.
*
* This software is distributed under the Common Public License 1.0
*/
/** \file HashCalcModule.cpp
* Contains the implementation of the hash calculation file analysis module.
*/
// System includes
#include <string>
#include <sstream>
#include <string.h>
// Framework includes
#include "tsk/framework/utilities/TskModuleDev.h"
// strings for command line arguments
static const std::string MD5_NAME("MD5");
static const std::string SHA1_NAME("SHA1");
static bool calculateMD5 = true;
static bool calculateSHA1 = false;
static const char hexMap[] = "0123456789abcdef";
extern "C"
{
/**
* Module identification function.
*
* @return The name of the module.
*/
TSK_MODULE_EXPORT const char *name()
{
return "tskHashCalcModule";
}
/**
* Module identification function.
*
* @return A description of the module.
*/
TSK_MODULE_EXPORT const char *description()
{
return "Calculates MD5 and/or SHA-1 hashes of file content";
}
/**
* Module identification function.
*
* @return The version of the module.
*/
TSK_MODULE_EXPORT const char *version()
{
return "1.0.1";
}
/**
* Module initialization function. Receives arguments, typically read by the
* caller from a pipeline configuration file, that determine what hashes the
* module calculates for a given file.
*
* @param args Valid values are "MD5", "SHA1" or the empty string which will
* result in just "MD5" being calculated. Hash names can be in any order,
* separated by spaces or commas.
* @return TskModule::OK if initialization arguments are valid, otherwise
* TskModule::FAIL.
*/
TskModule::Status TSK_MODULE_EXPORT initialize(const char* arguments)
{
std::string args(arguments);
// If the argument string is empty we calculate both hashes.
if (args.empty()) {
calculateMD5 = true;
calculateSHA1 = false;
}
else {
calculateMD5 = false;
calculateSHA1 = false;
// If the argument string contains "MD5" we calculate an MD5 hash.
if (args.find(MD5_NAME) != std::string::npos)
calculateMD5 = true;
// If the argument string contains "SHA1" we calculate a SHA1 hash.
if (args.find(SHA1_NAME) != std::string::npos)
calculateSHA1 = true;
// If neither hash is to be calculated it means that the arguments
// passed to the module were incorrect. We log an error message
// through the framework logging facility.
if (!calculateMD5 && !calculateSHA1) {
std::stringstream msg;
msg << "Invalid arguments passed to hash module: " << args.c_str();
LOGERROR(msg.str());
return TskModule::FAIL;
}
}
if (calculateMD5)
LOGINFO("HashCalcModule: Configured to calculate MD5 hashes");
if (calculateSHA1)
LOGINFO("HashCalcModule: Configured to calculate SHA-1 hashes");
return TskModule::OK;
}
/**
* Module execution function. Receives a pointer to a file the module is to
* process. The file is represented by a TskFile interface which is used
* to read the contents of the file and post calculated hashes of the
* file contents to the database.
*
* @param pFile A pointer to a file for which the hash calculations are to be performed.
* @returns TskModule::OK on success, TskModule::FAIL on error.
*/
TskModule::Status TSK_MODULE_EXPORT run(TskFile * pFile)
{
if (pFile == NULL)
{
LOGERROR("HashCalcModule: passed NULL file pointer.");
return TskModule::FAIL;
}
// We will not attempt to calculate hash values for "unused sector"
// files.
if (pFile->getTypeId() == TskImgDB::IMGDB_FILES_TYPE_UNUSED)
return TskModule::OK;
try
{
TSK_MD5_CTX md5Ctx;
TSK_SHA_CTX sha1Ctx;
if (calculateMD5)
TSK_MD5_Init(&md5Ctx);
if (calculateSHA1)
TSK_SHA_Init(&sha1Ctx);
// file buffer
static const uint32_t FILE_BUFFER_SIZE = 32768;
char buffer[FILE_BUFFER_SIZE];
ssize_t bytesRead = 0;
// Read file content into buffer and write it to the DigestOutputStream.
do
{
bytesRead = pFile->read(buffer, FILE_BUFFER_SIZE);
if (bytesRead > 0) {
if (calculateMD5)
TSK_MD5_Update(&md5Ctx, (unsigned char *) buffer, (unsigned int) bytesRead);
if (calculateSHA1)
TSK_SHA_Update(&sha1Ctx, (unsigned char *) buffer, (unsigned int) bytesRead);
}
} while (bytesRead > 0);
if (calculateMD5) {
unsigned char md5Hash[16];
TSK_MD5_Final(md5Hash, &md5Ctx);
char md5TextBuff[33];
for (int i = 0; i < 16; i++) {
md5TextBuff[2 * i] = hexMap[(md5Hash[i] >> 4) & 0xf];
md5TextBuff[2 * i + 1] = hexMap[md5Hash[i] & 0xf];
}
md5TextBuff[32] = '\0';
pFile->setHash(TskImgDB::MD5, md5TextBuff);
}
if (calculateSHA1) {
unsigned char sha1Hash[20];
TSK_SHA_Final(sha1Hash, &sha1Ctx);
char textBuff[41];
for (int i = 0; i < 20; i++) {
textBuff[2 * i] = hexMap[(sha1Hash[i] >> 4) & 0xf];
textBuff[2 * i + 1] = hexMap[sha1Hash[i] & 0xf];
}
textBuff[40] = '\0';
pFile->setHash(TskImgDB::SHA1, textBuff);
}
}
catch (TskException& tskEx)
{
std::stringstream msg;
msg << "HashCalcModule - Error processing file id " << pFile->getId() << ": " << tskEx.what();
LOGERROR(msg.str());
return TskModule::FAIL;
}
catch (std::exception& ex)
{
std::stringstream msg;
msg << "HashCalcModule - Error processing file id " << pFile->getId() << ": " << ex.what();
LOGERROR(msg.str());
return TskModule::FAIL;
}
return TskModule::OK;
}
/**
* Module cleanup function. This module does not need to free any
* resources allocated during initialization or execution.
*
* @returns TskModule::OK
*/
TskModule::Status TSK_MODULE_EXPORT finalize()
{
return TskModule::OK;
}
}
|