diff --git a/win32/is_image_supported_lib/IsImageSupportedLib.cpp b/win32/is_image_supported_lib/IsImageSupportedLib.cpp new file mode 100644 index 0000000000..7483743ecd --- /dev/null +++ b/win32/is_image_supported_lib/IsImageSupportedLib.cpp @@ -0,0 +1,111 @@ +/* + ** The Sleuth Kit + ** + ** Brian Carrier [carrier sleuthkit [dot] org] + ** Copyright (c) 2024 Sleuth Kit Labs, LLC. All Rights reserved + ** Copyright (c) 2010-2021 Brian Carrier. All Rights reserved + ** + ** This software is distributed under the Common Public License 1.0 + */ + +// Library to check if an image can be opened by TSK +#include "pch.h" +#include "IsImageSupportedLib.h" + +#include "tsk/auto/tsk_is_image_supported.h" +#include "tsk/tsk_tools_i.h" +#include "tsk/fs/apfs_fs.h" +#include + + +/** +* Try to open an image. Use the password if supplied. +* +* @param path Path to the image +* @param password Password. May be null. +* +* @return On success: Empty string + On failure: Non-empty string containing the reason image opening failed if the tests were completed + Null pointer if tests could not be run (memory allocation or path conversion issues) + If return value is non-null it must be freed by the caller +*/ +char* isImageSupported(const char* path, const char* password) { + TskIsImageSupported tskIsImage; + if (password != NULL) { + std::string passwordStr(password); + if (!passwordStr.empty()) { + tskIsImage.setFileSystemPassword(password); + } + } + + TSK_TCHAR* imagePathT = NULL; +#ifdef TSK_WIN32 + // If we're on Windows, TSK_TCHAR is a wchar so we need to convert the path + size_t pathLen = strlen(path); + imagePathT = (TSK_TCHAR*)tsk_malloc((pathLen + 1) * sizeof(TSK_TCHAR)); + if (imagePathT == nullptr) { + return nullptr; + } + + UTF8* utf8 = (UTF8*)path; + UTF16* utf16 = (UTF16*)imagePathT; + int ret = tsk_UTF8toUTF16((const UTF8**)&utf8, &utf8[pathLen], + &utf16, &utf16[pathLen], TSKlenientConversion); + if (ret != TSKconversionOK) { + free(imagePathT); + return nullptr; + } +#else + // If we're not on Windows then TSK_TCHAR is just char and we don't need to convert + imagePathT = path; +#endif + + TSK_TCHAR** imagePaths = (TSK_TCHAR**)tsk_malloc((1) * sizeof(TSK_TCHAR*)); + imagePaths[0] = imagePathT; + std::string resultStr = ""; + if (tskIsImage.openImage(1, imagePaths, TSK_IMG_TYPE_DETECT, 0)) { + resultStr = "Error opening image"; + } + else { + tskIsImage.findFilesInImg(); + resultStr = tskIsImage.getMessageForIsImageSupportedNat(); + } + + // Cleanup + tskIsImage.closeImage(); + free(imagePaths); +#ifdef TSK_WIN32 + if (imagePathT != nullptr) { + free(imagePathT); + } +#endif + + // Make a new result string to return to the caller + char* result_cStr = nullptr; + if (resultStr.empty()) { + result_cStr = (char*)malloc(1 * sizeof(char)); + if (result_cStr != nullptr) { + result_cStr[0] = '\0'; + } // We return nullptr on error so we're already good + } + else { + size_t resultLen = resultStr.size(); + result_cStr = (char*)malloc((resultLen + 1) * sizeof(char)); + if (result_cStr != nullptr) { + strncpy_s(result_cStr, resultLen + 1, resultStr.c_str(), resultLen); + }// We return nullptr on error so we're already good + } + + return result_cStr; +} + +/** +* Free a string. Intended to be used to free the result of isImageSupported(); +* +* @param str The string to free +*/ +void freeString(char* str) { + if (str != NULL) { + free(str); + } +} \ No newline at end of file diff --git a/win32/is_image_supported_lib/IsImageSupportedLib.h b/win32/is_image_supported_lib/IsImageSupportedLib.h new file mode 100644 index 0000000000..b412a04afc --- /dev/null +++ b/win32/is_image_supported_lib/IsImageSupportedLib.h @@ -0,0 +1,19 @@ +/* + ** The Sleuth Kit + ** + ** Brian Carrier [carrier sleuthkit [dot] org] + ** Copyright (c) 2024 Sleuth Kit Labs, LLC. All Rights reserved + ** Copyright (c) 2010-2021 Brian Carrier. All Rights reserved + ** + ** This software is distributed under the Common Public License 1.0 + */ +#pragma once + +#ifdef ISIMAGESUPPORTEDLIB_EXPORTS +#define ISIMAGESUPPORTEDLIB_API __declspec(dllexport) +#else +#define ISIMAGESUPPORTEDLIB_API __declspec(dllimport) +#endif + +extern "C" ISIMAGESUPPORTEDLIB_API char* isImageSupported(const char* path, const char* password); +extern "C" ISIMAGESUPPORTEDLIB_API void freeString(char* str); \ No newline at end of file diff --git a/win32/is_image_supported_lib/dllmain.cpp b/win32/is_image_supported_lib/dllmain.cpp new file mode 100644 index 0000000000..f2665971ac --- /dev/null +++ b/win32/is_image_supported_lib/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/win32/is_image_supported_lib/framework.h b/win32/is_image_supported_lib/framework.h new file mode 100644 index 0000000000..54b83e94fd --- /dev/null +++ b/win32/is_image_supported_lib/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/win32/is_image_supported_lib/is_image_supported_lib.vcxproj b/win32/is_image_supported_lib/is_image_supported_lib.vcxproj new file mode 100644 index 0000000000..7206b43841 --- /dev/null +++ b/win32/is_image_supported_lib/is_image_supported_lib.vcxproj @@ -0,0 +1,193 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {6666e9a0-2a86-426c-a17e-a6fb9352009d} + isimagesupportedlib + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + $(ProjectDir)\..\..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;ISIMAGESUPPORTEDLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + libvhdi.lib;libvmdk.lib;libewf.lib;zlib.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(TskNugetLibs);%(AdditionalLibraryDirectories) + Windows + true + false + + + + + + Level3 + true + true + true + $(ProjectDir)\..\..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;ISIMAGESUPPORTEDLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + libvhdi.lib;libvmdk.lib;libewf.lib;zlib.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(TskNugetLibs);%(AdditionalLibraryDirectories) + Windows + true + true + true + false + + + + + Level3 + true + $(ProjectDir)\..\..\;%(AdditionalIncludeDirectories) + _DEBUG;ISIMAGESUPPORTEDLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + libvhdi.lib;libvmdk.lib;libewf.lib;zlib.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(TskNugetLibs);%(AdditionalLibraryDirectories) + Windows + true + false + + + + + Level3 + true + true + true + $(ProjectDir)\..\..\;%(AdditionalIncludeDirectories) + NDEBUG;ISIMAGESUPPORTEDLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + libvhdi.lib;libvmdk.lib;libewf.lib;zlib.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(TskNugetLibs);%(AdditionalLibraryDirectories) + Windows + true + true + true + false + + + + + + + + + + + + Create + Create + Create + Create + + + + + {76efc06c-1f64-4478-abe8-79832716b393} + false + + + + + + + + + \ No newline at end of file diff --git a/win32/is_image_supported_lib/is_image_supported_lib.vcxproj.filters b/win32/is_image_supported_lib/is_image_supported_lib.vcxproj.filters new file mode 100644 index 0000000000..df2771f1e4 --- /dev/null +++ b/win32/is_image_supported_lib/is_image_supported_lib.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/win32/is_image_supported_lib/pch.cpp b/win32/is_image_supported_lib/pch.cpp new file mode 100644 index 0000000000..64b7eef6d6 --- /dev/null +++ b/win32/is_image_supported_lib/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/win32/is_image_supported_lib/pch.h b/win32/is_image_supported_lib/pch.h new file mode 100644 index 0000000000..885d5d62e4 --- /dev/null +++ b/win32/is_image_supported_lib/pch.h @@ -0,0 +1,13 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#include "framework.h" + +#endif //PCH_H diff --git a/win32/tsk-win.sln b/win32/tsk-win.sln index c68eab1d53..863e9e6bca 100644 --- a/win32/tsk-win.sln +++ b/win32/tsk-win.sln @@ -161,6 +161,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pstat", "pstat\pstat.vcxpro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tsk_imageinfo", "tsk_imageinfo\tsk_imageinfo.vcxproj", "{09E82DEB-4BC3-44B5-A9F6-4D65F885F88C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "is_image_supported_lib", "is_image_supported_lib\is_image_supported_lib.vcxproj", "{6666E9A0-2A86-426C-A17E-A6FB9352009D}" + ProjectSection(ProjectDependencies) = postProject + {76EFC06C-1F64-4478-ABE8-79832716B393} = {76EFC06C-1F64-4478-ABE8-79832716B393} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_NoLibs|Win32 = Debug_NoLibs|Win32 @@ -853,6 +858,20 @@ Global {09E82DEB-4BC3-44B5-A9F6-4D65F885F88C}.Release|Win32.Build.0 = Release|Win32 {09E82DEB-4BC3-44B5-A9F6-4D65F885F88C}.Release|x64.ActiveCfg = Release|x64 {09E82DEB-4BC3-44B5-A9F6-4D65F885F88C}.Release|x64.Build.0 = Release|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug_NoLibs|Win32.ActiveCfg = Debug|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug_NoLibs|x64.ActiveCfg = Debug|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug|Win32.ActiveCfg = Debug|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug|Win32.Build.0 = Debug|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug|x64.ActiveCfg = Debug|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Debug|x64.Build.0 = Debug|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release_NoLibs|Win32.ActiveCfg = Release|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release_NoLibs|x64.ActiveCfg = Release|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release_XPNoLibs|Win32.ActiveCfg = Release|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release_XPNoLibs|x64.ActiveCfg = Release|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release|Win32.ActiveCfg = Release|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release|Win32.Build.0 = Release|Win32 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release|x64.ActiveCfg = Release|x64 + {6666E9A0-2A86-426C-A17E-A6FB9352009D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE