diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp index 0e616dbad8d48d72916cab90e24d121908a0ac44..e9caaff5498ea17b430cae1849a100ded5b3b578 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp +++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp @@ -12,6 +12,7 @@ #include "tsk/auto/tsk_case_db.h" #include "tsk/hashdb/tsk_hash_info.h" #include "tsk/auto/tsk_is_image_supported.h" +#include "tsk/img/img_writer.h" #include "jni.h" #include "dataModel_SleuthkitJNI.h" #include <locale.h> @@ -1033,7 +1034,8 @@ JNIEXPORT jlong JNICALL */ JNIEXPORT void JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env, - jclass obj, jlong process, jstring deviceId, jobjectArray paths, jint numImgs, jstring timeZone) { + jclass obj, jlong process, jstring deviceId, jobjectArray paths, jint numImgs, + jstring timeZone, jstring imageWriterPathJ) { TskAutoDb *tskAuto = ((TskAutoDb *) process); if (!tskAuto || tskAuto->m_tag != TSK_AUTO_TAG) { @@ -1079,6 +1081,24 @@ JNIEXPORT void JNICALL env->ReleaseStringUTFChars(timeZone, time_zone); } + // Set up image writer, if the output path is present + if (env->GetStringLength(imageWriterPathJ) > 0) { + const char *imageWriterPath = env->GetStringUTFChars(imageWriterPathJ, &isCopy); + if (TSK_OK != tskAuto->enableImageWriter(imageWriterPath)) { + env->ReleaseStringUTFChars(imageWriterPathJ, imageWriterPath); + setThrowTskCoreError(env, + "runAddImgNat: error enabling image writer."); + return; + } + env->ReleaseStringUTFChars(imageWriterPathJ, imageWriterPath); + } + else { + tskAuto->disableImageWriter(); + setThrowTskCoreError(env, + "runAddImgNat: Disabling image writer."); + return; + } + // Add the data source. uint8_t ret = 0; if ( (ret = tskAuto->startAddImage((int) numImgs, imagepaths8, @@ -2061,3 +2081,34 @@ JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_isImageSupp return (jboolean) result; } + +/* + * Enable image writing during ingest + * @param env pointer to java environment this was called from + * @param obj the java object this was called from + * @param directoryJ directory to store the image in + * @param baseNameJ base name for the new image + * @return 0 if successful, -1 otherwise + */ +JNIEXPORT jint JNICALL +Java_org_sleuthkit_datamodel_SleuthkitJNI_enableImageWriterNat (JNIEnv * env, jclass obj, + jlong a_img_info, jstring directoryJ, jstring baseNameJ) { + + TSK_IMG_INFO *img_info = castImgInfo(env, a_img_info); + if (img_info == 0) { + //exception already set + return -1; + } + + TSK_TCHAR directoryT[1024]; + toTCHAR(env, directoryT, 1024, directoryJ); + + TSK_TCHAR baseNameT[1024]; + toTCHAR(env, baseNameT, 1024, baseNameJ); + + if (TSK_ERR == tsk_img_writer_create_from_dir(img_info, directoryT, baseNameT)) { + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h index e283fd074fc109f7d29452c0289d3ffc2f066e94..06e454ba3e887cc7aeb4bee0c9916af1d230911f 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.h +++ b/bindings/java/jni/dataModel_SleuthkitJNI.h @@ -226,10 +226,10 @@ JNIEXPORT jlong JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_initializeAddI /* * Class: org_sleuthkit_datamodel_SleuthkitJNI * Method: runAddImgNat - * Signature: (JLjava/lang/String;[Ljava/lang/String;ILjava/lang/String;)V + * Signature: (JLjava/lang/String;[Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat - (JNIEnv *, jclass, jlong, jstring, jobjectArray, jint, jstring); + (JNIEnv *, jclass, jlong, jstring, jobjectArray, jint, jstring, jstring); /* * Class: org_sleuthkit_datamodel_SleuthkitJNI @@ -399,6 +399,14 @@ JNIEXPORT jstring JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_getCurDirNat JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_isImageSupportedNat (JNIEnv *, jclass, jstring); +/* + * Class: org_sleuthkit_datamodel_SleuthkitJNI + * Method: enableImageWriterNat + * Signature: (JLjava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_enableImageWriterNat + (JNIEnv *, jclass, jlong, jstring, jstring); + #ifdef __cplusplus } #endif diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java index 972e06380cc06bc8ce1d60b0851c1a3f81ca4b7d..30ef618b49f3ca8d8dab5141338e3c06d323313e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java @@ -152,7 +152,7 @@ void free() throws TskCoreException { long addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone) throws TskCoreException { try { long tskAutoDbPointer = initializeAddImgNat(caseDbPointer, timezoneLongToShort(timeZone), false, false, false); - runAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone); + runAddImgNat(tskAutoDbPointer, UUID.randomUUID().toString(), imageFilePaths.toArray(new String[0]), imageFilePaths.size(), timeZone, ""); return commitAddImgNat(tskAutoDbPointer); } catch (TskDataException ex) { throw new TskCoreException("Error adding image to case database", ex); @@ -232,7 +232,7 @@ public void run(String deviceId, String[] imageFilePaths) throws TskCoreExceptio if (0 == tskAutoDbPointer) { throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer"); } - runAddImgNat(tskAutoDbPointer, deviceId, imageFilePaths, imageFilePaths.length, timeZone); + runAddImgNat(tskAutoDbPointer, deviceId, imageFilePaths, imageFilePaths.length, timeZone, "C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\autopsyVHD2.vhd"); } /** @@ -984,6 +984,10 @@ public static long findDeviceSize(String devPath) throws TskCoreException { public static boolean isImageSupported(String imagePath){ return isImageSupportedNat(imagePath); } + + public static int enableImageWriter(long imgHandle, String directory, String baseName){ + return enableImageWriterNat(imgHandle, directory, baseName); + } private static native String getVersionNat(); @@ -1039,7 +1043,7 @@ public static boolean isImageSupported(String imagePath){ private static native long initializeAddImgNat(long db, String timezone, boolean addFileSystems, boolean addUnallocSpace, boolean skipFatFsOrphans) throws TskCoreException; - private static native void runAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException; + private static native void runAddImgNat(long process, String deviceId, String[] imgPath, int splits, String timezone, String imageWriterPath) throws TskCoreException, TskDataException; private static native void stopAddImgNat(long process) throws TskCoreException; @@ -1082,5 +1086,7 @@ public static boolean isImageSupported(String imagePath){ private static native String getCurDirNat(long process); private static native boolean isImageSupportedNat(String imagePath); + + private static native int enableImageWriterNat(long imgHandle, String directory, String baseName); } diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp index 3ce2ddeaaceec80a86e0da47d46378d7c2bb123c..95e298fd240389b34fe15a892d36f9396fbf4757 100644 --- a/tsk/auto/auto.cpp +++ b/tsk/auto/auto.cpp @@ -15,6 +15,7 @@ #include "tsk_auto_i.h" #include "tsk/fs/tsk_fatxxfs.h" +#include "tsk/img/img_writer.h" // @@@ Follow through some error paths for sanity check and update docs somewhere to relfect the new scheme @@ -80,7 +81,10 @@ uint8_t closeImage(); m_internalOpen = true; + enableImageWriter("C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\newTest.vhd"); m_img_info = tsk_img_open(a_numImg, a_images, a_imgType, a_sSize); + tsk_img_writer_create(m_img_info, m_imageWriterPath); + //tsk_img_writer_create_from_dir(m_img_info, L"C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput", a_images[0]); if (m_img_info) return 0; else @@ -109,8 +113,9 @@ uint8_t m_internalOpen = true; m_img_info = tsk_img_open_utf8(a_numImg, a_images, a_imgType, a_sSize); - if (m_img_info) - return 0; + if (m_img_info) { + return 0; + } else return 1; } @@ -601,6 +606,55 @@ bool TskAuto::getStopProcessing() const { return m_stopAllProcessing; } + +TSK_RETVAL_ENUM +TskAuto::enableImageWriter(const char * imagePath) { +#ifdef TSK_WIN32 + m_imageWriterEnabled = false; + + size_t ilen; + UTF16 *utf16; + UTF8 *utf8; + TSKConversionResult retval2; + + // we allocate the buffer with the same number of chars as the UTF-8 length + ilen = strlen(imagePath); + if ((m_imageWriterPath = + (wchar_t *)tsk_malloc((ilen + 1) * sizeof(wchar_t))) == NULL) { + free(m_imageWriterPath); + return TSK_ERR; + } + + utf8 = (UTF8 *)imagePath; + utf16 = (UTF16 *)m_imageWriterPath; + + retval2 = + tsk_UTF8toUTF16((const UTF8 **)&utf8, &utf8[ilen], + &utf16, &utf16[ilen], TSKlenientConversion); + if (retval2 != TSKconversionOK) { + tsk_error_set_errno(TSK_ERR_IMG_CONVERT); + tsk_error_set_errstr + ("enableImageWriter: Error converting output path %s %d", + imagePath, retval2); + free(m_imageWriterPath); + return TSK_ERR; + } + *utf16 = '\0'; + + // At this point the path conversion was successful, so image writer is ready to go + m_imageWriterEnabled = true; + +#else + m_imageWriterEnabled = false; +#endif + return TSK_OK; +} + +void +TskAuto::disableImageWriter() { + m_imageWriterEnabled = false; +} + uint8_t TskAuto::registerError() { // add to our list of errors error_record er; diff --git a/tsk/auto/auto_db.cpp b/tsk/auto/auto_db.cpp index b2de68aeafc10833036d75998bb330c290ca7f06..b501476f1aebe64fae89196b138fda2b39e6a47f 100644 --- a/tsk/auto/auto_db.cpp +++ b/tsk/auto/auto_db.cpp @@ -14,6 +14,7 @@ */ #include "tsk_case_db.h" +#include "tsk/img/img_writer.h" #if HAVE_LIBEWF #include "tsk/img/ewf.h" #endif @@ -453,6 +454,10 @@ uint8_t registerError(); return 1; } + + if (m_imageWriterEnabled) { + tsk_img_writer_create(m_img_info, m_imageWriterPath); + } if (m_addFileSystems) { return addFilesInImgToDb(); @@ -516,6 +521,9 @@ uint8_t registerError(); return 1; } + if (m_imageWriterEnabled) { + tsk_img_writer_create(m_img_info, m_imageWriterPath); + } if (m_addFileSystems) { return addFilesInImgToDb(); diff --git a/tsk/auto/tsk_auto.h b/tsk/auto/tsk_auto.h index e428fcb66315f2965f12cc09d2c9691e5153be11..437799b511d496dc1aaa9d1289adfacb387b6d40 100644 --- a/tsk/auto/tsk_auto.h +++ b/tsk/auto/tsk_auto.h @@ -139,6 +139,16 @@ class TskAuto { virtual TSK_RETVAL_ENUM processFile(TSK_FS_FILE * fs_file, const char *path) = 0; + /** + * Enables image writer, which creates a copy of the image as it is being processed. + * @param imagePath UTF8 version of path to write the image to + */ + virtual TSK_RETVAL_ENUM enableImageWriter(const char * imagePath); + + /** + * Disables image writer + */ + virtual void disableImageWriter(); /** * Internal method that TskAuto calls when it encounters issues while processing an image. @@ -225,6 +235,7 @@ class TskAuto { void setCurVsPart(const TSK_VS_PART_INFO *); + protected: TSK_IMG_INFO * m_img_info; bool m_internalOpen; ///< True if m_img_info was opened in TskAuto and false if passed in @@ -239,6 +250,8 @@ class TskAuto { uint8_t isDefaultType(TSK_FS_FILE * fs_file, const TSK_FS_ATTR * fs_attr); uint8_t isNonResident(const TSK_FS_ATTR * fs_attr); + bool m_imageWriterEnabled; + wchar_t * m_imageWriterPath; TSK_RETVAL_ENUM processAttributes(TSK_FS_FILE * fs_file, @@ -263,6 +276,10 @@ class TskAuto { * When called, will cause TskAuto to not continue to recurse into directories and volumes. */ void setStopProcessing(); + + /** + * When called, will cause + */ }; diff --git a/tsk/img/img_writer.cpp b/tsk/img/img_writer.cpp index c0cf62334a25550803a2310330cf78be7188d1d2..5977888809fd2ed3f6edcfa23c68c90f8721396d 100644 --- a/tsk/img/img_writer.cpp +++ b/tsk/img/img_writer.cpp @@ -18,6 +18,7 @@ #include "tsk_img_i.h" #include "img_writer.h" #include "raw.h" +#include <time.h> #ifdef TSK_WIN32 #include <winioctl.h> @@ -32,6 +33,51 @@ TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer); +// TEMP LOGGING +char messageBuffer[0x2000]; +char logBuffer[0x2000]; +void openLogFile(TSK_IMG_WRITER * writer); +void writeLogFile(TSK_IMG_WRITER * writer, const char * message) { + if (writer->logFileHandle == 0) { + // Open it back up + openLogFile(writer); + } + time_t ltime; /* calendar time */ + ltime = time(NULL); /* get current cal time */ + sprintf(logBuffer, "%s : ", asctime(localtime(<ime))); + strcat(logBuffer, message); + + DWORD bytesWritten; + if (FALSE == WriteFile(writer->logFileHandle, logBuffer, + strlen(logBuffer), &bytesWritten, NULL)) { + int lastError = GetLastError(); + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_IMG_WRITE); + tsk_error_set_errstr("writeLogFile: error writing log", + lastError); + } +} + +void openLogFile(TSK_IMG_WRITER * writer) { + writer->logFileHandle = CreateFile(L"C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\tskLog.txt", FILE_APPEND_DATA, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, + NULL); + if (writer->logFileHandle == INVALID_HANDLE_VALUE) { + tsk_fprintf(stderr, "Error opening VHD!!!"); // temp + fflush(stderr); + int lastError = (int)GetLastError(); + writer->outputFileHandle = 0; /* so we don't close it next time */ + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_IMG_OPEN); + tsk_error_set_errstr("openLogFile: file %d", lastError); + } + writeLogFile(writer, "Opened log file\n"); + +} + + + + bool getBit(unsigned char * buffer, TSK_OFF_T index) { unsigned char b = buffer[index / 8]; return (b >> (7 - (index % 8)) & 0x01) == 1; @@ -309,6 +355,13 @@ static TSK_RETVAL_ENUM tsk_img_writer_add(TSK_IMG_WRITER* writer, TSK_OFF_T addr (TSK_OFF_T)len); } + sprintf(messageBuffer, "tsk_img_writer_add: addr: 0x%llx len: 0x%llx\n", addr, len); + writeLogFile(writer, messageBuffer); + + if (writer->outputFileHandle == 0) { + writeLogFile(writer, "tsk_img_writer_add: outputFileHandle is closed"); + } + /* This should never happen, but best to check */ if (addr % VHD_SECTOR_SIZE != 0) { return TSK_ERR; @@ -351,12 +404,18 @@ static TSK_RETVAL_ENUM tsk_img_writer_close(TSK_IMG_WRITER* img_writer) { tsk_fprintf(stderr, "tsk_img_writer_close: Closing image writer"); } + writeLogFile(img_writer, "Closing image writer"); + if (img_writer->outputFileHandle != 0) { CloseHandle(img_writer->outputFileHandle); img_writer->outputFileHandle = 0; /* TODO: Free the data */ } + if (img_writer->logFileHandle != 0) { + CloseHandle(img_writer->logFileHandle); + img_writer->logFileHandle = 0; + } return TSK_OK; #endif @@ -529,16 +588,48 @@ TSK_RETVAL_ENUM writeDynamicDiskHeader(TSK_IMG_WRITER * writer) { * Create and initailize the TSK_IMG_WRITER struct and save reference in img_info, * then write the headers to the output file */ -TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR * directory, - const TSK_TCHAR * basename) { +TSK_RETVAL_ENUM tsk_img_writer_create_from_dir(TSK_IMG_INFO * img_info, const TSK_TCHAR * directory, + const TSK_TCHAR * basename) { #ifndef TSK_WIN32 - return TSK_ERR; + return TSK_ERR; +#else + if (tsk_verbose) { + tsk_fprintf(stderr, + "tsk_img_writer_create: Creating image writer in directory %" PRIttocTSK" with basename %" PRIttocTSK"\n", + directory, basename); + fflush(stderr); + } + + /* Set up the output file */ + size_t len = TSTRLEN(directory) + TSTRLEN(basename) + 10; + TSK_TCHAR * outputFileName = (TSK_TCHAR *)malloc(len * sizeof(TSK_TCHAR)); + TSTRNCPY(outputFileName, directory, TSTRLEN(directory) + 1); + TSTRNCAT(outputFileName, _TSK_T("\\"), 2); + TSTRNCAT(outputFileName, basename, TSTRLEN(basename) + 1); + TSTRNCAT(outputFileName, _TSK_T(".vhd"), 5); + if (tsk_verbose) { + tsk_fprintf(stderr, + "tsk_img_writer_create: Output file: %" PRIttocTSK"\n", outputFileName); + fflush(stderr); + } + + return tsk_img_writer_create(img_info, outputFileName); +#endif +} + +/* +* Create and initailize the TSK_IMG_WRITER struct and save reference in img_info, +* then write the headers to the output file +*/ +TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR * outputFileName) { +#ifndef TSK_WIN32 + return TSK_ERR; #else if (tsk_verbose) { tsk_fprintf(stderr, - "tsk_img_writer_create: Creating image writer in directory %" PRIttocTSK" with basename %" PRIttocTSK"\n", - directory, basename); + "tsk_img_writer_create: Creating image writer in %" PRIttocTSK"\n", + outputFileName); fflush(stderr); } @@ -559,6 +650,9 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR * writer->close = tsk_img_writer_close; writer->finish_image = tsk_img_writer_finish_image; + writer->fileName = (TSK_TCHAR*)tsk_malloc((TSTRLEN(outputFileName) + 1) * sizeof(TCHAR)); + TSTRNCPY(writer->fileName, outputFileName, TSTRLEN(outputFileName) + 1); + /* Calculation time */ writer->imageSize = raw_info->img_info.size; if (writer->imageSize > VHD_MAX_IMAGE_SIZE) { @@ -579,19 +673,6 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR * writer->sectorBitmapLength += VHD_SECTOR_SIZE - (writer->sectorBitmapLength % VHD_SECTOR_SIZE); } - /* Set up the output file */ - size_t len = TSTRLEN(directory) + TSTRLEN(basename) + 10; - writer->fileName = (TSK_TCHAR *)malloc(len * sizeof(TSK_TCHAR)); - TSTRNCPY(writer->fileName, directory, TSTRLEN(directory) + 1); - TSTRNCAT(writer->fileName, _TSK_T("\\"), 2); - TSTRNCAT(writer->fileName, basename, TSTRLEN(basename) + 1); - TSTRNCAT(writer->fileName, _TSK_T(".vhd"), 5); - if (tsk_verbose) { - tsk_fprintf(stderr, - "tsk_img_writer_create: Output file: %" PRIttocTSK"\n", writer->fileName); - fflush(stderr); - } - /* TODO: Decide what to do if the file already exisits. For now, always overwrite */ writer->outputFileHandle = CreateFile(writer->fileName, FILE_WRITE_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, diff --git a/tsk/img/img_writer.h b/tsk/img/img_writer.h index fe6d6287e6e419c762683184f6ff7c4b9900ff6e..e421e020ce1eb3ed7580c8192fd4053d028ba024 100644 --- a/tsk/img/img_writer.h +++ b/tsk/img/img_writer.h @@ -20,8 +20,9 @@ extern "C" { #endif - TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO* img_info, const TSK_TCHAR * directory, + TSK_RETVAL_ENUM tsk_img_writer_create_from_dir(TSK_IMG_INFO* img_info, const TSK_TCHAR * directory, const TSK_TCHAR * basename); + TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO* img_info, const TSK_TCHAR * outputPath); enum IMG_WRITER_BLOCK_STATUS_ENUM { IMG_WRITER_BLOCK_STATUS_UNALLOC = 0, @@ -49,6 +50,9 @@ extern "C" { TSK_OFF_T batOffset; TSK_OFF_T nextDataOffset; + // TEMP + HANDLE logFileHandle; + IMG_WRITER_BLOCK_STATUS_ENUM* blockStatus; TSK_OFF_T* blockToOffset; unsigned char ** blockToSectorBitmap;