Merge pull request #6478 from markmckinnon/6965-Complete-aLeapp-Module

6965 complete a leapp module
This commit is contained in:
Richard Cordovano 2020-12-07 11:36:13 -05:00 committed by GitHub
commit 071dadd475
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1016 additions and 95 deletions

View File

@ -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"/>

View File

@ -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

View File

@ -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.

View 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
}
}
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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.

View 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);
} }

View 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 org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;

View 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;
@ -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);
} }
} }

View File

@ -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
View 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

Binary file not shown.