Yara ingest module

This commit is contained in:
Kelly Kelly 2020-11-04 13:41:49 -05:00
parent 621e828b72
commit 09d0c6e5f6
26 changed files with 1003 additions and 57 deletions

10
.gitignore vendored
View File

@ -89,3 +89,13 @@ hs_err_pid*.log
*.img
*.vhd
*.E01
/thirdparty/yara/yarabridge/yarabridge/x64/
/thirdparty/yara/yarabridge/yarabridge.VC.db
/thirdparty/yara/yarabridge/yarabridge.VC.VC.opendb
/thirdparty/yara/yarabridge/x64/
/thirdparty/yara/YaraWrapperTest/nbproject/private/
/thirdparty/yara/YaraWrapperTest/build/
/thirdparty/yara/YaraJNIWrapper/dist/
/thirdparty/yara/YaraJNIWrapper/build/
/thirdparty/yara/YaraJNIWrapper/nbproject/private/

View File

@ -98,6 +98,10 @@
<copy file="${thirdparty.dir}/jdom/jdom-2.0.5.jar" todir="${ext.dir}" />
<copy file="${thirdparty.dir}/jdom/jdom-2.0.5-contrib.jar" todir="${ext.dir}" />
<copy file="${thirdparty.dir}/DatCon/3.6.9/DatCon.jar" todir="${ext.dir}" />
<!--Copy iLeapp to release-->
<copy todir="${basedir}/release/yara" >
<fileset dir="${thirdparty.dir}/yara/bin"/>
</copy>
</target>

View File

@ -118,6 +118,7 @@ file.reference.StixLib.jar=release\\modules\\ext\\StixLib.jar
file.reference.threetenbp-1.3.3.jar=release\\modules\\ext\\threetenbp-1.3.3.jar
file.reference.webp-imageio-sejda-0.1.0.jar=release\\modules\\ext\\webp-imageio-sejda-0.1.0.jar
file.reference.xmpcore-5.1.3.jar=release\\modules\\ext\\xmpcore-5.1.3.jar
file.reference.YaraJNIWrapper.jar=release/modules/ext/YaraJNIWrapper.jar
file.reference.zookeeper-3.4.6.jar=release\\modules\\ext\\zookeeper-3.4.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -547,18 +547,10 @@
<runtime-relative-path>ext/checker-compat-qual-2.5.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\checker-compat-qual-2.5.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-4.10.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-4.10.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/animal-sniffer-annotations-1.17.jar</runtime-relative-path>
<binary-origin>release\modules\ext\animal-sniffer-annotations-1.17.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-caseuco-4.10.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-caseuco-4.10.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gax-1.44.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\gax-1.44.0.jar</binary-origin>
@ -567,6 +559,10 @@
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jsoup-1.10.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/YaraJNIWrapper.jar</runtime-relative-path>
<binary-origin>release/modules/ext/YaraJNIWrapper.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grpc-context-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-context-1.19.0.jar</binary-origin>
@ -671,6 +667,10 @@
<runtime-relative-path>ext/grpc-alts-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-alts-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-caseuco-4.10.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-caseuco-4.10.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jdom-2.0.5.jar</binary-origin>
@ -795,6 +795,10 @@
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sevenzipjbinding-AllPlatforms.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-4.10.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-4.10.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jutf7-1.0.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jutf7-1.0.0.jar</binary-origin>

View File

