mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #6478 from markmckinnon/6965-Complete-aLeapp-Module
6965 complete a leapp module
This commit is contained in:
commit
071dadd475
@ -54,6 +54,11 @@
|
|||||||
<fileset dir="${thirdparty.dir}/iLeapp"/>
|
<fileset dir="${thirdparty.dir}/iLeapp"/>
|
||||||
</copy>
|
</copy>
|
||||||
|
|
||||||
|
<!--Copy aLeapp to release-->
|
||||||
|
<copy todir="${basedir}/release/aLeapp" >
|
||||||
|
<fileset dir="${thirdparty.dir}/aLeapp"/>
|
||||||
|
</copy>
|
||||||
|
|
||||||
<!--Copy 7-Zip to release-->
|
<!--Copy 7-Zip to release-->
|
||||||
<copy todir="${basedir}/release/7-Zip" >
|
<copy todir="${basedir}/release/7-Zip" >
|
||||||
<fileset dir="${thirdparty.dir}/7-Zip"/>
|
<fileset dir="${thirdparty.dir}/7-Zip"/>
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
|
||||||
ILeappAnalyzerIngestModule.processing.file=Processing file {0}
|
|
||||||
ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
|
||||||
ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
|
@ -1,30 +0,0 @@
|
|||||||
ILeappAnalyzerIngestModule.completed=iLeapp Processing Completed
|
|
||||||
ILeappAnalyzerIngestModule.error.creating.output.dir=Error creating iLeapp module output directory.
|
|
||||||
ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize ILeappProcessFile
|
|
||||||
ILeappAnalyzerIngestModule.error.running.iLeapp=Error running iLeapp, see log file.
|
|
||||||
ILeappAnalyzerIngestModule.executable.not.found=iLeapp Executable Not Found.
|
|
||||||
ILeappAnalyzerIngestModule.has.run=iLeapp
|
|
||||||
ILeappAnalyzerIngestModule.iLeapp.cancelled=iLeapp run was canceled
|
|
||||||
ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
|
||||||
ILeappAnalyzerIngestModule.processing.file=Processing file {0}
|
|
||||||
ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
|
||||||
ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
|
||||||
ILeappAnalyzerIngestModule.report.name=iLeapp Html Report
|
|
||||||
ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
|
|
||||||
ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
|
|
||||||
ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
|
|
||||||
ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices.
|
|
||||||
ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)
|
|
||||||
ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
|
|
||||||
ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
|
|
||||||
ILeappFileProcessor.completed=iLeapp Processing Completed
|
|
||||||
ILeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts.
|
|
||||||
ILeappFileProcessor.error.creating.output.dir=Error creating iLeapp module output directory.
|
|
||||||
ILeappFileProcessor.error.reading.iLeapp.directory=Error reading iLeapp Output Directory
|
|
||||||
ILeappFileProcessor.error.running.iLeapp=Error running iLeapp, see log file.
|
|
||||||
ILeappFileProcessor.has.run=iLeapp
|
|
||||||
ILeappFileProcessor.iLeapp.cancelled=iLeapp run was canceled
|
|
||||||
ILeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact
|
|
||||||
ILeappFileProcessor.running.iLeapp=Running iLeapp
|
|
||||||
ILeappFileProcessor.starting.iLeapp=Starting iLeapp
|
|
||||||
ILeappFileProcessor_cannotParseXml=Cannot Parse XML file.
|
|
@ -0,0 +1,492 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.modules.leappanalyzers;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.openide.modules.InstalledFileLocator;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import static org.sleuthkit.autopsy.casemodule.Case.getCurrentCase;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ExecUtil;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||||
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
|
||||||
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.LocalFilesDataSource;
|
||||||
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data source ingest module that runs aLeapp against logical iOS files.
|
||||||
|
*/
|
||||||
|
public class ALeappAnalyzerIngestModule implements DataSourceIngestModule {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ALeappAnalyzerIngestModule.class.getName());
|
||||||
|
private static final String MODULE_NAME = ALeappAnalyzerModuleFactory.getModuleName();
|
||||||
|
|
||||||
|
private static final String ALEAPP = "aLeapp"; //NON-NLS
|
||||||
|
private static final String ALEAPP_FS = "fs_"; //NON-NLS
|
||||||
|
private static final String ALEAPP_EXECUTABLE = "aleapp.exe";//NON-NLS
|
||||||
|
private static final String ALEAPP_PATHS_FILE = "aLeapp_paths.txt"; //NON-NLS
|
||||||
|
|
||||||
|
private static final String XMLFILE = "aleap-artifact-attribute-reference.xml"; //NON-NLS
|
||||||
|
|
||||||
|
|
||||||
|
private File aLeappExecutable;
|
||||||
|
|
||||||
|
private IngestJobContext context;
|
||||||
|
|
||||||
|
private LeappFileProcessor aLeappFileProcessor;
|
||||||
|
|
||||||
|
ALeappAnalyzerIngestModule() {
|
||||||
|
// This constructor is intentionally empty. Nothing special is needed here.
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.",
|
||||||
|
"ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.",
|
||||||
|
"ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile"})
|
||||||
|
@Override
|
||||||
|
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
if (false == PlatformUtil.isWindowsOS()) {
|
||||||
|
throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_requires_windows());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
aLeappFileProcessor = new LeappFileProcessor(XMLFILE);
|
||||||
|
} catch (IOException | IngestModuleException | NoCurrentCaseException ex) {
|
||||||
|
throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
aLeappExecutable = locateExecutable(ALEAPP_EXECUTABLE);
|
||||||
|
} catch (FileNotFoundException exception) {
|
||||||
|
logger.log(Level.WARNING, "aLeapp executable not found.", exception); //NON-NLS
|
||||||
|
throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_executable_not_found(), exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.",
|
||||||
|
"ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.",
|
||||||
|
"ALeappAnalyzerIngestModule.starting.aLeapp=Starting aLeapp",
|
||||||
|
"ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp",
|
||||||
|
"ALeappAnalyzerIngestModule.has.run=aLeapp",
|
||||||
|
"ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled",
|
||||||
|
"ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed",
|
||||||
|
"ALeappAnalyzerIngestModule.report.name=aLeapp Html Report"})
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
|
||||||
|
|
||||||
|
Case currentCase = Case.getCurrentCase();
|
||||||
|
Path tempOutputPath = Paths.get(currentCase.getTempDirectory(), ALEAPP, ALEAPP_FS + dataSource.getId());
|
||||||
|
try {
|
||||||
|
Files.createDirectories(tempOutputPath);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", tempOutputPath.toString()), ex);
|
||||||
|
return ProcessResult.ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> aLeappPathsToProcess = new ArrayList<>();
|
||||||
|
ProcessBuilder aLeappCommand = buildaLeappListCommand(tempOutputPath);
|
||||||
|
try {
|
||||||
|
int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
|
||||||
|
if (result != 0) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
|
||||||
|
return ProcessResult.ERROR;
|
||||||
|
}
|
||||||
|
aLeappPathsToProcess = loadIleappPathFile(tempOutputPath);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program getting file paths to search"), ex);
|
||||||
|
return ProcessResult.ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusHelper.progress(Bundle.ALeappAnalyzerIngestModule_starting_aLeapp(), 0);
|
||||||
|
|
||||||
|
List<AbstractFile> aLeappFilesToProcess = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!(context.getDataSource() instanceof LocalFilesDataSource)) {
|
||||||
|
extractFilesFromImage(dataSource, aLeappPathsToProcess, tempOutputPath);
|
||||||
|
statusHelper.switchToDeterminate(aLeappFilesToProcess.size());
|
||||||
|
processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
|
||||||
|
} else {
|
||||||
|
aLeappFilesToProcess = findaLeappFilesToProcess(dataSource);
|
||||||
|
statusHelper.switchToDeterminate(aLeappFilesToProcess.size());
|
||||||
|
|
||||||
|
Integer filesProcessedCount = 0;
|
||||||
|
for (AbstractFile aLeappFile : aLeappFilesToProcess) {
|
||||||
|
processALeappFile(dataSource, currentCase, statusHelper, filesProcessedCount, aLeappFile);
|
||||||
|
filesProcessedCount++;
|
||||||
|
}
|
||||||
|
// Process the logical image as a fs in aLeapp to make sure this is not a logical fs that was added
|
||||||
|
extractFilesFromImage(dataSource, aLeappPathsToProcess, tempOutputPath);
|
||||||
|
processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
IngestMessage message = IngestMessage.createMessage(IngestMessage.MessageType.DATA,
|
||||||
|
Bundle.ALeappAnalyzerIngestModule_has_run(),
|
||||||
|
Bundle.ALeappAnalyzerIngestModule_completed());
|
||||||
|
IngestServices.getInstance().postMessage(message);
|
||||||
|
return ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a file from a logical image using the aLeapp program
|
||||||
|
* @param dataSource datasource to process
|
||||||
|
* @param currentCase current case that is being worked on
|
||||||
|
* @param statusHelper show progress and update what is being processed
|
||||||
|
* @param filesProcessedCount number of files that have been processed
|
||||||
|
* @param aLeappFile the abstract file to process
|
||||||
|
*/
|
||||||
|
private void processALeappFile(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, int filesProcessedCount,
|
||||||
|
AbstractFile aLeappFile) {
|
||||||
|
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());//NON-NLS
|
||||||
|
Path moduleOutputPath = Paths.get(currentCase.getModuleDirectory(), ALEAPP, currentTime);
|
||||||
|
try {
|
||||||
|
Files.createDirectories(moduleOutputPath);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusHelper.progress(NbBundle.getMessage(this.getClass(), "ALeappAnalyzerIngestModule.processing.file", aLeappFile.getName()), filesProcessedCount);
|
||||||
|
ProcessBuilder aLeappCommand = buildaLeappCommand(moduleOutputPath, aLeappFile.getLocalAbsPath(), aLeappFile.getNameExtension());
|
||||||
|
try {
|
||||||
|
int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
|
||||||
|
if (result != 0) {
|
||||||
|
logger.log(Level.WARNING, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addILeappReportToReports(moduleOutputPath, currentCase);
|
||||||
|
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file %s", aLeappFile.getLocalAbsPath()), ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.dataSourceIngestIsCancelled()) {
|
||||||
|
logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessResult fileProcessorResult = aLeappFileProcessor.processFiles(dataSource, moduleOutputPath, aLeappFile);
|
||||||
|
|
||||||
|
if (fileProcessorResult == ProcessResult.ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a image/directory using the aLeapp program
|
||||||
|
* @param dataSource datasource to process
|
||||||
|
* @param currentCase current case being procesed
|
||||||
|
* @param statusHelper show progress and update what is being processed
|
||||||
|
* @param directoryToProcess directory to run aLeapp against
|
||||||
|
*/
|
||||||
|
private void processALeappFs(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, String directoryToProcess) {
|
||||||
|
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());//NON-NLS
|
||||||
|
Path moduleOutputPath = Paths.get(currentCase.getModuleDirectory(), ALEAPP, currentTime);
|
||||||
|
try {
|
||||||
|
Files.createDirectories(moduleOutputPath);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusHelper.progress(NbBundle.getMessage(this.getClass(), "ALeappAnalyzerIngestModule.processing.filesystem"));
|
||||||
|
ProcessBuilder aLeappCommand = buildaLeappCommand(moduleOutputPath, directoryToProcess, "fs");
|
||||||
|
try {
|
||||||
|
int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
|
||||||
|
if (result != 0) {
|
||||||
|
logger.log(Level.WARNING, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addILeappReportToReports(moduleOutputPath, currentCase);
|
||||||
|
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file system"), ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.dataSourceIngestIsCancelled()) {
|
||||||
|
logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessResult fileProcessorResult = aLeappFileProcessor.processFileSystem(dataSource, moduleOutputPath);
|
||||||
|
|
||||||
|
if (fileProcessorResult == ProcessResult.ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the files that will be processed by the aLeapp program
|
||||||
|
*
|
||||||
|
* @param dataSource
|
||||||
|
*
|
||||||
|
* @return List of abstract files to process.
|
||||||
|
*/
|
||||||
|
private List<AbstractFile> findaLeappFilesToProcess(Content dataSource) {
|
||||||
|
|
||||||
|
List<AbstractFile> aLeappFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
FileManager fileManager = getCurrentCase().getServices().getFileManager();
|
||||||
|
|
||||||
|
// findFiles use the SQL wildcard % in the file name
|
||||||
|
try {
|
||||||
|
aLeappFiles = fileManager.findFiles(dataSource, "%", "/"); //NON-NLS
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, "No files found to process"); //NON-NLS
|
||||||
|
return aLeappFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AbstractFile> aLeappFilesToProcess = new ArrayList<>();
|
||||||
|
for (AbstractFile aLeappFile : aLeappFiles) {
|
||||||
|
if (((aLeappFile.getLocalAbsPath() != null)
|
||||||
|
&& (!aLeappFile.getNameExtension().isEmpty() && (!aLeappFile.isVirtual())))
|
||||||
|
&& ((aLeappFile.getName().toLowerCase().contains(".zip") || (aLeappFile.getName().toLowerCase().contains(".tar")))
|
||||||
|
|| aLeappFile.getName().toLowerCase().contains(".tgz"))) {
|
||||||
|
aLeappFilesToProcess.add(aLeappFile);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aLeappFilesToProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the aLeapp command to run
|
||||||
|
*
|
||||||
|
* @param moduleOutputPath output path for the aLeapp program.
|
||||||
|
* @param sourceFilePath where the source files to process reside.
|
||||||
|
* @param aLeappFileSystemType the filesystem type to process
|
||||||
|
*
|
||||||
|
* @return the command to execute
|
||||||
|
*/
|
||||||
|
private ProcessBuilder buildaLeappCommand(Path moduleOutputPath, String sourceFilePath, String aLeappFileSystemType) {
|
||||||
|
|
||||||
|
ProcessBuilder processBuilder = buildProcessWithRunAsInvoker(
|
||||||
|
"\"" + aLeappExecutable + "\"", //NON-NLS
|
||||||
|
"-t", aLeappFileSystemType, //NON-NLS
|
||||||
|
"-i", sourceFilePath, //NON-NLS
|
||||||
|
"-o", moduleOutputPath.toString()
|
||||||
|
);
|
||||||
|
processBuilder.redirectError(moduleOutputPath.resolve("aLeapp_err.txt").toFile()); //NON-NLS
|
||||||
|
processBuilder.redirectOutput(moduleOutputPath.resolve("aLeapp_out.txt").toFile()); //NON-NLS
|
||||||
|
return processBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProcessBuilder buildaLeappListCommand(Path moduleOutputPath) {
|
||||||
|
|
||||||
|
ProcessBuilder processBuilder = buildProcessWithRunAsInvoker(
|
||||||
|
"\"" + aLeappExecutable + "\"", //NON-NLS
|
||||||
|
"-p"
|
||||||
|
);
|
||||||
|
processBuilder.redirectError(moduleOutputPath.resolve("aLeapp_paths_error.txt").toFile()); //NON-NLS
|
||||||
|
processBuilder.redirectOutput(moduleOutputPath.resolve("aLeapp_paths.txt").toFile()); //NON-NLS
|
||||||
|
return processBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
static private ProcessBuilder buildProcessWithRunAsInvoker(String... commandLine) {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
|
||||||
|
/*
|
||||||
|
* Add an environment variable to force aLeapp to run with
|
||||||
|
* the same permissions Autopsy uses.
|
||||||
|
*/
|
||||||
|
processBuilder.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
|
||||||
|
return processBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File locateExecutable(String executableName) throws FileNotFoundException {
|
||||||
|
String executableToFindName = Paths.get(ALEAPP, executableName).toString();
|
||||||
|
|
||||||
|
File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, ALeappAnalyzerIngestModule.class.getPackage().getName(), false);
|
||||||
|
if (null == exeFile || exeFile.canExecute() == false) {
|
||||||
|
throw new FileNotFoundException(executableName + " executable not found.");
|
||||||
|
}
|
||||||
|
return exeFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the index.html file in the aLeapp output directory so it can be
|
||||||
|
* added to reports
|
||||||
|
*/
|
||||||
|
private void addILeappReportToReports(Path aLeappOutputDir, Case currentCase) {
|
||||||
|
List<String> allIndexFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
try (Stream<Path> walk = Files.walk(aLeappOutputDir)) {
|
||||||
|
|
||||||
|
allIndexFiles = walk.map(x -> x.toString())
|
||||||
|
.filter(f -> f.toLowerCase().endsWith("index.html")).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!allIndexFiles.isEmpty()) {
|
||||||
|
// Check for existance of directory that holds report data if does not exist then report contains no data
|
||||||
|
String filePath = FilenameUtils.getFullPathNoEndSeparator(allIndexFiles.get(0));
|
||||||
|
File dataFilesDir = new File(Paths.get(filePath, "_TSV Exports").toString());
|
||||||
|
if (dataFilesDir.exists()) {
|
||||||
|
currentCase.addReport(allIndexFiles.get(0), MODULE_NAME, Bundle.ALeappAnalyzerIngestModule_report_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException | UncheckedIOException | TskCoreException ex) {
|
||||||
|
// catch the error and continue on as report is not added
|
||||||
|
logger.log(Level.WARNING, String.format("Error finding index file in path %s", aLeappOutputDir.toString()), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads the aLeapp paths file to get the paths that we want to extract
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private List<String> loadIleappPathFile(Path moduleOutputPath) throws FileNotFoundException, IOException {
|
||||||
|
List<String> aLeappPathsToProcess = new ArrayList<>();
|
||||||
|
|
||||||
|
Path filePath = Paths.get(moduleOutputPath.toString(), ALEAPP_PATHS_FILE);
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(filePath.toString()))) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
while (line != null) {
|
||||||
|
if (line.contains("path list generation") || line.length() < 2) {
|
||||||
|
line = reader.readLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
aLeappPathsToProcess.add(line.trim());
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aLeappPathsToProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractFilesFromImage(Content dataSource, List<String> aLeappPathsToProcess, Path moduleOutputPath) {
|
||||||
|
FileManager fileManager = getCurrentCase().getServices().getFileManager();
|
||||||
|
|
||||||
|
for (String fullFilePath : aLeappPathsToProcess) {
|
||||||
|
|
||||||
|
if (context.dataSourceIngestIsCancelled()) {
|
||||||
|
logger.log(Level.INFO, "aLeapp Analyser ingest module run was canceled"); //NON-NLS
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ffp = fullFilePath.replaceAll("\\*", "%");
|
||||||
|
ffp = FilenameUtils.normalize(ffp, true);
|
||||||
|
String fileName = FilenameUtils.getName(ffp);
|
||||||
|
String filePath = FilenameUtils.getPath(ffp);
|
||||||
|
|
||||||
|
List<AbstractFile> aLeappFiles = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
if (filePath.isEmpty()) {
|
||||||
|
aLeappFiles = fileManager.findFiles(dataSource, fileName); //NON-NLS
|
||||||
|
} else {
|
||||||
|
aLeappFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, "No files found to process"); //NON-NLS
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractFile aLeappFile : aLeappFiles) {
|
||||||
|
Path parentPath = Paths.get(moduleOutputPath.toString(), aLeappFile.getParentPath());
|
||||||
|
File fileParentPath = new File(parentPath.toString());
|
||||||
|
|
||||||
|
extractFileToOutput(dataSource, aLeappFile, fileParentPath, parentPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractFileToOutput(Content dataSource, AbstractFile aLeappFile, File fileParentPath, Path parentPath) {
|
||||||
|
if (fileParentPath.exists()) {
|
||||||
|
if (!aLeappFile.isDir()) {
|
||||||
|
writeaLeappFile(dataSource, aLeappFile, fileParentPath.toString());
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(parentPath);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
|
||||||
|
}
|
||||||
|
if (!aLeappFile.isDir()) {
|
||||||
|
writeaLeappFile(dataSource, aLeappFile, fileParentPath.toString());
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeaLeappFile(Content dataSource, AbstractFile aLeappFile, String parentPath) {
|
||||||
|
String fileName = aLeappFile.getName().replace(":", "-");
|
||||||
|
if (!fileName.matches(".") && !fileName.matches("..") && !fileName.toLowerCase().endsWith("-slack")) {
|
||||||
|
Path filePath = Paths.get(parentPath, fileName);
|
||||||
|
File localFile = new File(filePath.toString());
|
||||||
|
try {
|
||||||
|
ContentUtils.writeToFile(aLeappFile, localFile, context::dataSourceIngestIsCancelled);
|
||||||
|
} catch (ReadContentInputStream.ReadContentInputStreamException ex) {
|
||||||
|
logger.log(Level.WARNING, String.format("Error reading file '%s' (id=%d).",
|
||||||
|
aLeappFile.getName(), aLeappFile.getId()), ex); //NON-NLS
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, String.format("Error writing file local file '%s' (id=%d).",
|
||||||
|
filePath.toString(), aLeappFile.getId()), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.modules.leappanalyzers;
|
||||||
|
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Version;
|
||||||
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory that creates data source ingest modules that will run aLeapp
|
||||||
|
* against logical files and saves the output to module output.
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = IngestModuleFactory.class)
|
||||||
|
public class ALeappAnalyzerModuleFactory extends IngestModuleFactoryAdapter {
|
||||||
|
|
||||||
|
@NbBundle.Messages({"ALeappAnalyzerModuleFactory_moduleName=Android Analyzer (aLEAPP)"})
|
||||||
|
static String getModuleName() {
|
||||||
|
return Bundle.ALeappAnalyzerModuleFactory_moduleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModuleDisplayName() {
|
||||||
|
return getModuleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"ALeappAnalyzerModuleFactory_moduleDesc=Uses aLEAPP to analyze logical acquisitions of Android devices."})
|
||||||
|
@Override
|
||||||
|
public String getModuleDescription() {
|
||||||
|
return Bundle.ALeappAnalyzerModuleFactory_moduleDesc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModuleVersionNumber() {
|
||||||
|
return Version.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDataSourceIngestModuleFactory() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings ingestJobOptions) {
|
||||||
|
return new ALeappAnalyzerIngestModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
||||||
|
ILeappAnalyzerIngestModule.processing.file=Processing file {0}
|
||||||
|
ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
||||||
|
ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
||||||
|
ALeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
||||||
|
ALeappAnalyzerIngestModule.processing.file=Processing file {0}
|
||||||
|
ALeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
||||||
|
ALeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
@ -0,0 +1,47 @@
|
|||||||
|
ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled
|
||||||
|
ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed
|
||||||
|
ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.
|
||||||
|
ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile
|
||||||
|
ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.
|
||||||
|
ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.
|
||||||
|
ALeappAnalyzerIngestModule.has.run=aLeapp
|
||||||
|
ALeappAnalyzerIngestModule.report.name=aLeapp Html Report
|
||||||
|
ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.
|
||||||
|
ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp
|
||||||
|
ALeappAnalyzerIngestModule.starting.aLeapp=Starting aLeapp
|
||||||
|
ALeappAnalyzerModuleFactory_moduleDesc=Uses aLEAPP to analyze logical acquisitions of Android devices.
|
||||||
|
ALeappAnalyzerModuleFactory_moduleName=Android Analyzer (aLEAPP)
|
||||||
|
ILeappAnalyzerIngestModule.completed=iLeapp Processing Completed
|
||||||
|
ILeappAnalyzerIngestModule.error.creating.output.dir=Error creating iLeapp module output directory.
|
||||||
|
ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize ILeappProcessFile
|
||||||
|
ILeappAnalyzerIngestModule.error.running.iLeapp=Error running iLeapp, see log file.
|
||||||
|
ILeappAnalyzerIngestModule.executable.not.found=iLeapp Executable Not Found.
|
||||||
|
ILeappAnalyzerIngestModule.has.run=iLeapp
|
||||||
|
ILeappAnalyzerIngestModule.iLeapp.cancelled=iLeapp run was canceled
|
||||||
|
ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
||||||
|
ILeappAnalyzerIngestModule.processing.file=Processing file {0}
|
||||||
|
ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
||||||
|
ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
||||||
|
ALeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
|
||||||
|
ALeappAnalyzerIngestModule.processing.file=Processing file {0}
|
||||||
|
ALeappAnalyzerIngestModule.parsing.file=Parsing file {0}
|
||||||
|
ALeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
|
||||||
|
ILeappAnalyzerIngestModule.report.name=iLeapp Html Report
|
||||||
|
ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
|
||||||
|
ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
|
||||||
|
ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
|
||||||
|
ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices.
|
||||||
|
ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)
|
||||||
|
LeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
|
||||||
|
LeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
|
||||||
|
LeappFileProcessor.completed=Leapp Processing Completed
|
||||||
|
LeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts.
|
||||||
|
LeappFileProcessor.error.creating.output.dir=Error creating Leapp module output directory.
|
||||||
|
LeappFileProcessor.error.reading.Leapp.directory=Error reading Leapp Output Directory
|
||||||
|
LeappFileProcessor.error.running.Leapp=Error running Leapp, see log file.
|
||||||
|
LeappFileProcessor.has.run=Leapp
|
||||||
|
LeappFileProcessor.Leapp.cancelled=Leapp run was canceled
|
||||||
|
LeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact
|
||||||
|
LeappFileProcessor.running.Leapp=Running Leapp
|
||||||
|
LeappFileProcessor.starting.Leapp=Starting Leapp
|
||||||
|
LeappFileProcessor_cannotParseXml=Cannot Parse XML file.
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.modules.ileappanalyzer;
|
package org.sleuthkit.autopsy.modules.leappanalyzers;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -71,11 +71,14 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule {
|
|||||||
private static final String ILEAPP_EXECUTABLE = "ileapp.exe";//NON-NLS
|
private static final String ILEAPP_EXECUTABLE = "ileapp.exe";//NON-NLS
|
||||||
private static final String ILEAPP_PATHS_FILE = "iLeapp_paths.txt"; //NON-NLS
|
private static final String ILEAPP_PATHS_FILE = "iLeapp_paths.txt"; //NON-NLS
|
||||||
|
|
||||||
|
private static final String XMLFILE = "ileap-artifact-attribute-reference.xml"; //NON-NLS
|
||||||
|
|
||||||
|
|
||||||
private File iLeappExecutable;
|
private File iLeappExecutable;
|
||||||
|
|
||||||
private IngestJobContext context;
|
private IngestJobContext context;
|
||||||
|
|
||||||
private ILeappFileProcessor iLeappFileProcessor;
|
private LeappFileProcessor iLeappFileProcessor;
|
||||||
|
|
||||||
ILeappAnalyzerIngestModule() {
|
ILeappAnalyzerIngestModule() {
|
||||||
// This constructor is intentionally empty. Nothing special is needed here.
|
// This constructor is intentionally empty. Nothing special is needed here.
|
||||||
@ -94,7 +97,7 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
iLeappFileProcessor = new ILeappFileProcessor();
|
iLeappFileProcessor = new LeappFileProcessor(XMLFILE);
|
||||||
} catch (IOException | IngestModuleException | NoCurrentCaseException ex) {
|
} catch (IOException | IngestModuleException | NoCurrentCaseException ex) {
|
||||||
throw new IngestModuleException(Bundle.ILeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
|
throw new IngestModuleException(Bundle.ILeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
|
||||||
}
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.modules.ileappanalyzer;
|
package org.sleuthkit.autopsy.modules.leappanalyzers;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.modules.ileappanalyzer;
|
package org.sleuthkit.autopsy.modules.leappanalyzers;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -63,14 +63,14 @@ import org.w3c.dom.NodeList;
|
|||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and process output from iLeapp program and bring into Autopsy
|
* Find and process output from Leapp program and bring into Autopsy
|
||||||
*/
|
*/
|
||||||
public final class ILeappFileProcessor {
|
public final class LeappFileProcessor {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ILeappFileProcessor.class.getName());
|
private static final Logger logger = Logger.getLogger(LeappFileProcessor.class.getName());
|
||||||
private static final String MODULE_NAME = ILeappAnalyzerModuleFactory.getModuleName();
|
private static final String MODULE_NAME = ILeappAnalyzerModuleFactory.getModuleName();
|
||||||
|
|
||||||
private static final String XMLFILE = "ileap-artifact-attribute-reference.xml"; //NON-NLS
|
private final String xmlFile; //NON-NLS
|
||||||
|
|
||||||
private final Map<String, String> tsvFiles;
|
private final Map<String, String> tsvFiles;
|
||||||
private final Map<String, String> tsvFileArtifacts;
|
private final Map<String, String> tsvFileArtifacts;
|
||||||
@ -79,11 +79,12 @@ public final class ILeappFileProcessor {
|
|||||||
|
|
||||||
Blackboard blkBoard;
|
Blackboard blkBoard;
|
||||||
|
|
||||||
public ILeappFileProcessor() throws IOException, IngestModuleException, NoCurrentCaseException {
|
public LeappFileProcessor(String xmlFile) throws IOException, IngestModuleException, NoCurrentCaseException {
|
||||||
this.tsvFiles = new HashMap<>();
|
this.tsvFiles = new HashMap<>();
|
||||||
this.tsvFileArtifacts = new HashMap<>();
|
this.tsvFileArtifacts = new HashMap<>();
|
||||||
this.tsvFileArtifactComments = new HashMap<>();
|
this.tsvFileArtifactComments = new HashMap<>();
|
||||||
this.tsvFileAttributes = new HashMap<>();
|
this.tsvFileAttributes = new HashMap<>();
|
||||||
|
this.xmlFile = xmlFile;
|
||||||
|
|
||||||
blkBoard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
|
blkBoard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
|
||||||
|
|
||||||
@ -93,22 +94,22 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"ILeappFileProcessor.error.running.iLeapp=Error running iLeapp, see log file.",
|
"LeappFileProcessor.error.running.Leapp=Error running Leapp, see log file.",
|
||||||
"ILeappFileProcessor.error.creating.output.dir=Error creating iLeapp module output directory.",
|
"LeappFileProcessor.error.creating.output.dir=Error creating Leapp module output directory.",
|
||||||
"ILeappFileProcessor.starting.iLeapp=Starting iLeapp",
|
"LeappFileProcessor.starting.Leapp=Starting Leapp",
|
||||||
"ILeappFileProcessor.running.iLeapp=Running iLeapp",
|
"LeappFileProcessor.running.Leapp=Running Leapp",
|
||||||
"ILeappFileProcessor.has.run=iLeapp",
|
"LeappFileProcessor.has.run=Leapp",
|
||||||
"ILeappFileProcessor.iLeapp.cancelled=iLeapp run was canceled",
|
"LeappFileProcessor.Leapp.cancelled=Leapp run was canceled",
|
||||||
"ILeappFileProcessor.completed=iLeapp Processing Completed",
|
"LeappFileProcessor.completed=Leapp Processing Completed",
|
||||||
"ILeappFileProcessor.error.reading.iLeapp.directory=Error reading iLeapp Output Directory"})
|
"LeappFileProcessor.error.reading.Leapp.directory=Error reading Leapp Output Directory"})
|
||||||
|
|
||||||
public ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile iLeappFile) {
|
public ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile LeappFile) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> iLeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
|
List<String> LeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
|
||||||
processiLeappFiles(iLeappTsvOutputFiles, iLeappFile);
|
processLeappFiles(LeappTsvOutputFiles, LeappFile);
|
||||||
} catch (IOException | IngestModuleException ex) {
|
} catch (IOException | IngestModuleException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error trying to process iLeapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error trying to process Leapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
|
||||||
return ProcessResult.ERROR;
|
return ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,10 +119,10 @@ public final class ILeappFileProcessor {
|
|||||||
public ProcessResult processFileSystem(Content dataSource, Path moduleOutputPath) {
|
public ProcessResult processFileSystem(Content dataSource, Path moduleOutputPath) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> iLeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
|
List<String> LeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
|
||||||
processiLeappFiles(iLeappTsvOutputFiles, dataSource);
|
processLeappFiles(LeappTsvOutputFiles, dataSource);
|
||||||
} catch (IOException | IngestModuleException ex) {
|
} catch (IOException | IngestModuleException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error trying to process iLeapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error trying to process Leapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
|
||||||
return ProcessResult.ERROR;
|
return ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,14 +130,14 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the tsv files in the iLeapp output directory and match them to files
|
* Find the tsv files in the Leapp output directory and match them to files
|
||||||
* we know we want to process and return the list to process those files.
|
* we know we want to process and return the list to process those files.
|
||||||
*/
|
*/
|
||||||
private List<String> findTsvFiles(Path iLeappOutputDir) throws IngestModuleException {
|
private List<String> findTsvFiles(Path LeappOutputDir) throws IngestModuleException {
|
||||||
List<String> allTsvFiles = new ArrayList<>();
|
List<String> allTsvFiles = new ArrayList<>();
|
||||||
List<String> foundTsvFiles = new ArrayList<>();
|
List<String> foundTsvFiles = new ArrayList<>();
|
||||||
|
|
||||||
try (Stream<Path> walk = Files.walk(iLeappOutputDir)) {
|
try (Stream<Path> walk = Files.walk(LeappOutputDir)) {
|
||||||
|
|
||||||
allTsvFiles = walk.map(x -> x.toString())
|
allTsvFiles = walk.map(x -> x.toString())
|
||||||
.filter(f -> f.toLowerCase().endsWith(".tsv")).collect(Collectors.toList());
|
.filter(f -> f.toLowerCase().endsWith(".tsv")).collect(Collectors.toList());
|
||||||
@ -148,7 +149,7 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException | UncheckedIOException e) {
|
} catch (IOException | UncheckedIOException e) {
|
||||||
throw new IngestModuleException(Bundle.ILeappFileProcessor_error_reading_iLeapp_directory() + iLeappOutputDir.toString(), e);
|
throw new IngestModuleException(Bundle.LeappFileProcessor_error_reading_Leapp_directory() + LeappOutputDir.toString(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundTsvFiles;
|
return foundTsvFiles;
|
||||||
@ -156,26 +157,26 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the iLeapp files that were found that match the xml mapping file
|
* Process the Leapp files that were found that match the xml mapping file
|
||||||
*
|
*
|
||||||
* @param iLeappFilesToProcess List of files to process
|
* @param LeappFilesToProcess List of files to process
|
||||||
* @param iLeappImageFile Abstract file to create artifact for
|
* @param LeappImageFile Abstract file to create artifact for
|
||||||
*
|
*
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void processiLeappFiles(List<String> iLeappFilesToProcess, AbstractFile iLeappImageFile) throws FileNotFoundException, IOException, IngestModuleException {
|
private void processLeappFiles(List<String> LeappFilesToProcess, AbstractFile LeappImageFile) throws FileNotFoundException, IOException, IngestModuleException {
|
||||||
List<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
List<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||||
|
|
||||||
for (String iLeappFileName : iLeappFilesToProcess) {
|
for (String LeappFileName : LeappFilesToProcess) {
|
||||||
String fileName = FilenameUtils.getName(iLeappFileName);
|
String fileName = FilenameUtils.getName(LeappFileName);
|
||||||
File iLeappFile = new File(iLeappFileName);
|
File LeappFile = new File(LeappFileName);
|
||||||
if (tsvFileAttributes.containsKey(fileName)) {
|
if (tsvFileAttributes.containsKey(fileName)) {
|
||||||
List<List<String>> attrList = tsvFileAttributes.get(fileName);
|
List<List<String>> attrList = tsvFileAttributes.get(fileName);
|
||||||
try {
|
try {
|
||||||
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
|
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
|
||||||
|
|
||||||
processFile(iLeappFile, attrList, fileName, artifactType, bbartifacts, iLeappImageFile);
|
processFile(LeappFile, attrList, fileName, artifactType, bbartifacts, LeappImageFile);
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
|
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
|
||||||
@ -191,26 +192,26 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the iLeapp files that were found that match the xml mapping file
|
* Process the Leapp files that were found that match the xml mapping file
|
||||||
*
|
*
|
||||||
* @param iLeappFilesToProcess List of files to process
|
* @param LeappFilesToProcess List of files to process
|
||||||
* @param iLeappImageFile Abstract file to create artifact for
|
* @param LeappImageFile Abstract file to create artifact for
|
||||||
*
|
*
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void processiLeappFiles(List<String> iLeappFilesToProcess, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException {
|
private void processLeappFiles(List<String> LeappFilesToProcess, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException {
|
||||||
List<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
List<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||||
|
|
||||||
for (String iLeappFileName : iLeappFilesToProcess) {
|
for (String LeappFileName : LeappFilesToProcess) {
|
||||||
String fileName = FilenameUtils.getName(iLeappFileName);
|
String fileName = FilenameUtils.getName(LeappFileName);
|
||||||
File iLeappFile = new File(iLeappFileName);
|
File LeappFile = new File(LeappFileName);
|
||||||
if (tsvFileAttributes.containsKey(fileName)) {
|
if (tsvFileAttributes.containsKey(fileName)) {
|
||||||
List<List<String>> attrList = tsvFileAttributes.get(fileName);
|
List<List<String>> attrList = tsvFileAttributes.get(fileName);
|
||||||
try {
|
try {
|
||||||
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
|
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
|
||||||
|
|
||||||
processFile(iLeappFile, attrList, fileName, artifactType, bbartifacts, dataSource);
|
processFile(LeappFile, attrList, fileName, artifactType, bbartifacts, dataSource);
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
|
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
|
||||||
@ -225,10 +226,10 @@ public final class ILeappFileProcessor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processFile(File iLeappFile, List<List<String>> attrList, String fileName, BlackboardArtifact.Type artifactType,
|
private void processFile(File LeappFile, List<List<String>> attrList, String fileName, BlackboardArtifact.Type artifactType,
|
||||||
List<BlackboardArtifact> bbartifacts, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException,
|
List<BlackboardArtifact> bbartifacts, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException,
|
||||||
TskCoreException {
|
TskCoreException {
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(iLeappFile))) {
|
try (BufferedReader reader = new BufferedReader(new FileReader(LeappFile))) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
// Check first line, if it is null then no heading so nothing to match to, close and go to next file.
|
// Check first line, if it is null then no heading so nothing to match to, close and go to next file.
|
||||||
if (line != null) {
|
if (line != null) {
|
||||||
@ -236,6 +237,10 @@ public final class ILeappFileProcessor {
|
|||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
while (line != null) {
|
while (line != null) {
|
||||||
Collection<BlackboardAttribute> bbattributes = processReadLine(line, columnNumberToProcess, fileName);
|
Collection<BlackboardAttribute> bbattributes = processReadLine(line, columnNumberToProcess, fileName);
|
||||||
|
if (artifactType == null) {
|
||||||
|
logger.log(Level.SEVERE, "Error trying to process Leapp output files in directory . "); //NON-NLS
|
||||||
|
|
||||||
|
}
|
||||||
if (!bbattributes.isEmpty() && !blkBoard.artifactExists(dataSource, BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactType.getTypeID()), bbattributes)) {
|
if (!bbattributes.isEmpty() && !blkBoard.artifactExists(dataSource, BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactType.getTypeID()), bbattributes)) {
|
||||||
BlackboardArtifact bbartifact = createArtifactWithAttributes(artifactType.getTypeID(), dataSource, bbattributes);
|
BlackboardArtifact bbartifact = createArtifactWithAttributes(artifactType.getTypeID(), dataSource, bbattributes);
|
||||||
if (bbartifact != null) {
|
if (bbartifact != null) {
|
||||||
@ -354,11 +359,11 @@ public final class ILeappFileProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.",
|
"LeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.",
|
||||||
"ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.",
|
"LeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.",
|
||||||
"ILeappFileProcessor_cannotParseXml=Cannot Parse XML file.",
|
"LeappFileProcessor_cannotParseXml=Cannot Parse XML file.",
|
||||||
"ILeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact",
|
"LeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact",
|
||||||
"ILeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts."
|
"LeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts."
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -367,18 +372,18 @@ public final class ILeappFileProcessor {
|
|||||||
private void loadConfigFile() throws IngestModuleException {
|
private void loadConfigFile() throws IngestModuleException {
|
||||||
Document xmlinput;
|
Document xmlinput;
|
||||||
try {
|
try {
|
||||||
String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFILE;
|
String path = PlatformUtil.getUserConfigDirectory() + File.separator + xmlFile;
|
||||||
File f = new File(path);
|
File f = new File(path);
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||||
xmlinput = db.parse(f);
|
xmlinput = db.parse(f);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IngestModuleException(Bundle.ILeappFileProcessor_cannot_load_artifact_xml() + e.getLocalizedMessage(), e); //NON-NLS
|
throw new IngestModuleException(Bundle.LeappFileProcessor_cannot_load_artifact_xml() + e.getLocalizedMessage(), e); //NON-NLS
|
||||||
} catch (ParserConfigurationException pce) {
|
} catch (ParserConfigurationException pce) {
|
||||||
throw new IngestModuleException(Bundle.ILeappFileProcessor_cannotBuildXmlParser() + pce.getLocalizedMessage(), pce); //NON-NLS
|
throw new IngestModuleException(Bundle.LeappFileProcessor_cannotBuildXmlParser() + pce.getLocalizedMessage(), pce); //NON-NLS
|
||||||
} catch (SAXException sxe) {
|
} catch (SAXException sxe) {
|
||||||
throw new IngestModuleException(Bundle.ILeappFileProcessor_cannotParseXml() + sxe.getLocalizedMessage(), sxe); //NON-NLS
|
throw new IngestModuleException(Bundle.LeappFileProcessor_cannotParseXml() + sxe.getLocalizedMessage(), sxe); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileNode(xmlinput);
|
getFileNode(xmlinput);
|
||||||
@ -466,7 +471,7 @@ public final class ILeappFileProcessor {
|
|||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
return bbart;
|
return bbart;
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, Bundle.ILeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
|
logger.log(Level.WARNING, Bundle.LeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -490,7 +495,7 @@ public final class ILeappFileProcessor {
|
|||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
return bbart;
|
return bbart;
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, Bundle.ILeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
|
logger.log(Level.WARNING, Bundle.LeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -509,17 +514,17 @@ public final class ILeappFileProcessor {
|
|||||||
try {
|
try {
|
||||||
Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifacts(artifacts, MODULE_NAME);
|
Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifacts(artifacts, MODULE_NAME);
|
||||||
} catch (Blackboard.BlackboardException ex) {
|
} catch (Blackboard.BlackboardException ex) {
|
||||||
logger.log(Level.SEVERE, Bundle.ILeappFileProcessor_postartifacts_error(), ex); //NON-NLS
|
logger.log(Level.SEVERE, Bundle.LeappFileProcessor_postartifacts_error(), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the iLeapp config xml file to the user directory to process
|
* Extract the Leapp config xml file to the user directory to process
|
||||||
*
|
*
|
||||||
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
|
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
|
||||||
*/
|
*/
|
||||||
private void configExtractor() throws IOException {
|
private void configExtractor() throws IOException {
|
||||||
PlatformUtil.extractResourceToUserConfigDir(ILeappFileProcessor.class, XMLFILE, true);
|
PlatformUtil.extractResourceToUserConfigDir(LeappFileProcessor.class, xmlFile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,307 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!---
|
||||||
|
This file contains the parameters for how to map aLeapp plugin output to attributes inside Autopsy for the aleapp Analyser module.
|
||||||
|
|
||||||
|
Each FileName node corresponds to a tab seperated values (tsv) file that is produced from iLeapp.
|
||||||
|
|
||||||
|
A FileName will have an associated TSK artifact assigned to it.
|
||||||
|
|
||||||
|
Each TSK artifact may have multiple attributes that correspond to the columns of the output from the iLeapp program tsv file.
|
||||||
|
|
||||||
|
|
||||||
|
FileName:
|
||||||
|
filename: The aLeapp TSV file that you want to process.
|
||||||
|
description: A description of the tsv file name, this is defined in the iLeapp plugin for each tsv file.
|
||||||
|
|
||||||
|
ArtifactName:
|
||||||
|
artifactname: The artifact that is to be created for the data in the tsv file.
|
||||||
|
comment: This will be the data that will be added to the TSK_COMMENT attribute for each artifact. If the artifact
|
||||||
|
does not need/require a comment then make the value null, a null comment will be ignored.
|
||||||
|
|
||||||
|
AttributeName:
|
||||||
|
attributeName: The TSK attribute that the data corresponds to in the TSV file. If the data has no corresponding TSK attribute then
|
||||||
|
make the value null, this will make sure the data in this column is ignored.
|
||||||
|
columnName: This is the column name that is defined in the tsv file and what the attributeName corresponds to.
|
||||||
|
required: whether the attribute is required or not (yes or no)
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
<aLeap_Files_To_Process>
|
||||||
|
|
||||||
|
<FileName filename="accounts ce 0.tsv" description="Accounts_ce">
|
||||||
|
<ArtifactName artifactname="TSK_SERVICE_ACCOUNT" comment="accounts ce 0">
|
||||||
|
<AttributeName attributename="TSK_USER_ID" columnName="Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName=" Type" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PASSWORD" columnName=" Password" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="authtokens 0.tsv" description="Authtokens">
|
||||||
|
<ArtifactName artifactname="TSK_SERVICE_ACCOUNT" comment="Authtokens">
|
||||||
|
<AttributeName attributename="null" columnName="ID" required="no" />
|
||||||
|
<AttributeName attributename="TSK_USER_ID" columnName=" Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName=" Account Type" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Authtoken Type" required="no" />
|
||||||
|
<AttributeName attributename="TSK_PASSWORD" columnName=" Authtoken" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="accounts de 0.tsv" description="Accounts_de">
|
||||||
|
<ArtifactName artifactname="TSK_SERVICE_ACCOUNT" comment="accounts de 0">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last password entry" required="no" />
|
||||||
|
<AttributeName attributename="TSK_USER_ID" columnName="Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName="Type" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser Bookmarks.tsv" description="Browser Bookmarks">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_BOOKMARK" comment="Browser Bookmarks">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED " columnName="Added Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName=" URL" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName=" Name" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName=" Parent" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" Type" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser cookies.tsv" description="Browser Cookies">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_COOKIE" comment="Browser Cookies">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESS" columnName="Last Access Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DOMAIN" columnName="Host" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_NAME" columnName="Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_VALUE" columnName="Value" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Created Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_END" columnName="Expiration Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PATH" columnName="Path" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser History.tsv" description="Browser History">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Browser History">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Visit Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName="Title" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Visit Count" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Hidden" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser keyword search terms.tsv" description="Browser keyword Search Terms">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_SEARCH_QUERY" comment="Browser Keyword Search Terms">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Visit Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Term" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser login data.tsv" description="Browser Login Data">
|
||||||
|
<ArtifactName artifactname="TSK_SERVICE_ACCOUNT" comment="Browser Login">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Created Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_USER_NAME" columnName="Username" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PASSWORD" columnName="Password" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="Origin URL" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName="Blacklisted by User" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser offline pages.tsv" description="Browser Offline Pages">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Browser Offline Pages">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Creation Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Access Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName=" Online URL" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName=" File Path" required="no" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName=" Title" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" Access Count" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" File Size" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser search terms.tsv" description="Browser Search Terms">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_SEARCH_QUERY" comment="Browser Search Terms">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Visit Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Search Term" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Title" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Visit Count" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Browser top sites.tsv" description="Browser Top Sites">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Browser Top Sites">
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Rank" required="no" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName="Title" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName="Redirects" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Call Logs.tsv" description="Call logs">
|
||||||
|
<ArtifactName artifactname="TSK_CALLLOG" comment="null">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_START" columnName="Call Date" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_PHONE_NUMBER_FROM" columnName="Phone Account Address" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_PHONE_NUMBER_TO" columnName="Partner" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_DIRECTION" columnName="Type" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Duration in Secs" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Partner Location" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Country ISO" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Data" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Mime Type" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Transcription" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Deleted" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome Bookmarks.tsv" description="Chrome Bookmarks">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_BOOKMARK" comment="Chrome Bookmarks">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED " columnName="Added Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName=" URL" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName=" Name" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName=" Parent" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" Type" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome cookies.tsv" description="Chrome Cookies">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_COOKIE" comment="Chrome Cookies">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESS" columnName="Last Access Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DOMAIN" columnName="Host" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_NAME" columnName="Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_VALUE" columnName="Value" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Created Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_END" columnName="Expiration Date" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PATH" columnName="Path" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome History.tsv" description="Chrome History">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Chrome History">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Visit Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName="Title" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Visit Count" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Hidden" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome login data.tsv" description="Chrome Login Data">
|
||||||
|
<ArtifactName artifactname="TSK_SERVICE_ACCOUNT" comment="Chrome Login">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Created Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_USER_NAME" columnName="Username" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PASSWORD" columnName="Password" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="Origin URL" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName="Blacklisted by User" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome offline pages.tsv" description="Chrome Offline Pages">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Chrome Offline Pages">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_CREATED" columnName="Creation Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Access Time" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_URL" columnName=" Online URL" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName=" File Path" required="no" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName=" Title" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" Access Count" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" File Size" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome search terms.tsv" description="Chrome Search Terms">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_SEARCH_QUERY" comment="Chrome Search Terms">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Last Visit Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Search Term" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Title" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Visit Count" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="Chrome top sites.tsv" description="Chrome Top Sites">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_HISTORY" comment="Chrome Top Sites">
|
||||||
|
<AttributeName attributename="TSK_URL" columnName="URL" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Rank" required="no" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName="Title" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName="Redirects" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="google play searches.tsv" description="Google Play Searches">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_SEARCH" comment="Google Play Search">
|
||||||
|
<AttributeName attributename="TSK_DATETIME_ACCESSED" columnName="Timestamp" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName="Display" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="query" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="google quick search box.tsv" description="Google quick search box">
|
||||||
|
<ArtifactName artifactname="TSK_WEB_SEARCH" comment="Google Quick Search Search">
|
||||||
|
<AttributeName attributename="TSK_DATETIME" columnName="File Timestamp" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Type" required="no" />
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Queries Response" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Source File" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="installed apps library.tsv" description="Installed Apps (Library)">
|
||||||
|
<ArtifactName artifactname="TSK_INSTALLED_PROG" comment="Installed Apps (Library)">
|
||||||
|
<AttributeName attributename="TSK_DATETIME" columnName="Purchase Time" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_USER_NAME" columnName="Account" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName="Doc ID" required="yes"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="installed apps - GMS.tsv" description="Installed Apps">
|
||||||
|
<ArtifactName artifactname="TSK_INSTALLED_PROG" comment="Installed Apps GSM">
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName="Bundle ID" required="yes" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="installed apps vending.tsv" description="Installed Apps (Vending)">
|
||||||
|
<ArtifactName artifactname="TSK_INSTALLED_PROG" comment="Installed Apps (VEnding)">
|
||||||
|
<AttributeName attributename="TSK_DATETIME" columnName="First Download" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PROG_NAME" columnName="Package Name" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_TITLE" columnName=" Title" required="yes" />
|
||||||
|
<AttributeName attributename="null" columnName="Install Reason" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" Auto Update?" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<FileName filename="mms messages.tsv" description="MMS messages">
|
||||||
|
<ArtifactName artifactname="TSK_MESSAGE" comment="MMS messages">
|
||||||
|
<AttributeName attributename="TSK_DATETIME" columnName="Date" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="MSG ID" required="no"/>
|
||||||
|
<AttributeName attributename="TSK_THREAD_ID" columnName="Thread ID" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_DATETIME_SENT" columnName="Date sent" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_READ_STATUS" columnName="Read" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_PHONE_NUMBER_FROM" columnName="From" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_PHONE_NUMBER_TO" columnName="To" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Cc" required="no"/>
|
||||||
|
<AttributeName attributename="null" columnName="Bcc" required="no"/>
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Body" required="yes"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
<!-- <FileName filename="partner settings.tsv" description="Partner Settings">
|
||||||
|
<ArtifactName artifactname="TSK_" comment="null">
|
||||||
|
<AttributeName attributename="null" columnName="Name" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName="Value ) # Dont remove the comma" required="no" />
|
||||||
|
<AttributeName attributename="null" columnName=" that is required to make this a tuple as there is only 1 eleme" required="no" />
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FileName filename="sms messages.tsv" description="SMS messages">
|
||||||
|
<ArtifactName artifactname="TSK_MESSAGE" comment="SMS messages">
|
||||||
|
<AttributeName attributename="TSK_DATETIME" columnName="Date" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="MSG ID" required="no"/>
|
||||||
|
<AttributeName attributename="TSK_THREAD_ID" columnName="Thread ID" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Address" required="yes" />
|
||||||
|
<AttributeName attributename="TSK_PHONE_NUMBER_FROM" columnName="Contact ID" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_DATETIME_SENT" columnName="Date sent" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_READ_STATUS" columnName="Read" required="yes"/>
|
||||||
|
<AttributeName attributename="TSK_TEXT" columnName="Body" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Service Center" required="yes"/>
|
||||||
|
<AttributeName attributename="null" columnName="Error Code" required="no"/>
|
||||||
|
</ArtifactName>
|
||||||
|
</FileName>
|
||||||
|
|
||||||
|
</aLeap_Files_To_Process>
|
21
thirdparty/aLeapp/LICENSE
vendored
Normal file
21
thirdparty/aLeapp/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Brigs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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 OR COPYRIGHT HOLDERS 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.
|
BIN
thirdparty/aLeapp/aleapp.exe
vendored
Normal file
BIN
thirdparty/aLeapp/aleapp.exe
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user