diff --git a/docs/doxygen/modDevPython.dox b/docs/doxygen/modDevPython.dox index 6026a4b6edf9c824628bdba95c652a990d88e954..9b1b74501f29147b1c78c5e7853da5af8d3c123f 100755 --- a/docs/doxygen/modDevPython.dox +++ b/docs/doxygen/modDevPython.dox @@ -4,9 +4,9 @@ any type of module. Information about specific types of modules should go into the page for that module type. --> -This page describes the basic concepts and setup that are needed for all types of Python modules. It is not needed for Java module development. +This page describes the basic concepts and setup that are needed for all types of Python modules. It is not needed if you are doing only Java module development. -Autopsy uses Jython (http://www.jython.org) to enable Python scripting. Jython looks like Python and gets converted into Java byte code and run on the JVM. Its biggest limitations are: +Autopsy uses Jython (http://www.jython.org) to enable Python scripting. Jython looks like Python and gets converted into Java byte code and runs on the JVM. Its biggest limitations are: - Limited to Python 2.7 (as of Autopsy 3.1.3) - Can't use Python libraries that have native code - You can't easily make UIs. This means that you can't make content viewer modules or easily have configuration settings for your ingest modules. We have done it, but it is tedious compared to using a Java tool to place UI widgets in various places. @@ -17,38 +17,41 @@ To develop a module, you should follow this section to get your environment setu There are also a set of tutorials that Basis Technology published on their blog: -* The File Ingest Module: http://www.basistech.com/python-autopsy-module-tutorial-1-the-file-ingest-module/ +* File Ingest Modules: http://www.basistech.com/python-autopsy-module-tutorial-1-the-file-ingest-module/ +* Data Source Ingest Modules: http://www.basistech.com/python-autopsy-module-tutorial-2-the-data-source-ingest-module/ \section mod_dev_py_setup Basic Setup -You don't really need anything to develop a python Autopsy module except for the standard Autopsy and your favorite text editor. - +You don't really need anything to develop a python Autopsy module except for the standard Autopsy and your favorite text editor. We recommend pyCharm or the Python plug-in to NetBeans. \section mod_dev_py_create Creating a Basic Python Module \subsection mod_dev_py_create_dir Packaging Structure -Autopsy requires that you have a self-contained folder for each Python module. This prevents naming collisions with other modules. You can name the folder what ever you want. You'll need to put all of the libraries that you depend on in there too. +Autopsy requires that you put all of your Python modules into a single folder. This prevents naming collisions with other modules. You can name the folder what ever you want. You'll need to put all of the libraries that you depend on in there too. -You will need to copy this folder into Autopsy's Python script folder. It will scan this folder each time it looks for modules. You can find the location of this folder from the "Tools -> Python Scripts" menu item. +You will need to copy this folder into Autopsy's Python script folder. Autopsy will scan this folder each time it looks for modules. You can find the location of this folder from the "Tools -> Python Scripts" menu item. \subsection mod_dev_py_create_create Module Creation --# Create a folder --# Copy one of the sample modules from the github repository (listed below) or make one from scratch --# Copy the folder to the previously mentioned folder to make updates during development. +We have a growing number of sample Python scripts and therefore the easiest starting point for any Python script is probably to start with one of the public domain examples. This approach is a bit different than what you'd find with Java because the Java environment auto-creates the modules more. + +This is the basic approach: + +-# Create a folder referenced in \ref mod_dev_py_create_dir. +-# Copy one of the sample modules from the github repository (https://github.com/sleuthkit/autopsy/tree/develop/pythonExamples) +-# Edit the sample module by looking for "TODO" references. That's it. Autopsy will find the module each time it needs it and you can make updates without having to restart Autopsy each time. -While it may be tempting to use the Python Scripts folder as a development folder, be warned that if you do a 'Clean' from the Java development environment (NetBeans), you could lose your script. If do not have NetBeans installed for Autopsy development, then you could be fine because you won't be able to do a 'Clean'. \subsection mod_dev_py_library Using External Libraries -If you need to bring in a library that is not part of the standard jython distribution, then do the following: +If you need to bring in a library that is not part of the standard Jython distribution, then do the following: --# Copy the library file or folder into the folder that you made in the previous section. For example, you may copy in folder called 'neededLib' that has a file named mylib.py in it. The end result be a folder structure such as myModuleFolder/neededLib/mylib.py. +-# Copy the library file or folder into the folder that you made in \ref mod_dev_py. For example, you may copy in folder called 'neededLib' that has a file named mylib.py in it. The end result be a folder structure such as myModuleFolder/neededLib/mylib.py. -# In your Python code, if you needed a class from mylib, then you'd have a line such as: \code{.py} from neededLib.mylib import neededClass @@ -56,6 +59,8 @@ from neededLib.mylib import neededClass Jython will look in the module's folder to resolve these libraries. +If you bring in a library that uses native code, then you will get a runtime error when you try to load it. + \subsection mod_dev_py_misc Minor Gotchas This section lists some helpful tips that we have found. These are all now in the sample modules, so refer to those for examples and a place to copy and paste from. @@ -63,18 +68,10 @@ This section lists some helpful tips that we have found. These are all now in t - When you name the file with your Python module in it, restrict its name to letters, numbers, and underscore (_). - Python modules using external libraries which load native code (SciPy, NumPy, etc.) are currently NOT supported. RuntimeError will be thrown. + \section mod_dev_py_distribute Distribution To distribute and share your Python module, ZIP up the folder and send it around. Other users of the module should expand the ZIP file and drop the folder into their Autopsy Python folder. -\section mod_dev_py_dev Developing Modules - -Jython allows you to access all of the Java classes. So, you should read the following sections of this document. All you should ignore is the Java environment setup sections. - -There are only two types of modules that you can make with Python. Those (along with a sample file) are listed below: -- Ingest Modules (both file-level and data source-level): https://github.com/sleuthkit/autopsy/blob/develop/pythonExamples/ -- Report Modules: https://github.com/sleuthkit/autopsy/blob/develop/pythonExamples/reportmodule.py - - */ diff --git a/docs/doxygen/platformConcepts.dox b/docs/doxygen/platformConcepts.dox index f76ea35f665abe5cb479577f1439c4e494013d13..64ea249fea8cb0401170edb50079fbaee9951e4a 100755 --- a/docs/doxygen/platformConcepts.dox +++ b/docs/doxygen/platformConcepts.dox @@ -1,41 +1,49 @@ /*! \page platform_page Module Development Overview -This page covers the basics of Autopsy, including the types of modules and the basic services that are provided. Other pages will cover development environment setup and how to build specific types of modules. This page applies to both Java and Python modules. + +This page covers the motivation for and basics of Autopsy modules. It applies to both Java and Python modules. Later pages will focus on getting the devevelopment environment setup and how to write specific modules. + +\section platform_motivation Why Write Modules? + +When writing digital forensics programs, the developer often has to focus on three areas: +- What types of data will the user be giving you (disk image, logical files, etc.). +- How to do the analysis that you want to do. +- How to show the results to the user and include the results into a report. + +The main reason for considering writing an Autopsy module instead of a stand-alone tool is that Autopsy will deal with the various data inputs and showing the user the results. All you need to do is focus on the analytics. \section platform_frameworks Types of Modules Autopsy was designed to be an extensible platform for other developers to leverage. There are several places in the platform where plug-in modules can be applied. - <b>Ingest Modules:</b> These modules are run when a new data source (such as a disk image) is added to a case (and can be re-run afterwards too). These modules come in two forms: - File Ingest Modules are called for every file in the data source. Use this type of module if you want to examine the contents of all or most of the files. Examples include hash calculation, hash lookup, file type identification, and entropy calculation. These modules are passed in a reference to a file to analyze. - - Data Source Ingest Modules are called once for every image or set of logical files. These modules can use the database to query for one or more files and perform analysis on them. Examples include web artifact analysis and searches that can rely only file names and extensions. Note that these modules will not have access to the contents of ZIP files. + - Data Source Ingest Modules are called once for every image or set of logical files. These modules can use the database to query for one or more files and perform analysis on them. Examples include web artifact analysis and searches that can rely only file names and extensions. Note that these modules will not have access to the contents of ZIP files. These modules are also often used when wrapping an executabe that takes a disk image in as input. See \ref mod_ingest_page for details on building these modules. -- <b>Report Modules:</b> These modules create different types of outputs that contain the analysis results. See \ref mod_report_page for details on creating these modules. -- <b>Content Viewers:</b> These graphical modules show information about a specific file. These are the modules in the lower right of the interface. The platform comes with viewers to view the file in hexadecimal, extract the strings from the file, and view images and movies. See \ref mod_content_page for details on creating these modules. -- <b>Result Viewers:</b> These modules show information about a set of files. These modules are in the upper right of the interface. The platform comes with viewers to view the set of files in a table and thumbnails. See \ref mod_result_page for details on creating these modules. +- <b>Report Modules:</b> These modules are (typically) run after the user has reviewed results and tagged files. Their intention is to create an output report of the results, but they can also be used to perform analysis. See \ref mod_report_page for details on creating these modules. +- <b>Content Viewers:</b> These modules are graphical and focus on displaying a specific file in some unique way. These are the modules in the lower right of the interface. The platform comes with viewers to view the file in hexadecimal, extract the strings from the file, and view images and movies. See \ref mod_content_page for details on creating these modules. +- <b>Result Viewers:</b> These modules show information about a set of files. These modules are in the upper right of the interface. The platform comes with viewers to view the set of files in a table and thumbnails. These are not commonly built and extended. See \ref mod_result_page for details on creating these modules. \section platform_languages Languages -All modules can be written in Java. The \ref mod_dev_page page covers setup of a Java environment. - -Some of the modules can be written in Python, namely ingest an report modules. See \ref mod_dev_py_page for setup details. Python modules have access to all of the same services as Java modules do, except they cannot currently make UI elements. +Autopsy is written in Java and all of previously listed modules can also be written in Java. The \ref mod_dev_page page covers setup of a Java environment. +You can also write some of the modules in Python, namely ingest an report modules. The setup for Python is far easier than Java, so it is the easiest way to get started. See \ref mod_dev_py_page for setup details. Python modules have access to all of the same services as Java modules do, except they cannot currently make UI elements. Therefore, you really should read all of this document (even though it is Java-focused) because it can all be used in Python. \section platform_basics Basic Concepts -These are the basic concepts that you should be aware of before writing any type of module. +Before we focus on the development environment or module details, let's cover some basic Autopsy concepts. -- <b>Data Source</b>: Data source is the term used in Autopsy to refer to disk images and logical files that are added to a case. Data sources are represented in Autopsy using several types of classes from the org.sleuthkit.datamodel package. -- <b>Case</b>: A case is a container for one or more data sources in Autopsy. A case is represented by a org.sleuthkit.autopsy.casemodule.Case class. Only one case can be open at a time. You can get the current case using org.sleuthkit.autopsy.casemodule.Case.getCurrentCase(). +- <b>Data Source</b>: Data source is the term used in Autopsy to refer to disk images and logical files that are added to a case. Data sources are represented in Autopsy using several types of classes from the org.sleuthkit.datamodel package, such as org.sleuthkit.datamodel.Image. +- <b>Case</b>: A case is a container for one or more data sources in Autopsy. A case is represented by a org.sleuthkit.autopsy.casemodule.Case class. Only one case can be open at a time. You can get the current case at any time using org.sleuthkit.autopsy.casemodule.Case.getCurrentCase(). - <b>Central Database</b>: A central SQLite database exists and stores all file metadata and analysis results. Access to this database can be found from the org.sleuthkit.datamodel.SleuthkitCase class, but you'll probably never need to directly interact with it. All modules can query it for information, though many do not need to. For example, file-level ingest modules will be passed in a reference to a specific file to analyze and may never need to directly go to the database for more information. - <b>Blackboard:</b> The blackboard is how modules communicate back and forth. Modules post their results to the blackboard in the form of artifacts and the UI will display them. See the \ref platform_blackboard section for more details. - <b>Services and Utilities</b>: There are a lot of convenience services and utilities that are provided to developers. Refer to the \ref mod_dev_other_services section for more details. - -\section platform_blackboard The Blackboard +\subsection platform_blackboard The Blackboard The blackboard allows modules to communicate with each other and the UI. It has three main uses in Autopsy: - Ingest modules can communicate with each other. For example, one module can calculate a MD5 hash of a file and post it to the blackboard. Then another module can retrieve the hash value from the blackboard and not need to calculate it again. @@ -47,9 +55,9 @@ The blackboard is not unique to Autopsy. It is part of The Sleuth Kit datamodel - \ref mod_bbpage (http://sleuthkit.org/sleuthkit/docs/jni-docs/mod_bbpage.html) -\section mod_dev_other_services Framework Services and Utilities +\subsection mod_dev_other_services Framework Services and Utilities -The following are basic services that are available to any module. They are provided here to be used as a reference. When you are developing your module and feel like something should be provided by the framework, then refer to this list to find out where it could be. If you don't find it, let us know and we'll talk about adding it for other writers to benefit. +Autopsy provides services and utilities to make it easier to write modules. Unfortunately, the utilities and services are scattered in various packages. Below is a list of things commonly used in modules. If you don't find something in here that you think should be a framework service, let us know and we'll talk about adding it for other writers to benefit. - FileManager: the org.sleuthkit.autopsy.casemodule.services.FileManager service provides an API to access any file in the case. You can access FileManager by calling org.sleuthkit.autopsy.casemodule.services.Services.getFileManager(). Data Source-level Ingest modules and Report modules typically use this service. diff --git a/pythonExamples/Aug2015DataSourceTutorial/README.txt b/pythonExamples/Aug2015DataSourceTutorial/README.txt index 3740d9cdfa73ad930ce51c7b2f234e5d95bc3d54..604eaccdbcb6438e32b749138290d7d369cdb31b 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/README.txt +++ b/pythonExamples/Aug2015DataSourceTutorial/README.txt @@ -1,7 +1,10 @@ This folder contains files that were created for an August 2015 Tutorial from Basis Technology. +http://www.basistech.com/python-autopsy-module-tutorial-2-the-data-source-ingest-module/ + + It contains the following: - FindContactsDb.py: Script to find databases and parse them. - Contacts.db: Sample database with the correct name and schema for the FindContactsDb.py script. - RunExe.py: Script that runs img_stat.exe on disk images. -- img_stat.exe: 32-bit version of img_stat.exe from The Sleuth Kit that is needed by RunExe.py. \ No newline at end of file +- img_stat.exe: 32-bit version of img_stat.exe from The Sleuth Kit that is needed by RunExe.py. diff --git a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py new file mode 100755 index 0000000000000000000000000000000000000000..25c1fc1d4b69a1c1149b16a5acdb7e44eb481d60 --- /dev/null +++ b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py @@ -0,0 +1,133 @@ +# Sample module in the public domain. Feel free to use this as a template +# for your modules (and you can remove this header and take complete credit +# and liability) +# +# Contact: Brian Carrier [carrier <at> sleuthkit [dot] org] +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# Simple file-level ingest module for Autopsy. +# Used as part of Python tutorials from Basis Technology - July 2015 +# http://www.basistech.com/python-autopsy-module-tutorial-1-the-file-ingest-module/ +# +# Looks for big files that are a multiple of 4096 and makes artifacts + + +import jarray +import inspect +from java.lang import System +from java.util.logging import Level +from org.sleuthkit.datamodel import SleuthkitCase +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import ReadContentInputStream +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import TskData +from org.sleuthkit.autopsy.ingest import IngestModule +from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException +from org.sleuthkit.autopsy.ingest import DataSourceIngestModule +from org.sleuthkit.autopsy.ingest import FileIngestModule +from org.sleuthkit.autopsy.ingest import IngestModuleFactoryAdapter +from org.sleuthkit.autopsy.ingest import IngestMessage +from org.sleuthkit.autopsy.ingest import IngestServices +from org.sleuthkit.autopsy.ingest import ModuleDataEvent +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Services +from org.sleuthkit.autopsy.casemodule.services import FileManager + +# Factory that defines the name and details of the module and allows Autopsy +# to create instances of the modules that will do the anlaysis. +class FindBigRoundFilesIngestModuleFactory(IngestModuleFactoryAdapter): + + moduleName = "Big and Round File Finder" + + def getModuleDisplayName(self): + return self.moduleName + + def getModuleDescription(self): + return "Sample module that files large files that are a multiple of 4096." + + def getModuleVersionNumber(self): + return "1.0" + + # Return true if module wants to get called for each file + def isFileIngestModuleFactory(self): + return True + + # can return null if isFileIngestModuleFactory returns false + def createFileIngestModule(self, ingestOptions): + return FindBigRoundFilesIngestModule() + + +# File-level ingest module. One gets created per thread. +class FindBigRoundFilesIngestModule(FileIngestModule): + + _logger = Logger.getLogger(FindBigRoundFilesIngestModuleFactory.moduleName) + + def log(self, level, msg): + self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) + + # Where any setup and configuration is done + # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. + # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # TODO: Add any setup code that you need here. + def startUp(self, context): + self.filesFound = 0 + + # Throw an IngestModule.IngestModuleException exception if there was a problem setting up + # raise IngestModuleException("Oh No!") + pass + + # Where the analysis is done. Each file will be passed into here. + # The 'file' object being passed in is of type org.sleuthkit.datamodel.AbstractFile. + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html + def process(self, file): + # Skip non-files + if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or + (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or + (file.isFile() == False)): + return IngestModule.ProcessResult.OK + + # Look for files bigger than 10MB that are a multiple of 4096 + if ((file.getSize() > 10485760) and ((file.getSize() % 4096) == 0)): + + # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of + # artifact. Refer to the developer docs for other examples. + art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) + att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), + FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files") + art.addAttribute(att) + + # Fire an event to notify the UI and others that there is a new artifact + IngestServices.getInstance().fireModuleDataEvent( + ModuleDataEvent(FindBigRoundFilesIngestModuleFactory.moduleName, + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)); + + return IngestModule.ProcessResult.OK + + # Where any shutdown code is run and resources are freed. + # TODO: Add any shutdown code that you need here. + def shutDown(self): + None diff --git a/pythonExamples/July2015FileTutorial_BigRound/README.txt b/pythonExamples/July2015FileTutorial_BigRound/README.txt new file mode 100755 index 0000000000000000000000000000000000000000..34a279b070dfc2b859ad8ac5e32e62781d38c4c4 --- /dev/null +++ b/pythonExamples/July2015FileTutorial_BigRound/README.txt @@ -0,0 +1,6 @@ +This folder contains files that were created for an July 2015 Tutorial from Basis Technology. + +It contains the following: +- FindBigRoundFiles.py: Module to find files that are bigger than 10MB and multiple of 4k +- bigRoundFile.dat: File that should be found if added as logical file and module is run on it +- nonRoundfile.dat: File that should not be flagged if added as logical file and module is run on it. diff --git a/pythonExamples/July2015FileTutorial_BigRound/bigRoundFile.dat b/pythonExamples/July2015FileTutorial_BigRound/bigRoundFile.dat new file mode 100644 index 0000000000000000000000000000000000000000..15ae5f2c4c4ce02a5f5ae4d2b5f76b6045080659 Binary files /dev/null and b/pythonExamples/July2015FileTutorial_BigRound/bigRoundFile.dat differ diff --git a/pythonExamples/July2015FileTutorial_BigRound/notRoundFile.dat b/pythonExamples/July2015FileTutorial_BigRound/notRoundFile.dat new file mode 100644 index 0000000000000000000000000000000000000000..cbed23ee1fde238313b34621d8bc43f2a8019693 Binary files /dev/null and b/pythonExamples/July2015FileTutorial_BigRound/notRoundFile.dat differ diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 802a2fb6198727874a2071c5b363303cfe4a9a5c..d335c6889c13f74cf995d8f5ddc3ea2da904cf5d 100755 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -114,6 +114,7 @@ def process(self, dataSource, progressBar): # For our example, we will use FileManager to get all # files with the word "test" # in the name and then count and read them + # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%test%") diff --git a/pythonExamples/reportmodule.py b/pythonExamples/reportmodule.py index 3dce311a7cd5b7864e096c62be6e92003cd9f04f..759602bdb6ee2d20c2c150c21a2e0ad9b808a576 100755 --- a/pythonExamples/reportmodule.py +++ b/pythonExamples/reportmodule.py @@ -28,24 +28,37 @@ # OTHER DEALINGS IN THE SOFTWARE. -# Report module for Autopsy. +# Sample report module for Autopsy. Use as a starting point for new modules. # # Search for TODO for the things that you need to change # See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +import os from java.lang import System +from java.util.logging import Level from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.report import GeneralReportModuleAdapter -import os +from org.sleuthkit.autopsy.report.ReportProgressPanel import ReportStatus -# TODO: Rename this to something more specific + +# TODO: Rename the class to something more specific class SampleGeneralReportModule(GeneralReportModuleAdapter): # TODO: Rename this. Will be shown to users when making a report + moduleName = "Sample Report Module" + + _logger = None + def log(self, level, msg): + if _logger == None: + _logger = Logger.getLogger(self.moduleName) + + self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) + def getName(self): - return "Sample Jython Report Module" + return self.moduleName - # TODO: rewrite this + # TODO: Give it a useful description def getDescription(self): return "A sample Jython report module" @@ -54,30 +67,43 @@ def getRelativeFilePath(self): return "sampleReport.txt" # TODO: Update this method to make a report + # The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath(). + # The 'progressBar' object is of type ReportProgressPanel. + # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, baseReportDir, progressBar): - # For an example, we write a file with the number of files created in the past 2 weeks - # Configure progress bar for 2 tasks - progressBar.setIndeterminate(False) - progressBar.start() - progressBar.setMaximumProgress(2) - - # Get files by created in last two weeks. - fileCount = 0 - autopsyCase = Case.getCurrentCase() - sleuthkitCase = autopsyCase.getSleuthkitCase() - currentTime = System.currentTimeMillis() / 1000 - minTime = currentTime - (14 * 24 * 60 * 60) - otherFiles = sleuthkitCase.findFilesWhere("crtime > %d" % minTime) - for otherFile in otherFiles: - fileCount += 1 - progressBar.increment() - - # Write the result to the report file. - report = open(os.path.join(baseReportDir, self.getRelativeFilePath()), 'w') - report.write("file count = %d" % fileCount) - Case.getCurrentCase().addReport(report.name, "SampleGeneralReportModule", "Sample Python Report"); - report.close() - - progressBar.increment() - progressBar.complete() + # For an example, we write a file with the number of files created in the past 2 weeks + # Configure progress bar for 2 tasks + progressBar.setIndeterminate(False) + progressBar.start() + progressBar.setMaximumProgress(2) + + # Find epoch time of when 2 weeks ago was + currentTime = System.currentTimeMillis() / 1000 + minTime = currentTime - (14 * 24 * 60 * 60) # (days * hours * minutes * seconds) + + # Query the database for files that meet our criteria + sleuthkitCase = Case.getCurrentCase().getSleuthkitCase() + files = sleuthkitCase.findAllFilesWhere("crtime > %d" % minTime) + + fileCount = 0 + for file in files: + fileCount += 1 + # Could do something else here and write it to HTML, CSV, etc. + + # Increment since we are done with step #1 + progressBar.increment() + + # Write the count to the report file. + fileName = os.path.join(baseReportDir, self.getRelativeFilePath()) + report = open(fileName, 'w') + report.write("file count = %d" % fileCount) + report.close() + + # Add the report to the Case, so it is shown in the tree + Case.getCurrentCase().addReport(fileName, self.moduleName, "File Count Report"); + + progressBar.increment() + + # Call this with ERROR if report was not generated + progressBar.complete(ReportStatus.COMPLETE) \ No newline at end of file