@ -0,0 +1,51 @@
/*
* 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.guicomponeontutils;
import javax.swing.Icon;
import org.sleuthkit.autopsy.guiutils.CheckBoxJList;
/**
* An abstract implementation of CheckBoxJList.CheckboxListItem so that
* implementing classes have default implementation.
*/
public abstract class AbstractCheckboxListItem implements CheckBoxJList.CheckboxListItem {
private boolean checked = false;
@Override
public boolean isChecked() {
return checked;
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
@Override
public boolean hasIcon() {
return false;
}
@Override
public Icon getIcon() {
return null;
}
}

View File

@ -32,8 +32,10 @@ import javax.swing.ListSelectionModel;
/**
* A JList that renders the list items as check boxes.
*
* @param <T> An object that implements CheckboxListItem
*/
final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JList<T> {
public final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JList<T> {
private static final long serialVersionUID = 1L;
@ -42,7 +44,7 @@ final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JLis
* a checkbox in CheckBoxJList.
*
*/
interface CheckboxListItem {
public interface CheckboxListItem {
/**
* Returns the checkbox state.
@ -83,7 +85,7 @@ final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JLis
/**
* Construct a new JCheckBoxList.
*/
CheckBoxJList() {
public CheckBoxJList() {
initalize();
}
@ -134,12 +136,15 @@ final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JLis
checkbox.setSelected(value.isChecked());
checkbox.setBackground(list.getBackground());
checkbox.setEnabled(list.isEnabled());
checkbox.setOpaque(list.isOpaque());
label.setText(value.getDisplayName());
label.setEnabled(list.isEnabled());
label.setOpaque(list.isOpaque());
if (value.hasIcon()) {
label.setIcon(value.getIcon());
}
setOpaque(list.isOpaque());
setEnabled(list.isEnabled());
return this;
}

View File

@ -0,0 +1,5 @@
Yara_Module_Description=With the YARA ingest module you use YARA rule files to search files for textual or binary patterns.
Yara_Module_Name=YARA
YaraIngestModule_no_ruleSets=Unable to run YARA ingest, list of YARA rule sets was empty.
YaraIngestModule_windows_error_msg=The YARA ingest module is only available on 64bit Windows.
YaraIngestModule_yarac_not_found=Unable to compile YARA rules files. Unable to find executable at.

View File

@ -0,0 +1,207 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.modules.yara;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.modules.yara.rules.RuleSet;
import org.sleuthkit.autopsy.modules.yara.rules.RuleSetManager;
import org.sleuthkit.autopsy.yara.YaraJNIWrapper;
import org.sleuthkit.autopsy.yara.YaraWrapperException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_YARA_HIT;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Methods for scanning files for yara rule matches.
*/
final class YaraIngestHelper {
private static final String YARA_DIR = "yara";
private static final String YARA_C_EXE = "yarac64.exe";
private static final String MODULE_NAME = YaraIngestModuleFactory.getModuleName();
private YaraIngestHelper() {
}
/**
* Uses the yarac tool to compile the rules in the given rule sets.
*
* @param ruleSetNames List of names of the selected rule sets.
* @param tempDir Path of the directory to put the compiled rule files.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
static void compileRules(List<String> ruleSetNames, Path outputDir) throws IngestModuleException {
if (ruleSetNames == null || ruleSetNames.isEmpty()) {
throw new IngestModule.IngestModuleException(Bundle.YaraIngestModule_no_ruleSets());
}
// Find javac
File exeFile = InstalledFileLocator.getDefault().locate(
Paths.get(YARA_DIR, YARA_C_EXE).toString(),
YaraIngestModule.class.getPackage().getName(), false);
if (exeFile == null) {
throw new IngestModuleException(Bundle.YaraIngestModule_yarac_not_found());
}
for (RuleSet set : getRuleSetsForNames(ruleSetNames)) {
compileRuleSet(set, outputDir, exeFile);
}
}
/**
* Scan the given AbstractFile for yara rule matches from the rule sets in
* the given directory creating a blackboard artifact for each matching
* rule.
*
* The baseDirectory should contain a series of directories one for each
* rule set.
*
* @param file The file to scan.
* @param baseDirectory Base directory for the compiled rule sets.
*
* @throws TskCoreException
*/
static List<BlackboardArtifact> scanFileForMatches(AbstractFile file, File baseDirectory) throws TskCoreException, YaraWrapperException {
List<BlackboardArtifact> artifacts = new ArrayList<>();
byte[] fileBytes = new byte[(int) file.getSize()];
file.read(fileBytes, 0, fileBytes.length);
File[] ruleSetDirectories = baseDirectory.listFiles();
for (File ruleSetDirectory : ruleSetDirectories) {
List<String> ruleMatches = YaraIngestHelper.scanFileForMatches(fileBytes, ruleSetDirectory);
if (!ruleMatches.isEmpty()) {
artifacts.addAll(YaraIngestHelper.createArtifact(file, ruleSetDirectory.getName(), ruleMatches));
}
}
return artifacts;
}
/**
* Scan the given file byte array for rule matches using the YaraJNIWrapper
* API.
*
* @param fileBytes
* @param ruleSetDirectory
*
* @return List of rules that match from the given file from the given rule
* set. Empty list is returned if no matches where found.
*
* @throws TskCoreException
*/
private static List<String> scanFileForMatches(byte[] fileBytes, File ruleSetDirectory) throws TskCoreException, YaraWrapperException {
List<String> matchingRules = new ArrayList<>();
File[] ruleSetCompiledFileList = ruleSetDirectory.listFiles();
for (File ruleFile : ruleSetCompiledFileList) {
matchingRules.addAll(YaraJNIWrapper.findRuleMatch(ruleFile.getAbsolutePath(), fileBytes));
}
return matchingRules;
}
/**
* Create a list of Blackboard Artifacts, one for each matching rule.
*
* @param abstractFile File to add artifact to.
* @param ruleSetName Name rule set with matching rule.
* @param matchingRules Matching rule.
*
* @return List of artifacts or empty list if none were found.
*
* @throws TskCoreException
*/
private static List<BlackboardArtifact> createArtifact(AbstractFile abstractFile, String ruleSetName, List<String> matchingRules) throws TskCoreException {
List<BlackboardArtifact> artifacts = new ArrayList<>();
for (String rule : matchingRules) {
BlackboardArtifact artifact = abstractFile.newArtifact(TSK_YARA_HIT);
List<BlackboardAttribute> attributes = new ArrayList<>();
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, ruleSetName));
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, rule));
artifact.addAttributes(attributes);
artifacts.add(artifact);
}
return artifacts;
}
@NbBundle.Messages({
"YaraIngestModule_yarac_not_found=Unable to compile YARA rules files. Unable to find executable at.",
"YaraIngestModule_no_ruleSets=Unable to run YARA ingest, list of YARA rule sets was empty."
})
/**
* Compiles the rule files in the given rule set.
*
* The compiled rule files are created in outputDir\RuleSetName.
*
* @param set RuleSet for which to compile files.
* @param outputDir Output directory for the compiled rule files.
* @param yarac yarac executeable file.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
static private void compileRuleSet(RuleSet set, Path outputDir, File yarac) throws IngestModuleException {
File tempFolder = Paths.get(outputDir.toString(), set.getName()).toFile();
if (!tempFolder.exists()) {
tempFolder.mkdir();
}
List<File> fileList = set.getRuleFiles();
for (File file : fileList) {
List<String> commandList = new ArrayList<>();
commandList.add(String.format("\"%s\"", yarac.toString()));
commandList.add(String.format("\"%s\"", file.toString()));
commandList.add(String.format("\"%s\"", Paths.get(tempFolder.getAbsolutePath(), "compiled_" + file.getName())));
ProcessBuilder builder = new ProcessBuilder(commandList);
try {
ExecUtil.execute(builder);
} catch (SecurityException | IOException ex) {
throw new IngestModuleException(String.format("Failed to compile Yara rules file", file.toString()), ex);
}
}
}
/**
* Returns a list of RuleSet objects for the given list of RuleSet names.
*
* @param names List of RuleSet names.
*
* @return List of RuleSet or empty list if none of the names matched
* existing rules.
*/
private static List<RuleSet> getRuleSetsForNames(List<String> names) {
List<RuleSet> ruleSetList = new ArrayList<>();
RuleSetManager manager = new RuleSetManager();
for (RuleSet set : manager.getRuleSetList()) {
if (names.contains(set.getName())) {
ruleSetList.add(set);
}
}
return ruleSetList;
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.yara;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.modules.yara.rules.RuleSet;
/**
* IngestJobSettings for the YARA ingest module.
*/
public final class YaraIngestJobSettings implements IngestModuleIngestJobSettings {
private static final long serialVersionUID = 1L;
private List<String> selectedRuleSetNames;
private boolean onlyExecutableFiles;
// Default constructor.
YaraIngestJobSettings() {
onlyExecutableFiles = true;
selectedRuleSetNames = new ArrayList<>();
}
/**
* Constructor.
*
* @param selected List of selected rules.
* @param onlyExecutableFiles Process only executable files.
*/
public YaraIngestJobSettings(List<RuleSet> selected, boolean onlyExecutableFiles) {
this.selectedRuleSetNames = new ArrayList<>();
for (RuleSet set : selected) {
selectedRuleSetNames.add(set.getName());
}
this.onlyExecutableFiles = onlyExecutableFiles;
}
/**
* Return the list of rule name sets that were selected in the ingest
* settings panel.
*
* @return List of selected RuleSet names.
*/
public List<String> getSelectedRuleSetNames() {
return Collections.unmodifiableList(selectedRuleSetNames);
}
/**
* Set the list of selected rule names.
*
* @param selected List of selected rule Sets.
*/
void setSelectedRuleSetNames(List<RuleSet> selected) {
this.selectedRuleSetNames = new ArrayList<>();
for (RuleSet set : selected) {
selectedRuleSetNames.add(set.getName());
}
}
/**
* Process only executable Files.
*
* @return If true the ingest module should process only executable files,
* if false process all files.
*/
public boolean onlyExecutableFiles() {
return onlyExecutableFiles;
}
/**
* Set whether to process only executable files or all files.
*
* @param onlyExecutableFiles True if the ingest module should only process
* executable files.
*/
void setOnlyExecuteableFile(boolean onlyExecutableFiles) {
this.onlyExecutableFiles = onlyExecutableFiles;
}
@Override
public long getVersionNumber() {
return serialVersionUID;
}
}

View File

@ -0,0 +1,168 @@
/*
* 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.yara;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import org.apache.commons.lang3.RandomStringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.yara.YaraWrapperException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.Blackboard.BlackboardException;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
* An ingest module that runs the yara against the given files.
*
*/
public class YaraIngestModule extends FileIngestModuleAdapter {
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
private final static Logger logger = Logger.getLogger(YaraIngestModule.class.getName());
private static final String YARA_DIR = "yara";
private static final Map<Long, Path> pathsByJobId = new ConcurrentHashMap<>();
private final YaraIngestJobSettings settings;
private IngestJobContext context = null;
private Long jobId;
/**
* Constructor.
*
* @param settings
*/
YaraIngestModule(YaraIngestJobSettings settings) {
this.settings = settings;
}
@Messages({
"YaraIngestModule_windows_error_msg=The YARA ingest module is only available on 64bit Windows.",})
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
this.context = context;
this.jobId = context.getJobId();
if (!PlatformUtil.isWindowsOS() || !PlatformUtil.is64BitOS()) {
throw new IngestModule.IngestModuleException(Bundle.YaraIngestModule_windows_error_msg());
}
if (refCounter.incrementAndGet(jobId) == 1) {
// compile the selected rules & put into temp folder based on jobID
Path tempDir = getTempDirectory(jobId);
YaraIngestHelper.compileRules(settings.getSelectedRuleSetNames(), tempDir);
}
}
@Override
public void shutDown() {
if (context != null && refCounter.decrementAndGet(jobId) == 0) {
// do some clean up.
Path jobPath = pathsByJobId.get(jobId);
if (jobPath != null) {
jobPath.toFile().delete();
pathsByJobId.remove(jobId);
}
}
}
@Override
public ProcessResult process(AbstractFile file) {
if (settings.onlyExecutableFiles()) {
String extension = file.getNameExtension();
if (!extension.equals("exe")) {
return ProcessResult.OK;
}
}
// Skip the file if its 0 in length.
if (file.getSize() == 0) {
return ProcessResult.OK;
}
try {
List<BlackboardArtifact> artifacts = YaraIngestHelper.scanFileForMatches(file, getTempDirectory(jobId).toFile());
if(!artifacts.isEmpty()) {
Blackboard blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
blackboard.postArtifacts(artifacts, YaraIngestModuleFactory.getModuleName());
}
} catch (BlackboardException | NoCurrentCaseException | IngestModuleException | TskCoreException | YaraWrapperException ex) {
logger.log(Level.SEVERE, "YARA ingest module failed to process file.", ex);
return ProcessResult.ERROR;
}
return ProcessResult.OK;
}
/**
* Return the temp directory for this jobId. If the folder does not exit it
* will be created.
*
* @param jobId The current jobId
*
* @return The path of the temporary directory for the given jobId.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
private synchronized Path getTempDirectory(long jobId) throws IngestModuleException {
Path jobPath = pathsByJobId.get(jobId);
if (jobPath != null) {
return jobPath;
}
Path baseDir;
try {
baseDir = Paths.get(Case.getCurrentCaseThrows().getTempDirectory(), YARA_DIR);
} catch (NoCurrentCaseException ex) {
throw new IngestModuleException("Failed to create YARA ingest model temp directory, no open case.", ex);
}
// Make the base yara directory, as needed
if (!baseDir.toFile().exists()) {
baseDir.toFile().mkdirs();
}
String randomDirName = String.format("%s_%d", RandomStringUtils.randomAlphabetic(8), jobId);
jobPath = Paths.get(baseDir.toString(), randomDirName);
jobPath.toFile().mkdir();
pathsByJobId.put(jobId, jobPath);
return jobPath;
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.yara;
import java.util.ArrayList;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
import org.sleuthkit.autopsy.modules.yara.ui.YaraIngestSettingsPanel;
/**
* A factory that creates ingest modules that use the Yara rule set definitions
* to identify files that may be of interest to the user.
*/
@ServiceProvider(service = IngestModuleFactory.class)
public class YaraIngestModuleFactory extends IngestModuleFactoryAdapter {
@Messages({
"Yara_Module_Name=YARA",
"Yara_Module_Description=With the YARA ingest module you use YARA rule files to search files for textual or binary patterns."
})
@Override
public String getModuleDisplayName() {
return getModuleName();
}
@Override
public String getModuleDescription() {
return Bundle.Yara_Module_Description();
}
@Override
public String getModuleVersionNumber() {
return Version.getVersion();
}
@Override
public boolean hasIngestJobSettingsPanel() {
return true;
}
@Override
public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
return new YaraIngestSettingsPanel((YaraIngestJobSettings)settings);
}
@Override
public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
return new YaraIngestJobSettings(new ArrayList<>(), true);
}
@Override
public boolean isFileIngestModuleFactory() {
return true;
}
@Override
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
return new YaraIngestModule((YaraIngestJobSettings) settings);
}
/**
* Return the name of the ingest module.
*
* @return Ingest module name.
*/
static String getModuleName() {
return Bundle.Yara_Module_Name();
}
}

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.modules.yara.rules;
import java.io.File;
import java.io.Serializable;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
@ -26,7 +27,9 @@ import java.util.List;
/**
* Represents a yara rule set which is a collection of yara rule files.
*/
public class RuleSet implements Comparable<RuleSet> {
public class RuleSet implements Comparable<RuleSet>, Serializable {
private static final long serialVersionUID = 1L;
private final String name;
private final Path path;

View File

@ -8,3 +8,7 @@ RuleSetDetailsPanel.setDetailsLabel.text=Set Details
RuleSetDetailsPanel.openFolderButton.text=Open Folder
RuleSetPanel.descriptionField.text=This module allows you to find files the match Yara rules. Each set has a list of Yara rule files. A file need only match one rule in the set to be found.
RuleSetDetailsPanel.openLabel.text=Place rule files in the set's folder. They will be compiled before use.
YaraIngestSettingsPanel.border.title=Select YARA rule sets to enable during ingest:
YaraIngestSettingsPanel.allFilesButton.text=All Files
YaraIngestSettingsPanel.allFilesButton.toolTipText=
YaraIngestSettingsPanel.executableFilesButton.text=Only Executable Files

View File

@ -10,6 +10,10 @@ RuleSetDetailsPanel.setDetailsLabel.text=Set Details
RuleSetDetailsPanel.openFolderButton.text=Open Folder
RuleSetPanel.descriptionField.text=This module allows you to find files the match Yara rules. Each set has a list of Yara rule files. A file need only match one rule in the set to be found.
RuleSetDetailsPanel.openLabel.text=Place rule files in the set's folder. They will be compiled before use.
YaraIngestSettingsPanel.border.title=Select YARA rule sets to enable during ingest:
YaraIngestSettingsPanel.allFilesButton.text=All Files
YaraIngestSettingsPanel.allFilesButton.toolTipText=
YaraIngestSettingsPanel.executableFilesButton.text=Only Executable Files
# {0} - rule set name
YaraRuleSetOptionPanel_badName_msg=Rule set name {0} already exists.\nRule set names must be unique.
YaraRuleSetOptionPanel_badName_title=Create Rule Set

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup">
</Component>
</NonVisualComponents>
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Select YARA rule sets to enable during ingest:">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="YaraIngestSettingsPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
</Properties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="scrollPane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="buttonPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JRadioButton" name="allFilesButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="YaraIngestSettingsPanel.allFilesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="YaraIngestSettingsPanel.allFilesButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JRadioButton" name="executableFilesButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup"/>
</Property>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties" key="YaraIngestSettingsPanel.executableFilesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,182 @@
/*
* 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.yara.ui;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.DefaultListModel;
import org.sleuthkit.autopsy.guicomponeontutils.AbstractCheckboxListItem;
import org.sleuthkit.autopsy.guiutils.CheckBoxJList;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
import org.sleuthkit.autopsy.modules.yara.YaraIngestJobSettings;
import org.sleuthkit.autopsy.modules.yara.rules.RuleSet;
import org.sleuthkit.autopsy.modules.yara.rules.RuleSetManager;
/**
* Yara Ingest settings panel.
*/
public class YaraIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
private static final long serialVersionUID = 1L;
private final CheckBoxJList<RuleSetListItem> checkboxList;
private final DefaultListModel<RuleSetListItem> listModel;
/**
* Creates new form YaraIngestSettingsPanel
*/
YaraIngestSettingsPanel() {
initComponents();
listModel = new DefaultListModel<>();
checkboxList = new CheckBoxJList<>();
scrollPane.setViewportView(checkboxList);
}
public YaraIngestSettingsPanel(YaraIngestJobSettings settings) {
this();
List<String> setNames = settings.getSelectedRuleSetNames();
checkboxList.setModel(listModel);
checkboxList.setOpaque(false);
RuleSetManager manager = new RuleSetManager();
List<RuleSet> ruleSetList = manager.getRuleSetList();
for (RuleSet set : ruleSetList) {
RuleSetListItem item = new RuleSetListItem(set);
item.setChecked(setNames.contains(set.getName()));
listModel.addElement(item);
}
allFilesButton.setSelected(!settings.onlyExecutableFiles());
executableFilesButton.setSelected(settings.onlyExecutableFiles());
}
@Override
public IngestModuleIngestJobSettings getSettings() {
List<RuleSet> selectedRules = new ArrayList<>();
Enumeration<RuleSetListItem> enumeration = listModel.elements();
while (enumeration.hasMoreElements()) {
RuleSetListItem item = enumeration.nextElement();
if (item.isChecked()) {
selectedRules.add(item.getRuleSet());
}
}
return new YaraIngestJobSettings(selectedRules, executableFilesButton.isSelected());
}
/**
* RuleSet wrapper class for Checkbox JList model.
*/
private final class RuleSetListItem extends AbstractCheckboxListItem {
private final RuleSet ruleSet;
/**
* RuleSetListItem constructor.
*
* @param set RuleSet object to display in list.
*/
RuleSetListItem(RuleSet set) {
this.ruleSet = set;
}
/**
* Returns the RuleSet.
*
* @return
*/
RuleSet getRuleSet() {
return ruleSet;
}
@Override
public String getDisplayName() {
return ruleSet.getName();
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
buttonGroup = new javax.swing.ButtonGroup();
scrollPane = new javax.swing.JScrollPane();
buttonPanel = new javax.swing.JPanel();
allFilesButton = new javax.swing.JRadioButton();
executableFilesButton = new javax.swing.JRadioButton();
setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(YaraIngestSettingsPanel.class, "YaraIngestSettingsPanel.border.title"))); // NOI18N
setLayout(new java.awt.GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
add(scrollPane, gridBagConstraints);
buttonPanel.setLayout(new java.awt.GridBagLayout());
buttonGroup.add(allFilesButton);
org.openide.awt.Mnemonics.setLocalizedText(allFilesButton, org.openide.util.NbBundle.getMessage(YaraIngestSettingsPanel.class, "YaraIngestSettingsPanel.allFilesButton.text")); // NOI18N
allFilesButton.setToolTipText(org.openide.util.NbBundle.getMessage(YaraIngestSettingsPanel.class, "YaraIngestSettingsPanel.allFilesButton.toolTipText")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
buttonPanel.add(allFilesButton, gridBagConstraints);
buttonGroup.add(executableFilesButton);
executableFilesButton.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(executableFilesButton, org.openide.util.NbBundle.getMessage(YaraIngestSettingsPanel.class, "YaraIngestSettingsPanel.executableFilesButton.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
buttonPanel.add(executableFilesButton, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.weightx = 1.0;
add(buttonPanel, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JRadioButton allFilesButton;
private javax.swing.ButtonGroup buttonGroup;
private javax.swing.JPanel buttonPanel;
private javax.swing.JRadioButton executableFilesButton;
private javax.swing.JScrollPane scrollPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -179,9 +179,7 @@ is divided into following sections:
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
<or/>
</condition>
<condition property="have.sources">
<or>
@ -289,7 +287,6 @@ is divided into following sections:
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
@ -588,9 +585,6 @@ is divided into following sections:
<j2seproject3:junit-prototype>
<customizePrototype>
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
<fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
<filename name="${test.binarytestincludes}"/>
</fileset>
@ -613,11 +607,7 @@ is divided into following sections:
<condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
<isset property="test.method"/>
</condition>
<union id="test.set">
<fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</union>
<union id="test.set"/>
<taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
<testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="YaraJNIWrapper" testname="TestNG tests" workingDir="${work.dir}">
<xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
@ -1544,14 +1534,14 @@ is divided into following sections:
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-javac-module-properties-with-module">
<j2seproject3:modulename property="test.module.name" sourcepath="${test.src.dir}"/>
<condition else="${empty.dir}" property="javac.test.sourcepath" value="${test.src.dir}">
<j2seproject3:modulename property="test.module.name" sourcepath=""/>
<condition else="${empty.dir}" property="javac.test.sourcepath" value="">
<and>
<isset property="test.module.name"/>
<length length="0" string="${test.module.name}" when="greater"/>
</and>
</condition>
<condition else="--patch-module ${module.name}=${test.src.dir} --add-reads ${module.name}=ALL-UNNAMED" property="javac.test.compilerargs" value="--add-reads ${test.module.name}=ALL-UNNAMED">
<condition else="--patch-module ${module.name}= --add-reads ${module.name}=ALL-UNNAMED" property="javac.test.compilerargs" value="--add-reads ${test.module.name}=ALL-UNNAMED">
<and>
<isset property="test.module.name"/>
<length length="0" string="${test.module.name}" when="greater"/>
@ -1592,17 +1582,15 @@ is divided into following sections:
</target>
<target depends="-init-test-javac-module-properties-with-module,-init-test-module-properties-without-module" name="-init-test-module-properties"/>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir=""/>
</target>
<target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${javac.test.sourcepath}" srcdir="${test.src.dir}">
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${javac.test.sourcepath}" srcdir="">
<customize>
<compilerarg line="${javac.test.compilerargs}"/>
</customize>
</j2seproject3:javac>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
<copy todir="${build.test.classes.dir}"/>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
@ -1616,14 +1604,12 @@ is divided into following sections:
<target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}, module-info.java" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}">
<j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}, module-info.java" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="" srcdir="">
<customize>
<compilerarg line="${javac.test.compilerargs}"/>
</customize>
</j2seproject3:javac>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
<copy todir="${build.test.classes.dir}"/>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->

View File

@ -1,9 +1,10 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processor.options=
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=YaraJNIWrapper
application.vendor=kelly
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
@ -32,10 +33,13 @@ dist.jar=${dist.dir}/YaraJNIWrapper.jar
dist.javadoc.dir=${dist.dir}/javadoc
dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/YaraJNIWrapper
endorsed.classpath=
excludes=
file.reference.yara-lib=src/org/sleuthkit/autopsy/yara/lib
includes=**
jar.compress=false
javac.classpath=
javac.classpath=\
${file.reference.yara-lib}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
@ -90,4 +94,3 @@ run.test.modulepath=\
${javac.test.modulepath}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -7,9 +7,7 @@
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
<test-roots/>
</data>
</configuration>
</project>

View File

@ -18,9 +18,11 @@
*/
package org.sleuthkit.autopsy.yara;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -31,18 +33,12 @@ import java.util.logging.Logger;
*/
public class YaraJNIWrapper {
// Load the yarabridge.dll which should be located in the same directory as
// the jar file. If we need to use this code for debugging the dll this
// code will need to be modified to add that support.
static {
Path directoryPath = null;
try {
directoryPath = Paths.get(YaraJNIWrapper.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent().toAbsolutePath();
} catch (URISyntaxException ex) {
extractAndLoadDll();
} catch (IOException | YaraWrapperException ex) {
Logger.getLogger(YaraJNIWrapper.class.getName()).log(Level.SEVERE, null, ex);
}
String libraryPath = Paths.get(directoryPath != null ? directoryPath.toString() : "", "yarabridge.dll").toAbsolutePath().toString();
System.load(libraryPath);
}
/**
@ -59,6 +55,36 @@ public class YaraJNIWrapper {
*/
static public native List<String> findRuleMatch(String compiledRulesPath, byte[] byteBuffer) throws YaraWrapperException;
/**
* Copy yarabridge.dll from inside the jar to a temp file that can be loaded
* with System.load.
*
* To make this work, the dll needs to be in the same folder as this source
* file. The dll needs to be located somewhere in the jar class path.
*
* @throws IOException
* @throws YaraWrapperException
*/
static private void extractAndLoadDll() throws IOException, YaraWrapperException {
File tempFile = File.createTempFile("lib", null);
tempFile.deleteOnExit();
try (InputStream in = YaraJNIWrapper.class.getResourceAsStream("yarabridge.dll")) {
if (in == null) {
throw new YaraWrapperException("native library was not found in jar file.");
}
try (OutputStream out = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int lengthRead;
while ((lengthRead = in.read(buffer)) > 0) {
out.write(buffer, 0, lengthRead);
out.flush();
}
}
}
System.load(tempFile.getAbsolutePath());
}
/**
* private constructor.
*/

View File

@ -35,7 +35,7 @@ dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/YaraWrapperTest
endorsed.classpath=
excludes=
file.reference.YaraJNIWrapper.jar=../bin/YaraJNIWrapper.jar
file.reference.YaraJNIWrapper.jar=../YaraJNIWrapper/dist/YaraJNIWrapper.jar
includes=**
jar.compress=false
javac.classpath=\

Binary file not shown.

Binary file not shown.

BIN
thirdparty/yara/bin/yarac64.exe vendored Executable file

Binary file not shown.

View File

@ -113,7 +113,7 @@
<AdditionalDependencies>ws2_32.lib;crypt32.lib;libyara64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)..\bin\$(ProjectName).dll"</Command>
<Command>copy "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)..\YaraJNIWrapper\src\org\sleuthkit\autopsy\yara\$(ProjectName).dll"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -153,7 +153,7 @@
<AdditionalDependencies>ws2_32.lib;crypt32.lib;libyara64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)..\bin\$(ProjectName).dll"</Command>
<Command>copy "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)..\YaraJNIWrapper\src\org\sleuthkit\autopsy\yara\$(ProjectName).dll"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>