mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-5290_d-millar_angr--SQUASHED'
This commit is contained in:
commit
70d43e73d8
24 changed files with 605 additions and 113 deletions
|
@ -29,6 +29,7 @@ dependencies {
|
||||||
api project(':Base')
|
api project(':Base')
|
||||||
api project(':ByteViewer')
|
api project(':ByteViewer')
|
||||||
api project(':Decompiler')
|
api project(':Decompiler')
|
||||||
|
api project(':DecompilerDependent')
|
||||||
api project(':FunctionGraph')
|
api project(':FunctionGraph')
|
||||||
api project(':ProposedUtils')
|
api project(':ProposedUtils')
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* 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 ghidra.app.plugin.core.debug.taint;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.app.decompiler.ClangFuncNameToken;
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.*;
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.app.services.ConsoleService;
|
||||||
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.lang.*;
|
||||||
|
import ghidra.program.model.listing.CodeUnit;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.pcode.HighParam;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.memory.*;
|
||||||
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.NumericUtilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for all the decompiler elements the users "selects" via the menu.
|
||||||
|
* This data is used to build queries.
|
||||||
|
*/
|
||||||
|
public class AngrTaintState extends AbstractTaintState {
|
||||||
|
|
||||||
|
private DebuggerTraceManagerService traceManager;
|
||||||
|
|
||||||
|
public AngrTaintState(TaintPlugin plugin) {
|
||||||
|
super(plugin);
|
||||||
|
ENGINE_NAME = "angr";
|
||||||
|
usesIndex = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address start;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildQuery(List<String> paramList, Path engine, File indexDBFile,
|
||||||
|
String indexDirectory) {
|
||||||
|
paramList.add("python");
|
||||||
|
paramList.add(engine.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildIndex(List<String> paramList, String engine_path, String facts_path,
|
||||||
|
String indexDirectory) {
|
||||||
|
// Unused
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GhidraScript getExportScript(ConsoleService console, boolean perFunction) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeHeader(PrintWriter writer) {
|
||||||
|
Program currentProgram = plugin.getCurrentProgram();
|
||||||
|
start = currentProgram.getMaxAddress().getNewAddress(Integer.MAX_VALUE);
|
||||||
|
writer.println("{");
|
||||||
|
writer.println("\t\"binary_file\":\"" + currentProgram.getExecutablePath() + "\",");
|
||||||
|
writer.println("\t\"base_address\":\"" +
|
||||||
|
Long.toHexString(currentProgram.getImageBase().getOffset()) + "\",");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: This is the only method used now for Sources and Sinks.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void writeRule(PrintWriter writer, TaintLabel mark, boolean isSource) {
|
||||||
|
Program currentProgram = plugin.getCurrentProgram();
|
||||||
|
Address addr = mark.getAddress();
|
||||||
|
if (isSource) {
|
||||||
|
if (start.getOffset() > addr.getOffset()) {
|
||||||
|
start = addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writer.println("\t\"find_address\":\"" + Long.toHexString(addr.getOffset()) + "\",");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSource) {
|
||||||
|
if (mark.getToken() instanceof ClangFuncNameToken) {
|
||||||
|
CodeUnit cu = currentProgram.getListing().getCodeUnitAt(addr);
|
||||||
|
writer.println("\t\"hooks\":[{\"" + Long.toHexString(addr.getOffset()) +
|
||||||
|
"\":{\"length\":\"" + cu.getLength() + "\"}}],");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mark.getHighVariable() instanceof HighParam hp) {
|
||||||
|
writer.println(
|
||||||
|
"\t\"arguments\":{\"" + hp.getSlot() + "\":\"" + mark.getSize() + "\"},");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Address vaddr = mark.getVarnodeAddress();
|
||||||
|
if (vaddr != null) {
|
||||||
|
if (vaddr.isRegisterAddress()) {
|
||||||
|
Language language = currentProgram.getLanguage();
|
||||||
|
Register register = language.getRegister(vaddr, mark.getSize());
|
||||||
|
writer.println("\t\"regs_vals\":{\"" + register.getName() + "\":\"" +
|
||||||
|
mark.getSize() + "\"},");
|
||||||
|
}
|
||||||
|
if (vaddr.isMemoryAddress()) {
|
||||||
|
writer.println("\t\"vectors\":{\"" + vaddr + "\":\"" + mark.getSize() + "\"},");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeGate(PrintWriter writer, TaintLabel mark) {
|
||||||
|
Address addr = mark.getAddress();
|
||||||
|
writer.println("\t\"avoid_address\":\"" + Long.toHexString(addr.getOffset()) + "\",");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeFooter(PrintWriter writer) {
|
||||||
|
writeState(writer);
|
||||||
|
writer.println("\t\"blank_state\":\"" + Long.toHexString(start.getOffset()) + "\",");
|
||||||
|
writer.println("\t\"auto_load_libs\":false");
|
||||||
|
writer.println("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeState(PrintWriter writer) {
|
||||||
|
if (traceManager == null) {
|
||||||
|
traceManager = plugin.getTool().getService(DebuggerTraceManagerService.class);
|
||||||
|
if (traceManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebuggerCoordinates current = traceManager.getCurrent();
|
||||||
|
Trace trace = current.getTrace();
|
||||||
|
if (trace == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceMemoryManager memoryManager = trace.getMemoryManager();
|
||||||
|
Collection<? extends TraceMemoryRegion> allRegions =
|
||||||
|
memoryManager.getRegionsAtSnap(current.getSnap());
|
||||||
|
for (TraceMemoryRegion region : allRegions) {
|
||||||
|
AddressRange range = region.getRange();
|
||||||
|
Address min = range.getMinAddress();
|
||||||
|
int len = (int) range.getLength();
|
||||||
|
byte[] bytes = new byte[len];
|
||||||
|
int nread =
|
||||||
|
memoryManager.getBytes(current.getSnap(), min, ByteBuffer.wrap(bytes));
|
||||||
|
if (nread == len) {
|
||||||
|
writer.println("\t\"mem_store\":{\"" + min + "\":\"" + convert(bytes) + "\"},");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Msg.error(this, "Requested " + len + " but returned " + nread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Program currentProgram = plugin.getCurrentProgram();
|
||||||
|
List<Register> registers = currentProgram.getLanguage().getRegisters();
|
||||||
|
TraceThread thread = current.getThread();
|
||||||
|
if (thread == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TraceMemorySpace regs =
|
||||||
|
memoryManager.getMemoryRegisterSpace(thread, current.getFrame(), true);
|
||||||
|
if (regs == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Register r : registers) {
|
||||||
|
TraceMemoryState state = regs.getState(current.getPlatform(), current.getSnap(), r);
|
||||||
|
if (!state.equals(TraceMemoryState.KNOWN)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RegisterValue value = regs.getValue(current.getSnap(), r);
|
||||||
|
byte[] bytes = value.getUnsignedValue().toByteArray();
|
||||||
|
String bytestr = convert(bytes);
|
||||||
|
if (!bytestr.equals("") && !bytestr.equals("00")) {
|
||||||
|
writer.println(
|
||||||
|
"\t\"regs_vals\":{\"" + r.getName() + "\":\"0x" + convert(bytes) + "\"},");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convert(byte[] bytes) {
|
||||||
|
return NumericUtilities.convertBytesToString(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readQueryResultsIntoDataFrame(Program program, InputStream is) {
|
||||||
|
|
||||||
|
Program currentProgram = plugin.getCurrentProgram();
|
||||||
|
String line = null;
|
||||||
|
taintAddressSet.clear();
|
||||||
|
taintVarnodeMap.clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
|
||||||
|
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
if (line.startsWith("t:")) {
|
||||||
|
String addrStr = line.substring(line.indexOf(":") + 1);
|
||||||
|
Address address = currentProgram.getMinAddress().getAddress(addrStr);
|
||||||
|
taintAddressSet.add(address);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bufferedReader.close();
|
||||||
|
}
|
||||||
|
catch (IOException | AddressFormatException e) {
|
||||||
|
plugin.consoleMessage("IO Error Reading Query Results from Process: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
DataTypeReferenceFinder
|
DataTypeReferenceFinder
|
||||||
|
TaintState
|
|
@ -151,6 +151,14 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="sect2">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="TaintAllAccess"></a>Match on Fields</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Use all access paths, including field references, for sink/source variables.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<div class="titlepage"><div><div><h3 class="title">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<a name="TaintOutputFormat"></a>Output Format</h3></div></div></div>
|
<a name="TaintOutputFormat"></a>Output Format</h3></div></div></div>
|
||||||
|
@ -163,9 +171,9 @@
|
||||||
|
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<div class="titlepage"><div><div><h3 class="title">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<a name="TaintAllAccess"></a>Match on Fields</h3></div></div></div>
|
<a name="TaintEngine"></a>Query Engine</h3></div></div></div>
|
||||||
<p>
|
<p>
|
||||||
Use all access paths, including field references, for sink/source variables.
|
The engine to be used for formatting queries (e.g. ctadl, angr).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -43,22 +43,22 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
|
|
||||||
public static String ENGINE_NAME = "";
|
public static String ENGINE_NAME = "";
|
||||||
|
|
||||||
private Set<TaintLabel> sources = new HashSet<>();
|
protected Set<TaintLabel> sources = new HashSet<>();
|
||||||
private Set<TaintLabel> sinks = new HashSet<>();
|
protected Set<TaintLabel> sinks = new HashSet<>();
|
||||||
private Set<TaintLabel> gates = new HashSet<>();
|
protected Set<TaintLabel> gates = new HashSet<>();
|
||||||
|
|
||||||
// Sets used for highlighting.
|
// Sets used for highlighting.
|
||||||
private AddressSet taintAddressSet = new AddressSet();
|
protected AddressSet taintAddressSet = new AddressSet();
|
||||||
private Map<Address, Set<TaintQueryResult>> taintVarnodeMap = new HashMap<>();
|
protected Map<Address, Set<TaintQueryResult>> taintVarnodeMap = new HashMap<>();
|
||||||
|
|
||||||
private AddressSet deltaAddressSet = new AddressSet();
|
private AddressSet deltaAddressSet = new AddressSet();
|
||||||
private Map<Address, Set<TaintQueryResult>> deltaVarnodeMap = new HashMap<>();
|
private Map<Address, Set<TaintQueryResult>> deltaVarnodeMap = new HashMap<>();
|
||||||
|
|
||||||
private SarifSchema210 currentQueryData;
|
protected SarifSchema210 currentQueryData;
|
||||||
|
|
||||||
protected TaintOptions taintOptions;
|
protected TaintOptions taintOptions;
|
||||||
private TaintPlugin plugin;
|
protected TaintPlugin plugin;
|
||||||
|
protected boolean usesIndex = true;
|
||||||
private boolean cancellation;
|
private boolean cancellation;
|
||||||
|
|
||||||
private TaskType taskType;
|
private TaskType taskType;
|
||||||
|
@ -74,10 +74,14 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
public abstract void buildIndex(List<String> param_list, String engine_path, String facts_path,
|
public abstract void buildIndex(List<String> param_list, String engine_path, String facts_path,
|
||||||
String index_path);
|
String index_path);
|
||||||
|
|
||||||
|
protected abstract void writeHeader(PrintWriter writer);
|
||||||
|
|
||||||
protected abstract void writeRule(PrintWriter writer, TaintLabel mark, boolean isSource);
|
protected abstract void writeRule(PrintWriter writer, TaintLabel mark, boolean isSource);
|
||||||
|
|
||||||
protected abstract void writeGate(PrintWriter writer, TaintLabel mark);
|
protected abstract void writeGate(PrintWriter writer, TaintLabel mark);
|
||||||
|
|
||||||
|
protected abstract void writeFooter(PrintWriter writer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean wasCancelled() {
|
public boolean wasCancelled() {
|
||||||
return this.cancellation;
|
return this.cancellation;
|
||||||
|
@ -122,6 +126,17 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
return tlabel;
|
return tlabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TaintLabel getLabelForToken(MarkType type, ClangToken token) {
|
||||||
|
Set<TaintLabel> marks = getTaintLabels(type);
|
||||||
|
for (TaintLabel existingLabel : marks) {
|
||||||
|
if (token.equals(existingLabel.getToken())) {
|
||||||
|
return existingLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predicate indicating the presence of one or more sources in the source set;
|
* Predicate indicating the presence of one or more sources in the source set;
|
||||||
* this is used to determine state validity.
|
* this is used to determine state validity.
|
||||||
|
@ -173,7 +188,7 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
public boolean writeQueryFile(File queryTextFile) throws Exception {
|
public boolean writeQueryFile(File queryTextFile) throws Exception {
|
||||||
|
|
||||||
PrintWriter writer = new PrintWriter(queryTextFile);
|
PrintWriter writer = new PrintWriter(queryTextFile);
|
||||||
writer.println("#include \"pcode/taintquery.dl\"");
|
writeHeader(writer);
|
||||||
|
|
||||||
for (TaintLabel mark : sources) {
|
for (TaintLabel mark : sources) {
|
||||||
if (mark.isActive()) {
|
if (mark.isActive()) {
|
||||||
|
@ -181,8 +196,6 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.println("");
|
|
||||||
|
|
||||||
for (TaintLabel mark : sinks) {
|
for (TaintLabel mark : sinks) {
|
||||||
if (mark.isActive()) {
|
if (mark.isActive()) {
|
||||||
// CAREFUL note the "false"
|
// CAREFUL note the "false"
|
||||||
|
@ -191,7 +204,6 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gates.isEmpty()) {
|
if (!gates.isEmpty()) {
|
||||||
writer.println("");
|
|
||||||
for (TaintLabel mark : gates) {
|
for (TaintLabel mark : gates) {
|
||||||
if (mark.isActive()) {
|
if (mark.isActive()) {
|
||||||
writeGate(writer, mark);
|
writeGate(writer, mark);
|
||||||
|
@ -199,6 +211,8 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeFooter(writer);
|
||||||
|
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
@ -220,7 +234,7 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> param_list = new ArrayList<String>();
|
List<String> paramList = new ArrayList<String>();
|
||||||
File queryFile = null;
|
File queryFile = null;
|
||||||
taintOptions = plugin.getOptions();
|
taintOptions = plugin.getOptions();
|
||||||
|
|
||||||
|
@ -228,37 +242,39 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
|
|
||||||
// Make sure we can access and execute the engine binary.
|
// Make sure we can access and execute the engine binary.
|
||||||
Path engine = Path.of(taintOptions.getTaintEnginePath());
|
Path engine = Path.of(taintOptions.getTaintEnginePath());
|
||||||
File engine_file = engine.toFile();
|
File engineFile = engine.toFile();
|
||||||
|
|
||||||
if (!engine_file.exists() || !engine_file.canExecute()) {
|
if (!engineFile.exists()) {
|
||||||
plugin.consoleMessage("The " + getName() + " binary (" +
|
plugin.consoleMessage("The " + getName() + " binary (" +
|
||||||
engine_file.getCanonicalPath() + ") cannot be found or executed.");
|
engineFile.getCanonicalPath() + ") cannot be found or executed.");
|
||||||
engine_file = getFilePath(taintOptions.getTaintEnginePath(),
|
engineFile = getFilePath(taintOptions.getTaintEnginePath(),
|
||||||
"Select the " + getName() + " binary");
|
"Select the " + getName() + " binary");
|
||||||
if (engine_file == null) {
|
if (engineFile == null) {
|
||||||
plugin.consoleMessage(
|
plugin.consoleMessage(
|
||||||
"No " + getName() + " engine has been specified; exiting query function.");
|
"No " + getName() + " engine has been specified; exiting query function.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.consoleMessage("Using " + getName() + " binary: " + engine_file.toString());
|
plugin.consoleMessage("Using " + getName() + " binary: " + engineFile.toString());
|
||||||
|
|
||||||
Path index_directory = Path.of(taintOptions.getTaintOutputDirectory());
|
Path indexDirectory = Path.of(taintOptions.getTaintOutputDirectory());
|
||||||
Path indexDBPath = Path.of(taintOptions.getTaintOutputDirectory(),
|
Path indexDBPath = Path.of(taintOptions.getTaintOutputDirectory(),
|
||||||
taintOptions.getTaintIndexDBName(program.getName()));
|
taintOptions.getTaintIndexDBName(program.getName()));
|
||||||
|
|
||||||
File indexDBFile = indexDBPath.toFile();
|
File indexDBFile = indexDBPath.toFile();
|
||||||
plugin.consoleMessage("Attempting to use index: " + indexDBFile.toString());
|
|
||||||
|
if (usesIndex) {
|
||||||
if (!indexDBFile.exists()) {
|
plugin.consoleMessage("Attempting to use index: " + indexDBFile.toString());
|
||||||
plugin.consoleMessage("The index database for the binary named: " +
|
|
||||||
program.getName() + " does not exist; create it first.");
|
if (!indexDBFile.exists()) {
|
||||||
return false;
|
plugin.consoleMessage("The index database for the binary named: " +
|
||||||
|
program.getName() + " does not exist; create it first.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.consoleMessage("Using index database: " + indexDBFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.consoleMessage("Using index database: " + indexDBFile);
|
|
||||||
|
|
||||||
switch (queryType) {
|
switch (queryType) {
|
||||||
case SRCSINK:
|
case SRCSINK:
|
||||||
// Generate a datalog query file based on the selected source, sink, etc. data.
|
// Generate a datalog query file based on the selected source, sink, etc. data.
|
||||||
|
@ -280,7 +296,7 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
plugin.consoleMessage("Unknown query type.");
|
plugin.consoleMessage("Unknown query type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buildQuery(param_list, engine, indexDBFile, index_directory.toString());
|
buildQuery(paramList, engine, indexDBFile, indexDirectory.toString());
|
||||||
|
|
||||||
if (queryType.equals(QueryType.SRCSINK) || queryType.equals(QueryType.CUSTOM)) {
|
if (queryType.equals(QueryType.SRCSINK) || queryType.equals(QueryType.CUSTOM)) {
|
||||||
// The datalog that specifies the query.
|
// The datalog that specifies the query.
|
||||||
|
@ -294,12 +310,12 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
param_list.add(queryFile.getAbsolutePath());
|
paramList.add(queryFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg.info(this, "Query Param List: " + param_list.toString());
|
Msg.info(this, "Query Param List: " + paramList.toString());
|
||||||
try {
|
try {
|
||||||
ProcessBuilder pb = new ProcessBuilder(param_list);
|
ProcessBuilder pb = new ProcessBuilder(paramList);
|
||||||
pb.directory(new File(taintOptions.getTaintOutputDirectory()));
|
pb.directory(new File(taintOptions.getTaintOutputDirectory()));
|
||||||
pb.redirectError(Redirect.INHERIT);
|
pb.redirectError(Redirect.INHERIT);
|
||||||
Process p = pb.start();
|
Process p = pb.start();
|
||||||
|
@ -326,9 +342,10 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param prog current program if needed
|
||||||
* @param is the input stream (SARIF json) from the process builder that runs the engine
|
* @param is the input stream (SARIF json) from the process builder that runs the engine
|
||||||
*/
|
*/
|
||||||
private void readQueryResultsIntoDataFrame(Program program, InputStream is) {
|
protected void readQueryResultsIntoDataFrame(Program prog, InputStream is) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String line = null;
|
String line = null;
|
||||||
|
@ -533,6 +550,7 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
return plugin.getOptions();
|
return plugin.getOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return ENGINE_NAME;
|
return ENGINE_NAME;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class TaintLabel {
|
||||||
private String fname;
|
private String fname;
|
||||||
private HighFunction hfun;
|
private HighFunction hfun;
|
||||||
private HighVariable hvar;
|
private HighVariable hvar;
|
||||||
|
private Varnode vnode;
|
||||||
private boolean active;
|
private boolean active;
|
||||||
private String label;
|
private String label;
|
||||||
private boolean isGlobal = false;
|
private boolean isGlobal = false;
|
||||||
|
@ -36,8 +37,10 @@ public class TaintLabel {
|
||||||
// TODO: This is not a good identifier since it could change during re work!
|
// TODO: This is not a good identifier since it could change during re work!
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private ClangLine clangLine;
|
private ClangLine clangLine;
|
||||||
|
private int size = 0;
|
||||||
|
|
||||||
public TaintLabel(MarkType mtype, ClangToken token) throws PcodeException {
|
public TaintLabel(MarkType mtype, ClangToken token) throws PcodeException {
|
||||||
|
|
||||||
HighVariable highVar = token.getHighVariable();
|
HighVariable highVar = token.getHighVariable();
|
||||||
if (highVar == null) {
|
if (highVar == null) {
|
||||||
hfun = token.getClangFunction().getHighFunction();
|
hfun = token.getClangFunction().getHighFunction();
|
||||||
|
@ -50,25 +53,31 @@ public class TaintLabel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Varnode exactSpot = token.getVarnode();
|
this.vnode = token.getVarnode();
|
||||||
if (exactSpot != null) { // The user pointed at a particular usage, not just the vardecl
|
if (vnode != null) { // The user pointed at a particular usage, not just the vardecl
|
||||||
HighVariable high = exactSpot.getHigh();
|
HighVariable high = vnode.getHigh();
|
||||||
if (high instanceof HighLocal) {
|
if (high instanceof HighLocal) {
|
||||||
highVar = hfun.splitOutMergeGroup(high, exactSpot);
|
highVar = hfun.splitOutMergeGroup(high, vnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String fn = token instanceof ClangFuncNameToken ftoken ? ftoken.getText()
|
String fn = token instanceof ClangFuncNameToken ftoken ? ftoken.getText()
|
||||||
: hfun.getFunction().getName();
|
: hfun.getFunction().getName();
|
||||||
PcodeOp pcodeOp = token.getPcodeOp();
|
PcodeOp pcodeOp = token.getPcodeOp();
|
||||||
Address target = pcodeOp == null ? null : pcodeOp.getSeqnum().getTarget();
|
Address target = pcodeOp == null ? hfun.getFunction().getEntryPoint() : pcodeOp.getSeqnum().getTarget();
|
||||||
|
if (vnode == null && pcodeOp != null) {
|
||||||
|
vnode = pcodeOp.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
this.mtype = mtype;
|
this.mtype = mtype;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.fname = fn;
|
this.fname = fn;
|
||||||
this.hvar = highVar;
|
this.hvar = highVar;
|
||||||
this.active = true;
|
this.active = true;
|
||||||
this.addr = target;
|
this.addr = target;
|
||||||
|
if (hvar != null) {
|
||||||
|
size = hvar.getSize();
|
||||||
|
}
|
||||||
this.clangLine = token.getLineParent();
|
this.clangLine = token.getLineParent();
|
||||||
|
|
||||||
// Initial label is one of SOURCE, SINK, or GATE
|
// Initial label is one of SOURCE, SINK, or GATE
|
||||||
|
@ -145,6 +154,14 @@ public class TaintLabel {
|
||||||
public void activate() {
|
public void activate() {
|
||||||
active = true;
|
active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
public void toggle() {
|
public void toggle() {
|
||||||
active = !active;
|
active = !active;
|
||||||
|
@ -213,5 +230,12 @@ public class TaintLabel {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Address getVarnodeAddress() {
|
||||||
|
if (vnode != null) {
|
||||||
|
return vnode.getAddress();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public class TaintOptions {
|
||||||
/* The default name of the index database file. */
|
/* The default name of the index database file. */
|
||||||
public final static String OP_KEY_TAINT_DB = "Taint.Query.Index";
|
public final static String OP_KEY_TAINT_DB = "Taint.Query.Index";
|
||||||
|
|
||||||
|
public final static String OP_KEY_TAINT_QUERY_ENGINE = "Taint.Query Engine";
|
||||||
public final static String OP_KEY_TAINT_QUERY_DIRECTION = "Taint.Force Direction";
|
public final static String OP_KEY_TAINT_QUERY_DIRECTION = "Taint.Force Direction";
|
||||||
public final static String OP_KEY_TAINT_QUERY_OUTPUT_FORM = "Taint.Output Format";
|
public final static String OP_KEY_TAINT_QUERY_OUTPUT_FORM = "Taint.Output Format";
|
||||||
/* Color used in the decompiler to highlight taint. */
|
/* Color used in the decompiler to highlight taint. */
|
||||||
|
@ -68,13 +69,14 @@ public class TaintOptions {
|
||||||
new GColor("color.bg.listing.highlighter.default");
|
new GColor("color.bg.listing.highlighter.default");
|
||||||
private final static Highlighter TAINT_HIGHLIGHT_STYLE_DEFAULT = Highlighter.DEFAULT;
|
private final static Highlighter TAINT_HIGHLIGHT_STYLE_DEFAULT = Highlighter.DEFAULT;
|
||||||
|
|
||||||
private String taintEngine;
|
private String taintEnginePath;
|
||||||
private String taintFactsDir;
|
private String taintFactsDir;
|
||||||
private String taintOutputDir;
|
private String taintOutputDir;
|
||||||
|
|
||||||
private String taintQuery;
|
private String taintQuery;
|
||||||
private String taintDB;
|
private String taintDB;
|
||||||
|
|
||||||
|
private String taintQueryEngine;
|
||||||
private TaintDirection taintQueryDirection;
|
private TaintDirection taintQueryDirection;
|
||||||
private TaintFormat taintQueryOutputForm;
|
private TaintFormat taintQueryOutputForm;
|
||||||
|
|
||||||
|
@ -106,7 +108,7 @@ public class TaintOptions {
|
||||||
public TaintOptions(TaintProvider provider) {
|
public TaintOptions(TaintProvider provider) {
|
||||||
taintProvider = provider;
|
taintProvider = provider;
|
||||||
|
|
||||||
taintEngine = DEFAULT_TAINT_ENGINE_PATH;
|
taintEnginePath = DEFAULT_TAINT_ENGINE_PATH;
|
||||||
taintFactsDir = DEFAULT_TAINT_FACTS_DIR;
|
taintFactsDir = DEFAULT_TAINT_FACTS_DIR;
|
||||||
taintOutputDir = DEFAULT_TAINT_OUTPUT_DIR;
|
taintOutputDir = DEFAULT_TAINT_OUTPUT_DIR;
|
||||||
taintQuery = DEFAULT_TAINT_QUERY;
|
taintQuery = DEFAULT_TAINT_QUERY;
|
||||||
|
@ -129,7 +131,11 @@ public class TaintOptions {
|
||||||
|
|
||||||
opt.registerOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, TaintFormat.ALL,
|
opt.registerOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, TaintFormat.ALL,
|
||||||
new HelpLocation(HelpTopics.DECOMPILER, "Taint Output Type"),
|
new HelpLocation(HelpTopics.DECOMPILER, "Taint Output Type"),
|
||||||
"The type of Source-Sink query output (e.g., sarif, summary, text");
|
"The type of Source-Sink query output (e.g., sarif, summary, text)");
|
||||||
|
|
||||||
|
opt.registerOption(OP_KEY_TAINT_QUERY_ENGINE, "",
|
||||||
|
new HelpLocation(HelpTopics.DECOMPILER, "Taint Query Engine"),
|
||||||
|
"The query engine (e.g., angr, ctadl)");
|
||||||
|
|
||||||
opt.registerOption(OP_KEY_TAINT_ENGINE_PATH, DEFAULT_TAINT_ENGINE_PATH,
|
opt.registerOption(OP_KEY_TAINT_ENGINE_PATH, DEFAULT_TAINT_ENGINE_PATH,
|
||||||
new HelpLocation(HelpTopics.DECOMPILER, "Taint Engine Directory"),
|
new HelpLocation(HelpTopics.DECOMPILER, "Taint Engine Directory"),
|
||||||
|
@ -176,7 +182,17 @@ public class TaintOptions {
|
||||||
*/
|
*/
|
||||||
public void grabFromToolAndProgram(Plugin ownerPlugin, ToolOptions opt, Program program) {
|
public void grabFromToolAndProgram(Plugin ownerPlugin, ToolOptions opt, Program program) {
|
||||||
|
|
||||||
taintEngine = opt.getString(OP_KEY_TAINT_ENGINE_PATH, "");
|
String engine = opt.getString(OP_KEY_TAINT_QUERY_ENGINE, "");
|
||||||
|
if (!engine.equals(taintQueryEngine)) {
|
||||||
|
TaintPlugin plugin = (TaintPlugin) ownerPlugin;
|
||||||
|
TaintState state = TaintState.newInstance(plugin, engine);
|
||||||
|
if (state != null) {
|
||||||
|
plugin.setTaintState(state);
|
||||||
|
taintQueryEngine = engine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taintEnginePath = opt.getString(OP_KEY_TAINT_ENGINE_PATH, "");
|
||||||
taintFactsDir = opt.getString(OP_KEY_TAINT_FACTS_DIR, "");
|
taintFactsDir = opt.getString(OP_KEY_TAINT_FACTS_DIR, "");
|
||||||
taintQuery = opt.getString(OP_KEY_TAINT_QUERY, "");
|
taintQuery = opt.getString(OP_KEY_TAINT_QUERY, "");
|
||||||
// taintQueryResultsFile = opt.getString(OP_KEY_TAINT_QUERY_RESULTS, "");
|
// taintQueryResultsFile = opt.getString(OP_KEY_TAINT_QUERY_RESULTS, "");
|
||||||
|
@ -196,8 +212,12 @@ public class TaintOptions {
|
||||||
return taintQueryOutputForm;
|
return taintQueryOutputForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTaintEngineType() {
|
||||||
|
return taintQueryEngine;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTaintEnginePath() {
|
public String getTaintEnginePath() {
|
||||||
return taintEngine;
|
return taintEnginePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTaintFactsDirectory() {
|
public String getTaintFactsDirectory() {
|
||||||
|
@ -244,6 +264,11 @@ public class TaintOptions {
|
||||||
return taintUseAllAccess;
|
return taintUseAllAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTaintQueryEngine(String engine) {
|
||||||
|
this.taintQueryEngine = engine;
|
||||||
|
taintProvider.setOption(OP_KEY_TAINT_QUERY_ENGINE, engine);
|
||||||
|
}
|
||||||
|
|
||||||
public void setTaintOutputForm(TaintFormat form) {
|
public void setTaintOutputForm(TaintFormat form) {
|
||||||
this.taintQueryOutputForm = form;
|
this.taintQueryOutputForm = form;
|
||||||
taintProvider.setOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, form.getOptionString());
|
taintProvider.setOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, form.getOptionString());
|
||||||
|
|
|
@ -111,8 +111,11 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum TaintFormat {
|
public static enum TaintFormat {
|
||||||
ALL("all", "sarif+all"), GRAPHS("graphs", "sarif+graphs"),
|
ALL("all", "sarif+all"),
|
||||||
INSTS("insts", "sarif+instructions"), PATHS("paths", "sarif");
|
GRAPHS("graphs", "sarif+graphs"),
|
||||||
|
INSTS("insts", "sarif+instructions"),
|
||||||
|
PATHS("paths", "sarif"),
|
||||||
|
NONE("none", "none");
|
||||||
|
|
||||||
private String label;
|
private String label;
|
||||||
private String optionString;
|
private String optionString;
|
||||||
|
@ -175,7 +178,6 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
|
||||||
|
|
||||||
public TaintPlugin(PluginTool tool) {
|
public TaintPlugin(PluginTool tool) {
|
||||||
super(tool);
|
super(tool);
|
||||||
state = TaintState.newInstance(this);
|
|
||||||
taintProvider = new TaintProvider(this);
|
taintProvider = new TaintProvider(this);
|
||||||
taintDecompMarginProvider = new TaintDecompilerMarginProvider(this);
|
taintDecompMarginProvider = new TaintDecompilerMarginProvider(this);
|
||||||
createActions();
|
createActions();
|
||||||
|
@ -353,9 +355,11 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
|
||||||
GhidraState ghidraState = new GhidraState(tool, null, currentProgram,
|
GhidraState ghidraState = new GhidraState(tool, null, currentProgram,
|
||||||
currentLocation, currentHighlight, currentHighlight);
|
currentLocation, currentHighlight, currentHighlight);
|
||||||
GhidraScript exportScript = state.getExportScript(consoleService, false);
|
GhidraScript exportScript = state.getExportScript(consoleService, false);
|
||||||
RunPCodeExportScriptTask export_task =
|
if (exportScript != null) {
|
||||||
new RunPCodeExportScriptTask(tool, exportScript, ghidraState, consoleService);
|
RunPCodeExportScriptTask export_task =
|
||||||
tool.execute(export_task);
|
new RunPCodeExportScriptTask(tool, exportScript, ghidraState, consoleService);
|
||||||
|
tool.execute(export_task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -433,6 +437,10 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTaintState(TaintState state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
public TaintProvider getProvider() {
|
public TaintProvider getProvider() {
|
||||||
return taintProvider;
|
return taintProvider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,6 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
private DecompilerProvider decompilerProvider;
|
private DecompilerProvider decompilerProvider;
|
||||||
private Navigatable navigatable;
|
private Navigatable navigatable;
|
||||||
|
|
||||||
private TaintState state;
|
|
||||||
|
|
||||||
private DecompilerHighlighter highlighter;
|
private DecompilerHighlighter highlighter;
|
||||||
|
|
||||||
private TaintCTokenHighlighterPalette highlightPalette;
|
private TaintCTokenHighlighterPalette highlightPalette;
|
||||||
|
@ -84,7 +82,6 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
super(plugin.getTool(), "TaintProvider", plugin.getName(), DecompilerActionContext.class);
|
super(plugin.getTool(), "TaintProvider", plugin.getName(), DecompilerActionContext.class);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.taintOptions = new TaintOptions(this);
|
this.taintOptions = new TaintOptions(this);
|
||||||
this.state = plugin.getTaintState();
|
|
||||||
this.cachedHighlightsByToken = new HashMap<>();
|
this.cachedHighlightsByToken = new HashMap<>();
|
||||||
this.cachedHighlightByAddress = new HashMap<>();
|
this.cachedHighlightByAddress = new HashMap<>();
|
||||||
this.highlightPalette = new TaintCTokenHighlighterPalette(256);
|
this.highlightPalette = new TaintCTokenHighlighterPalette(256);
|
||||||
|
@ -108,34 +105,37 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
|
|
||||||
// These actions are only available in the drop-down window
|
// These actions are only available in the drop-down window
|
||||||
|
|
||||||
TaintSourceAction taintSourceAction = new TaintSourceAction(plugin, state);
|
TaintSourceAction taintSourceAction = new TaintSourceAction(plugin);
|
||||||
setGroupInfo(taintSourceAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintSourceAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
TaintSourceBySymbolAction taintSourceBySymbolAction =
|
TaintSourceBySymbolAction taintSourceBySymbolAction =
|
||||||
new TaintSourceBySymbolAction(plugin, state);
|
new TaintSourceBySymbolAction(plugin);
|
||||||
setGroupInfo(taintSourceBySymbolAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintSourceBySymbolAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
TaintSinkAction taintSinkAction = new TaintSinkAction(plugin, state);
|
TaintSinkAction taintSinkAction = new TaintSinkAction(plugin);
|
||||||
setGroupInfo(taintSinkAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintSinkAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
TaintSinkBySymbolAction taintSinkBySymbolAction =
|
TaintSinkBySymbolAction taintSinkBySymbolAction =
|
||||||
new TaintSinkBySymbolAction(plugin, state);
|
new TaintSinkBySymbolAction(plugin);
|
||||||
setGroupInfo(taintSinkBySymbolAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintSinkBySymbolAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
TaintGateAction taintGateAction = new TaintGateAction(plugin, state);
|
TaintGateAction taintGateAction = new TaintGateAction(plugin);
|
||||||
setGroupInfo(taintGateAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintGateAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
TaintClearAction taintClearAction = new TaintClearAction(plugin, state);
|
TaintClearAction taintClearAction = new TaintClearAction(plugin);
|
||||||
setGroupInfo(taintClearAction, variableGroup, subGroupPosition++);
|
setGroupInfo(taintClearAction, variableGroup, subGroupPosition++);
|
||||||
|
|
||||||
// These actions have an icon and a drop-down menu option in the decompiler window.
|
TaintSetSizeAction taintSizeAction = new TaintSetSizeAction(plugin);
|
||||||
TaintQueryAction taintQueryAction = new TaintQueryAction(plugin, state);
|
setGroupInfo(taintSizeAction, variableGroup, subGroupPosition++);
|
||||||
TaintQueryDefaultAction taintQueryDefaultAction =
|
|
||||||
new TaintQueryDefaultAction(plugin, state);
|
|
||||||
TaintQueryCustomAction taintQueryCustomAction = new TaintQueryCustomAction(plugin, state);
|
|
||||||
TaintLoadAction taintLoadAction = new TaintLoadAction(plugin, state);
|
|
||||||
|
|
||||||
TaintSliceTreeAction taintSliceTreeAction = new TaintSliceTreeAction(plugin, state);
|
// These actions have an icon and a drop-down menu option in the decompiler window.
|
||||||
|
TaintQueryAction taintQueryAction = new TaintQueryAction(plugin);
|
||||||
|
TaintQueryDefaultAction taintQueryDefaultAction =
|
||||||
|
new TaintQueryDefaultAction(plugin);
|
||||||
|
TaintQueryCustomAction taintQueryCustomAction = new TaintQueryCustomAction(plugin);
|
||||||
|
TaintLoadAction taintLoadAction = new TaintLoadAction(plugin);
|
||||||
|
|
||||||
|
TaintSliceTreeAction taintSliceTreeAction = new TaintSliceTreeAction(plugin);
|
||||||
|
|
||||||
DockingAction taintLabelTableAction = new DockingAction("TaintShowLabels", TaintPlugin.HELP_LOCATION) {
|
DockingAction taintLabelTableAction = new DockingAction("TaintShowLabels", TaintPlugin.HELP_LOCATION) {
|
||||||
|
|
||||||
|
@ -153,7 +153,8 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
return state.hasMarks();
|
TaintState state = plugin.getTaintState();
|
||||||
|
return state == null ? false : state.hasMarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -175,6 +176,7 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
provider.addLocalAction(taintQueryCustomAction);
|
provider.addLocalAction(taintQueryCustomAction);
|
||||||
provider.addLocalAction(taintLoadAction);
|
provider.addLocalAction(taintLoadAction);
|
||||||
provider.addLocalAction(taintClearAction);
|
provider.addLocalAction(taintClearAction);
|
||||||
|
provider.addLocalAction(taintSizeAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,6 +255,10 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
* @param taskType subtract previous result
|
* @param taskType subtract previous result
|
||||||
*/
|
*/
|
||||||
public void setTaint(TaskType taskType) {
|
public void setTaint(TaskType taskType) {
|
||||||
|
TaintState state = plugin.getTaintState();
|
||||||
|
if (state == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (navigatable == null) {
|
if (navigatable == null) {
|
||||||
navigatable = tool.getService(CodeViewerService.class).getNavigatable();
|
navigatable = tool.getService(CodeViewerService.class).getNavigatable();
|
||||||
}
|
}
|
||||||
|
@ -284,6 +290,11 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matchOn(ClangToken token) {
|
public boolean matchOn(ClangToken token) {
|
||||||
|
|
||||||
|
TaintState state = plugin.getTaintState();
|
||||||
|
if (state == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (token instanceof ClangBreak ||
|
if (token instanceof ClangBreak ||
|
||||||
token instanceof ClangTypeToken ||
|
token instanceof ClangTypeToken ||
|
||||||
|
@ -372,7 +383,7 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
|
||||||
Msg.info(this,
|
Msg.info(this,
|
||||||
"TaintProvider: clearTaint() - state clearTaint() and highligher apply highlights.");
|
"TaintProvider: clearTaint() - state clearTaint() and highligher apply highlights.");
|
||||||
matchCount = 0;
|
matchCount = 0;
|
||||||
state.clearTaint();
|
plugin.getTaintState().clearTaint();
|
||||||
highlighter.clearHighlights();
|
highlighter.clearHighlights();
|
||||||
cachedHighlightByAddress.clear();
|
cachedHighlightByAddress.clear();
|
||||||
cachedHighlightsByToken.clear();
|
cachedHighlightsByToken.clear();
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
package ghidra.app.plugin.core.decompiler.taint;
|
package ghidra.app.plugin.core.decompiler.taint;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import com.contrastsecurity.sarif.SarifSchema210;
|
import com.contrastsecurity.sarif.SarifSchema210;
|
||||||
|
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.ctadl.TaintStateCTADL;
|
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
@ -31,12 +31,18 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
import ghidra.program.model.symbol.SymbolTable;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface for the methods that collect desired taint information from the decompiler window and store them
|
* The interface for the methods that collect desired taint information from the decompiler window and store them
|
||||||
* for construction of queries and indexing.
|
* for construction of queries and indexing.
|
||||||
|
* <p>
|
||||||
|
* NOTE: ALL TaintState CLASSES MUST END IN "TaintState". If not,
|
||||||
|
* the ClassSearcher will not find them.
|
||||||
*/
|
*/
|
||||||
public interface TaintState {
|
public interface TaintState extends ExtensionPoint {
|
||||||
|
|
||||||
public enum MarkType {
|
public enum MarkType {
|
||||||
SOURCE, SINK, GATE
|
SOURCE, SINK, GATE
|
||||||
|
@ -50,10 +56,31 @@ public interface TaintState {
|
||||||
SET_TAINT, SET_DELTA, APPLY_DELTA
|
SET_TAINT, SET_DELTA, APPLY_DELTA
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaintState newInstance(TaintPlugin plugin) {
|
public static TaintState newInstance(TaintPlugin plugin, String type) {
|
||||||
return new TaintStateCTADL(plugin);
|
List<Class<? extends TaintState>> list = ClassSearcher.getClasses(TaintState.class)
|
||||||
|
.stream()
|
||||||
|
.toList();
|
||||||
|
Class<?>[] constructorArgumentTypes = {TaintPlugin.class};
|
||||||
|
Object[] args = new Object[1];
|
||||||
|
args[0] = plugin;
|
||||||
|
for (Class<? extends TaintState> clazz : list) {
|
||||||
|
if (clazz.getName().toLowerCase().contains(type)) {
|
||||||
|
try {
|
||||||
|
Constructor<?> constructor = clazz.getConstructor(constructorArgumentTypes);
|
||||||
|
Object obj = constructor.newInstance(plugin);
|
||||||
|
return TaintState.class.cast(obj);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException("Unable to instantiate TaintState");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Msg.error(plugin, "No match for engine = "+type);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a Source-Sink query on the index database.
|
* Perform a Source-Sink query on the index database.
|
||||||
*
|
*
|
||||||
|
@ -108,6 +135,10 @@ public interface TaintState {
|
||||||
|
|
||||||
public GhidraScript getExportScript(ConsoleService console, boolean perFunction);
|
public GhidraScript getExportScript(ConsoleService console, boolean perFunction);
|
||||||
|
|
||||||
|
public void setTaskType(TaskType taskType);
|
||||||
|
|
||||||
|
public TaintLabel getLabelForToken(MarkType type, ClangToken token);
|
||||||
|
|
||||||
public static String hvarName(ClangToken token) {
|
public static String hvarName(ClangToken token) {
|
||||||
HighVariable hv = token.getHighVariable();
|
HighVariable hv = token.getHighVariable();
|
||||||
HighFunction hf =
|
HighFunction hf =
|
||||||
|
@ -159,6 +190,4 @@ public interface TaintState {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTaskType(TaskType taskType);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import javax.swing.Icon;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.*;
|
import ghidra.app.plugin.core.decompiler.taint.*;
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin.TaintFormat;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.sarif.SarifTaintGraphRunHandler;
|
import ghidra.app.plugin.core.decompiler.taint.sarif.SarifTaintGraphRunHandler;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
@ -37,7 +38,6 @@ import sarif.SarifService;
|
||||||
public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAction {
|
public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
protected TaintPlugin plugin;
|
protected TaintPlugin plugin;
|
||||||
protected TaintState state;
|
|
||||||
protected String desc;
|
protected String desc;
|
||||||
protected String title;
|
protected String title;
|
||||||
|
|
||||||
|
@ -45,14 +45,13 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
|
||||||
protected Icon executeTaintQueryIcon;
|
protected Icon executeTaintQueryIcon;
|
||||||
protected QueryType queryType;
|
protected QueryType queryType;
|
||||||
|
|
||||||
public TaintAbstractQueryAction(TaintPlugin plugin, TaintState state, String desc, String title, String cmd) {
|
public TaintAbstractQueryAction(TaintPlugin plugin, String desc, String title, String cmd) {
|
||||||
super(cmd);
|
super(cmd);
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "Taint"+desc));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "Taint"+desc));
|
||||||
setMenuBarData(new MenuData(new String[] { "Source-Sink", getName() }));
|
setMenuBarData(new MenuData(new String[] { "Source-Sink", getName() }));
|
||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.state = state;
|
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +61,9 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +75,7 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
|
||||||
Task defaultQueryTask = new Task(title, true, true, true, true) {
|
Task defaultQueryTask = new Task(title, true, true, true, true) {
|
||||||
@Override
|
@Override
|
||||||
public void run(TaskMonitor monitor) {
|
public void run(TaskMonitor monitor) {
|
||||||
|
TaintState state = plugin.getTaintState();
|
||||||
state.setCancellation(false);
|
state.setCancellation(false);
|
||||||
monitor.initialize(program.getFunctionManager().getFunctionCount());
|
monitor.initialize(program.getFunctionManager().getFunctionCount());
|
||||||
state.queryIndex(program, tool, queryType);
|
state.queryIndex(program, tool, queryType);
|
||||||
|
@ -87,10 +90,14 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
|
||||||
// We still get a progress bar and option to cancel.
|
// We still get a progress bar and option to cancel.
|
||||||
tool.execute(defaultQueryTask);
|
tool.execute(defaultQueryTask);
|
||||||
|
|
||||||
|
TaintState state = plugin.getTaintState();
|
||||||
if (!state.wasCancelled()) {
|
if (!state.wasCancelled()) {
|
||||||
SarifService sarifService = plugin.getSarifService();
|
TaintFormat format = state.getOptions().getTaintOutputForm();
|
||||||
sarifService.getController().setDefaultGraphHander(SarifTaintGraphRunHandler.class);
|
if (!format.equals(TaintFormat.NONE)) {
|
||||||
sarifService.showSarif(desc, state.getData());
|
SarifService sarifService = plugin.getSarifService();
|
||||||
|
sarifService.getController().setDefaultGraphHander(SarifTaintGraphRunHandler.class);
|
||||||
|
sarifService.showSarif(desc, state.getData());
|
||||||
|
}
|
||||||
|
|
||||||
plugin.consoleMessage("executing query...");
|
plugin.consoleMessage("executing query...");
|
||||||
TaintProvider provider = plugin.getProvider();
|
TaintProvider provider = plugin.getProvider();
|
||||||
|
|
|
@ -23,7 +23,6 @@ import docking.action.MenuData;
|
||||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,25 +33,26 @@ import ghidra.util.HelpLocation;
|
||||||
public class TaintClearAction extends TaintAbstractDecompilerAction {
|
public class TaintClearAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private TaintState state;
|
|
||||||
|
|
||||||
public TaintClearAction(TaintPlugin plugin, TaintState state) {
|
public TaintClearAction(TaintPlugin plugin) {
|
||||||
super("Clear Markers");
|
super("Clear Markers");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintClear"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintClear"));
|
||||||
setPopupMenuData(new MenuData(new String[] { "Taint", "Clear" }, "Decompile"));
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Clear" }, "Decompile"));
|
||||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
|
setKeyBindingData(new KeyBindingData(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
||||||
state.clearMarkers();
|
plugin.getTaintState().clearMarkers();
|
||||||
plugin.clearIcons();
|
plugin.clearIcons();
|
||||||
plugin.clearTaint();
|
plugin.clearTaint();
|
||||||
plugin.consoleMessage("taint cleared");
|
plugin.consoleMessage("taint cleared");
|
||||||
|
|
|
@ -25,7 +25,6 @@ import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
@ -43,7 +42,7 @@ public class TaintGateAction extends TaintAbstractDecompilerAction {
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private MarkType mtype;
|
private MarkType mtype;
|
||||||
|
|
||||||
public TaintGateAction(TaintPlugin plugin, TaintState state) {
|
public TaintGateAction(TaintPlugin plugin) {
|
||||||
super("Mark Gate");
|
super("Mark Gate");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintGate"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintGate"));
|
||||||
setPopupMenuData(new MenuData(new String[] { "Taint", "Gate" }, "Decompile"));
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Gate" }, "Decompile"));
|
||||||
|
@ -58,6 +57,10 @@ public class TaintGateAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Function function = context.getFunction();
|
Function function = context.getFunction();
|
||||||
if (function == null || function instanceof UndefinedFunction) {
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -27,7 +27,6 @@ import generic.theme.GIcon;
|
||||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
@ -47,12 +46,11 @@ import ghidra.util.HelpLocation;
|
||||||
public class TaintLoadAction extends TaintAbstractDecompilerAction {
|
public class TaintLoadAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private TaintState state;
|
|
||||||
|
|
||||||
private static String loadSarifFileIconString = "icon.fsbrowser.file.extension.obj";
|
private static String loadSarifFileIconString = "icon.fsbrowser.file.extension.obj";
|
||||||
private static Icon loadSarifFileIcon = new GIcon(loadSarifFileIconString);
|
private static Icon loadSarifFileIcon = new GIcon(loadSarifFileIconString);
|
||||||
|
|
||||||
public TaintLoadAction(TaintPlugin plugin, TaintState state) {
|
public TaintLoadAction(TaintPlugin plugin) {
|
||||||
super("Load SARIF file");
|
super("Load SARIF file");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintLoadSarif"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintLoadSarif"));
|
||||||
|
|
||||||
|
@ -60,7 +58,6 @@ public class TaintLoadAction extends TaintAbstractDecompilerAction {
|
||||||
setToolBarData(new ToolBarData(loadSarifFileIcon));
|
setToolBarData(new ToolBarData(loadSarifFileIcon));
|
||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,6 +75,7 @@ public class TaintLoadAction extends TaintAbstractDecompilerAction {
|
||||||
// Pop a file dialog to select the SARIF file.
|
// Pop a file dialog to select the SARIF file.
|
||||||
|
|
||||||
// need to pop-up a file chooser dialog.
|
// need to pop-up a file chooser dialog.
|
||||||
|
TaintState state = plugin.getTaintState();
|
||||||
GhidraFileChooser file_chooser = new GhidraFileChooser(tool.getToolFrame());
|
GhidraFileChooser file_chooser = new GhidraFileChooser(tool.getToolFrame());
|
||||||
file_chooser.setCurrentDirectory(new File(state.getOptions().getTaintEnginePath()));
|
file_chooser.setCurrentDirectory(new File(state.getOptions().getTaintEnginePath()));
|
||||||
file_chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
file_chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
||||||
|
|
|
@ -27,8 +27,8 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
||||||
|
|
||||||
public class TaintQueryAction extends TaintAbstractQueryAction {
|
public class TaintQueryAction extends TaintAbstractQueryAction {
|
||||||
|
|
||||||
public TaintQueryAction(TaintPlugin plugin, TaintState state) {
|
public TaintQueryAction(TaintPlugin plugin) {
|
||||||
super(plugin, state, "Query", "Source-Sink Taint Query", "Run taint query");
|
super(plugin, "Query", "Source-Sink Taint Query", "Run taint query");
|
||||||
executeTaintQueryIconString = "icon.graph.default.display.program.graph";
|
executeTaintQueryIconString = "icon.graph.default.display.program.graph";
|
||||||
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
|
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
|
||||||
queryType = QueryType.SRCSINK;
|
queryType = QueryType.SRCSINK;
|
||||||
|
@ -39,7 +39,8 @@ public class TaintQueryAction extends TaintAbstractQueryAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
return state.isValid();
|
TaintState state = plugin.getTaintState();
|
||||||
|
return state == null ? false : state.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
||||||
|
|
||||||
public class TaintQueryCustomAction extends TaintAbstractQueryAction {
|
public class TaintQueryCustomAction extends TaintAbstractQueryAction {
|
||||||
|
|
||||||
public TaintQueryCustomAction(TaintPlugin plugin, TaintState state) {
|
public TaintQueryCustomAction(TaintPlugin plugin) {
|
||||||
super(plugin, state, "CustomQuery", "Custom Taint Query", "Run custom taint query");
|
super(plugin, "CustomQuery", "Custom Taint Query", "Run custom taint query");
|
||||||
queryType = QueryType.CUSTOM;
|
queryType = QueryType.CUSTOM;
|
||||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
|
setKeyBindingData(new KeyBindingData(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
||||||
|
|
||||||
public class TaintQueryDefaultAction extends TaintAbstractQueryAction {
|
public class TaintQueryDefaultAction extends TaintAbstractQueryAction {
|
||||||
|
|
||||||
public TaintQueryDefaultAction(TaintPlugin plugin, TaintState state) {
|
public TaintQueryDefaultAction(TaintPlugin plugin) {
|
||||||
super(plugin, state, "DefaultQuery", "Default Taint Query", "Run default taint query");
|
super(plugin, "DefaultQuery", "Default Taint Query", "Run default taint query");
|
||||||
executeTaintQueryIconString = "icon.version.tracking.markup.status.conflict";
|
executeTaintQueryIconString = "icon.version.tracking.markup.status.conflict";
|
||||||
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
|
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
|
||||||
queryType = QueryType.DEFAULT;
|
queryType = QueryType.DEFAULT;
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* 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 ghidra.app.plugin.core.decompiler.taint.actions;
|
||||||
|
|
||||||
|
import docking.action.MenuData;
|
||||||
|
import docking.widgets.dialogs.InputDialog;
|
||||||
|
import ghidra.app.decompiler.*;
|
||||||
|
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.TaintLabel;
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.util.UndefinedFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered by right-click on a token in the decompiler window.
|
||||||
|
* <p>
|
||||||
|
* Action triggered from a specific token in the decompiler window to mark a variable as a
|
||||||
|
* source or sink and generate the requisite query. Legal tokens to select include:
|
||||||
|
* <ul><li>
|
||||||
|
* An input parameter,
|
||||||
|
* </li><li>
|
||||||
|
* A stack variable,
|
||||||
|
* </li><li>
|
||||||
|
* A variable associated with a register, or
|
||||||
|
* </li><li>
|
||||||
|
* A "dynamic" variable.
|
||||||
|
* </li></ul>
|
||||||
|
*/
|
||||||
|
public class TaintSetSizeAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
|
private TaintPlugin plugin;
|
||||||
|
|
||||||
|
public TaintSetSizeAction(TaintPlugin plugin) {
|
||||||
|
super("Set length");
|
||||||
|
// Taint Menu -> Source sub item.
|
||||||
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Set length" }, "Decompile"));
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function function = context.getFunction();
|
||||||
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangToken tokenAtCursor = context.getTokenAtCursor();
|
||||||
|
if (tokenAtCursor == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tokenAtCursor instanceof ClangFieldToken) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (tokenAtCursor.Parent() instanceof ClangReturnType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tokenAtCursor instanceof ClangFuncNameToken) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!tokenAtCursor.isVariableRef()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
||||||
|
TaintLabel label = plugin.getTaintState().getLabelForToken(MarkType.SOURCE, context.getTokenAtCursor());
|
||||||
|
if (label != null) {
|
||||||
|
InputDialog dialog = new InputDialog("Update length", "Length", Integer.toHexString(label.getSize()));
|
||||||
|
plugin.getTool().showDialog(dialog);
|
||||||
|
if (dialog.isCanceled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String val = dialog.getValue();
|
||||||
|
label.setSize(Integer.parseInt(val, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,6 @@ import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
@ -40,7 +39,7 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction {
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private MarkType mtype;
|
private MarkType mtype;
|
||||||
|
|
||||||
public TaintSinkAction(TaintPlugin plugin, TaintState state) {
|
public TaintSinkAction(TaintPlugin plugin) {
|
||||||
super("Mark Sink");
|
super("Mark Sink");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSink"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSink"));
|
||||||
setPopupMenuData(new MenuData(new String[] { "Taint", "Sink" }, "Decompile"));
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Sink" }, "Decompile"));
|
||||||
|
@ -59,6 +58,10 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Function function = context.getFunction();
|
Function function = context.getFunction();
|
||||||
if (function == null || function instanceof UndefinedFunction) {
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,7 +21,6 @@ import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
@ -36,7 +35,7 @@ public class TaintSinkBySymbolAction extends TaintAbstractDecompilerAction {
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private MarkType mtype;
|
private MarkType mtype;
|
||||||
|
|
||||||
public TaintSinkBySymbolAction(TaintPlugin plugin, TaintState state) {
|
public TaintSinkBySymbolAction(TaintPlugin plugin) {
|
||||||
super("Mark Sink (Symbol)");
|
super("Mark Sink (Symbol)");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSinkSymbol"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSinkSymbol"));
|
||||||
setPopupMenuData(new MenuData(new String[] { "Taint", "Sink (Symbol)" }, "Decompile"));
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Sink (Symbol)" }, "Decompile"));
|
||||||
|
@ -54,6 +53,10 @@ public class TaintSinkBySymbolAction extends TaintAbstractDecompilerAction {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Function function = context.getFunction();
|
Function function = context.getFunction();
|
||||||
if (function == null || function instanceof UndefinedFunction) {
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,7 +20,6 @@ import ghidra.app.decompiler.ClangToken;
|
||||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.pcode.HighVariable;
|
import ghidra.program.model.pcode.HighVariable;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
@ -45,7 +44,7 @@ public class TaintSliceTreeAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
|
|
||||||
public TaintSliceTreeAction(TaintPlugin plugin, TaintState state) {
|
public TaintSliceTreeAction(TaintPlugin plugin) {
|
||||||
super("Show Slice Tree");
|
super("Show Slice Tree");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSliceTree"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSliceTree"));
|
||||||
setPopupMenuData(new MenuData(new String[] { "Taint", "Slice Tree" }, "Decompile"));
|
setPopupMenuData(new MenuData(new String[] { "Taint", "Slice Tree" }, "Decompile"));
|
||||||
|
@ -56,6 +55,10 @@ public class TaintSliceTreeAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
@ -49,7 +48,7 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction {
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private MarkType mtype;
|
private MarkType mtype;
|
||||||
|
|
||||||
public TaintSourceAction(TaintPlugin plugin, TaintState state) {
|
public TaintSourceAction(TaintPlugin plugin) {
|
||||||
super("Mark Source");
|
super("Mark Source");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSource"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSource"));
|
||||||
// Taint Menu -> Source sub item.
|
// Taint Menu -> Source sub item.
|
||||||
|
@ -66,6 +65,10 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Function function = context.getFunction();
|
Function function = context.getFunction();
|
||||||
if (function == null || function instanceof UndefinedFunction) {
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,7 +21,6 @@ import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState;
|
||||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
@ -46,7 +45,7 @@ public class TaintSourceBySymbolAction extends TaintAbstractDecompilerAction {
|
||||||
private TaintPlugin plugin;
|
private TaintPlugin plugin;
|
||||||
private MarkType mtype;
|
private MarkType mtype;
|
||||||
|
|
||||||
public TaintSourceBySymbolAction(TaintPlugin plugin, TaintState state) {
|
public TaintSourceBySymbolAction(TaintPlugin plugin) {
|
||||||
super("Mark Source (Symbol)");
|
super("Mark Source (Symbol)");
|
||||||
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSourceSymbol"));
|
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "TaintSourceSymbol"));
|
||||||
// Taint Menu -> Source sub item.
|
// Taint Menu -> Source sub item.
|
||||||
|
@ -61,6 +60,10 @@ public class TaintSourceBySymbolAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
|
||||||
|
if (plugin.getTaintState() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Function function = context.getFunction();
|
Function function = context.getFunction();
|
||||||
if (function == null || function instanceof UndefinedFunction) {
|
if (function == null || function instanceof UndefinedFunction) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -35,9 +35,9 @@ import ghidra.program.model.pcode.HighVariable;
|
||||||
* Container for all the decompiler elements the users "selects" via the menu.
|
* Container for all the decompiler elements the users "selects" via the menu.
|
||||||
* This data is used to build queries.
|
* This data is used to build queries.
|
||||||
*/
|
*/
|
||||||
public class TaintStateCTADL extends AbstractTaintState {
|
public class CTADLTaintState extends AbstractTaintState {
|
||||||
|
|
||||||
public TaintStateCTADL(TaintPlugin plugin) {
|
public CTADLTaintState(TaintPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin);
|
||||||
ENGINE_NAME = "ctadl";
|
ENGINE_NAME = "ctadl";
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,12 @@ public class TaintStateCTADL extends AbstractTaintState {
|
||||||
return perFunction ? "ExportPCodeForSingleFunction.java" : "ExportPCodeForCTADL.java";
|
return perFunction ? "ExportPCodeForSingleFunction.java" : "ExportPCodeForCTADL.java";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeHeader(PrintWriter writer) {
|
||||||
|
writer.println("#include \"pcode/taintquery.dl\"");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: This is the only method used now for Sources and Sinks.
|
* NOTE: This is the only method used now for Sources and Sinks.
|
||||||
*/
|
*/
|
||||||
|
@ -178,6 +184,7 @@ public class TaintStateCTADL extends AbstractTaintState {
|
||||||
Boolean allAccess = taintOptions.getTaintUseAllAccess();
|
Boolean allAccess = taintOptions.getTaintUseAllAccess();
|
||||||
String method = "TaintSanitizeAll";
|
String method = "TaintSanitizeAll";
|
||||||
Address addr = mark.getAddress();
|
Address addr = mark.getAddress();
|
||||||
|
// TODO: verify setting entryPoint as addr doesn't break things
|
||||||
|
|
||||||
if (mark.getFunctionName() == null) {
|
if (mark.getFunctionName() == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -199,4 +206,9 @@ public class TaintStateCTADL extends AbstractTaintState {
|
||||||
writer.println("\tVertex(vn, p).");
|
writer.println("\tVertex(vn, p).");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeFooter(PrintWriter writer) {
|
||||||
|
// Nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue