mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-wkshp: post-review
GP-wkshp: minor mod GP-wkshp: post-rebase GP-wkshp: rebase GP-5290: first pass GP-5290: fixes for abstract state; set sizeGP-5290: basically workingGP-5290: state updates in motionGP-5290: some cleanupGP-5290: mid-reviewGP-5290: lose the interfaceGP-wkshp: add opsGP-wkshp: trimGP-wkshp: first pass on exportGP-wkshp: error in writeRule?GP-wkshp: working version of source exportGP-wkshp: more tweaksGP-wkshp: unnecessary
This commit is contained in:
parent
738fe8bc4f
commit
0fac9cc491
14 changed files with 319 additions and 96 deletions
|
@ -202,7 +202,6 @@ public class AngrTaintState extends AbstractTaintState {
|
||||||
return NumericUtilities.convertBytesToString(bytes);
|
return NumericUtilities.convertBytesToString(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void readQueryResultsIntoDataFrame(Program program, InputStream is) {
|
protected void readQueryResultsIntoDataFrame(Program program, InputStream is) {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
//Decompile the function at the cursor and its callees, then output facts files corresponding to the pcodes
|
||||||
|
//@category PCode
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.contrastsecurity.sarif.LogicalLocation;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.decompiler.taint.*;
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.app.services.GraphDisplayBroker;
|
||||||
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.graph.*;
|
||||||
|
import ghidra.graph.jung.JungDirectedGraph;
|
||||||
|
import ghidra.service.graph.*;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.exception.GraphException;
|
||||||
|
import sarif.SarifUtils;
|
||||||
|
|
||||||
|
|
||||||
|
public class ExportSourceSetScript extends GhidraScript {
|
||||||
|
|
||||||
|
private TaintPlugin plugin;
|
||||||
|
private TaintProvider provider;
|
||||||
|
private TaintOptions options;
|
||||||
|
Map<String, AttributedVertex> nodeMap = new HashMap<String, AttributedVertex>();
|
||||||
|
private Map<String, String> mnemonics = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
|
||||||
|
PluginTool tool = state.getTool();
|
||||||
|
if (tool == null) {
|
||||||
|
println("Script is not running in GUI");
|
||||||
|
}
|
||||||
|
plugin = (TaintPlugin) tool.getService(TaintService.class);
|
||||||
|
provider = plugin.getProvider();
|
||||||
|
options = plugin.getOptions();
|
||||||
|
String facts = options.getTaintFactsDirectory();
|
||||||
|
File mnFile = new File(facts+"/PCODE_MNEMONIC.facts");
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(mnFile));
|
||||||
|
String line = null;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String[] split = line.split("\t");
|
||||||
|
mnemonics.put(split[0], split[1]);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
AttributedGraph g = handle();
|
||||||
|
showGraph(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GDirectedGraph<AttributedVertex, GEdge<AttributedVertex>> parse() {
|
||||||
|
GDirectedGraph<AttributedVertex, GEdge<AttributedVertex>> graph = new JungDirectedGraph<>();
|
||||||
|
Map<String, Set<String>> edgeMap = SarifUtils.getEdgeMap();
|
||||||
|
for (Set<String> ids : edgeMap.values()) {
|
||||||
|
for (String id : ids) {
|
||||||
|
String srcId = SarifUtils.getEdgeSource(id);
|
||||||
|
String dstId = SarifUtils.getEdgeDest(id);
|
||||||
|
String mnemonic = mnemonics.get(id.split("/")[2]);
|
||||||
|
if (mnemonic != null && !mnemonic.equals("INDIRECT")) {
|
||||||
|
AttributedVertex s = addVertex(srcId, id);
|
||||||
|
AttributedVertex d = addVertex(dstId, id);
|
||||||
|
graph.addVertex(s);
|
||||||
|
graph.addVertex(d);
|
||||||
|
graph.addEdge(new DefaultGEdge<>(s,d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AttributedVertex addVertex(String id, String edgeId) {
|
||||||
|
LogicalLocation[] locs = SarifUtils.getNodeLocs(id);
|
||||||
|
String label = locs.length == 0 ? id : locs[0].getFullyQualifiedName();
|
||||||
|
AttributedVertex v = new AttributedVertex(label);
|
||||||
|
v.setAttribute("id", id);
|
||||||
|
v.setAttribute("edge", edgeId);
|
||||||
|
nodeMap.put(id, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributedGraph handle() {
|
||||||
|
GDirectedGraph<AttributedVertex, GEdge<AttributedVertex>> g = parse();
|
||||||
|
Collection<AttributedVertex> vertices = g.getVertices();
|
||||||
|
Map<AttributedVertex, AttributedVertex> toFrom = new HashMap<>();
|
||||||
|
Collection<GEdge<AttributedVertex>> edges = g.getEdges();
|
||||||
|
for (GEdge<AttributedVertex> edge : edges) {
|
||||||
|
AttributedVertex end = edge.getEnd();
|
||||||
|
AttributedVertex start = edge.getStart();
|
||||||
|
toFrom.put(end, start);
|
||||||
|
}
|
||||||
|
Set<AttributedVertex> sources = new HashSet<>();
|
||||||
|
Set<AttributedVertex> nonSources = new HashSet<>();
|
||||||
|
Set<Set<AttributedVertex>> components = GraphAlgorithms.getStronglyConnectedComponents(g);
|
||||||
|
for (Set<AttributedVertex> c : components) {
|
||||||
|
Iterator<AttributedVertex> iterator = c.iterator();
|
||||||
|
boolean isSource = true;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
AttributedVertex to = iterator.next();
|
||||||
|
AttributedVertex from = toFrom.get(to);
|
||||||
|
if (from != null && !c.contains(from)) {
|
||||||
|
isSource = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isSource) {
|
||||||
|
sources.addAll(c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nonSources.addAll(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (AttributedVertex v : vertices) {
|
||||||
|
if (!nonSources.contains(v)) {
|
||||||
|
AttributedVertex from = toFrom.get(v);
|
||||||
|
if (from == null) {
|
||||||
|
sources.add(v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nonSources.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> srcList = new ArrayList<>();
|
||||||
|
AttributedGraph graph = new AttributedGraph("BOB", new EmptyGraphType());
|
||||||
|
for (GEdge<AttributedVertex> edge : edges) {
|
||||||
|
AttributedVertex end = edge.getEnd();
|
||||||
|
AttributedVertex start = edge.getStart();
|
||||||
|
String edgeId = end.getAttribute("edge");
|
||||||
|
String edgeDesc = edgeId.split("/")[2];
|
||||||
|
String mnemonic = mnemonics.get(edgeDesc);
|
||||||
|
|
||||||
|
AttributedEdge ae = graph.addEdge(start, end);
|
||||||
|
ae.setAttribute("desc", edgeId);
|
||||||
|
ae.setAttribute("mnemonic", mnemonic);
|
||||||
|
start.setAttribute("src", sources.contains(start) ? "TRUE" : "FALSE");
|
||||||
|
graph.addVertex(start);
|
||||||
|
end.setAttribute("src", sources.contains(end) ? "TRUE" : "FALSE");
|
||||||
|
graph.addVertex(end);
|
||||||
|
if (sources.contains(start) && !start.getName().contains(":const:")) {
|
||||||
|
srcList.add(edgeDesc+"::"+start.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String outfile = options.getTaintOutputDirectory();
|
||||||
|
File srcFile = new File(outfile+"/SOURCES");
|
||||||
|
try {
|
||||||
|
BufferedWriter srcWriter = new BufferedWriter(new FileWriter(srcFile));
|
||||||
|
for (String src : srcList) {
|
||||||
|
srcWriter.write(src+"\n");
|
||||||
|
}
|
||||||
|
srcWriter.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showGraph(AttributedGraph graph) {
|
||||||
|
try {
|
||||||
|
PluginTool tool = plugin.getTool();
|
||||||
|
GraphDisplayBroker service = tool.getService(GraphDisplayBroker.class);
|
||||||
|
GraphDisplay display = service.getDefaultGraphDisplay(false, null);
|
||||||
|
GraphDisplayOptions graphOptions = new GraphDisplayOptions(new EmptyGraphType());
|
||||||
|
graphOptions.setMaxNodeCount(10000);
|
||||||
|
display.setGraph(graph, graphOptions, graph.getDescription(), false, null);
|
||||||
|
}
|
||||||
|
catch (GraphException | CancelledException e) {
|
||||||
|
Msg.error(this, "showGraph failed " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ public abstract class AbstractTaintState implements TaintState {
|
||||||
protected boolean usesIndex = true;
|
protected boolean usesIndex = true;
|
||||||
private boolean cancellation;
|
private boolean cancellation;
|
||||||
|
|
||||||
private TaskType taskType;
|
private TaskType taskType = TaskType.SET_TAINT;
|
||||||
|
|
||||||
public AbstractTaintState(TaintPlugin plugin) {
|
public AbstractTaintState(TaintPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
|
|
@ -106,12 +106,12 @@ public class CreateTargetIndexTask extends Task {
|
||||||
|
|
||||||
// This will pull all the Taint options default set in the plugin. These could also be set in Ghidra configuration files.
|
// This will pull all the Taint options default set in the plugin. These could also be set in Ghidra configuration files.
|
||||||
String enginePathName = options.getString(TaintOptions.OP_KEY_TAINT_ENGINE_PATH,
|
String enginePathName = options.getString(TaintOptions.OP_KEY_TAINT_ENGINE_PATH,
|
||||||
"/home/user/workspace/engine_binary");
|
"/home/user/workspace/engine_binary").trim();
|
||||||
String factsDirectory =
|
String factsDirectory =
|
||||||
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export");
|
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export").trim();
|
||||||
String indexDirectory =
|
String indexDirectory =
|
||||||
options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output");
|
options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output").trim();
|
||||||
String indexDBName = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db");
|
String indexDBName = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db").trim();
|
||||||
|
|
||||||
// builds a custom db name with the string of the binary embedded in it for better identification.
|
// builds a custom db name with the string of the binary embedded in it for better identification.
|
||||||
indexDBName = TaintOptions.makeDBName(indexDBName, program.getName());
|
indexDBName = TaintOptions.makeDBName(indexDBName, program.getName());
|
||||||
|
|
|
@ -48,10 +48,10 @@ public class PurgeIndexTask extends Task {
|
||||||
|
|
||||||
// This will pull all the Taint options default set in the plugin. These could also be set in Ghidra configuration files.
|
// This will pull all the Taint options default set in the plugin. These could also be set in Ghidra configuration files.
|
||||||
String facts_directory =
|
String facts_directory =
|
||||||
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export");
|
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export").trim();
|
||||||
String index_directory =
|
String index_directory =
|
||||||
options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output");
|
options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output").trim();
|
||||||
String index_db_name = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db");
|
String index_db_name = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db").trim();
|
||||||
|
|
||||||
// builds a custom db name with the string of the binary embedded in it for better identification.
|
// builds a custom db name with the string of the binary embedded in it for better identification.
|
||||||
index_db_name = TaintOptions.makeDBName(index_db_name, program.getName());
|
index_db_name = TaintOptions.makeDBName(index_db_name, program.getName());
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class RunPCodeExportScriptTask extends Task {
|
||||||
|
|
||||||
ToolOptions options = tool.getOptions("Decompiler");
|
ToolOptions options = tool.getOptions("Decompiler");
|
||||||
String facts_directory =
|
String facts_directory =
|
||||||
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export");
|
options.getString(TaintOptions.OP_KEY_TAINT_FACTS_DIR, "/tmp/export").trim();
|
||||||
Path facts_path = Path.of(facts_directory);
|
Path facts_path = Path.of(facts_directory);
|
||||||
if (!facts_path.toFile().exists() || !facts_path.toFile().isDirectory()) {
|
if (!facts_path.toFile().exists() || !facts_path.toFile().isDirectory()) {
|
||||||
Msg.info(this, "Facts Path: " + facts_path.toString() + " does not exists.");
|
Msg.info(this, "Facts Path: " + facts_path.toString() + " does not exists.");
|
||||||
|
|
|
@ -182,7 +182,7 @@ public class TaintOptions {
|
||||||
*/
|
*/
|
||||||
public void grabFromToolAndProgram(Plugin ownerPlugin, ToolOptions opt, Program program) {
|
public void grabFromToolAndProgram(Plugin ownerPlugin, ToolOptions opt, Program program) {
|
||||||
|
|
||||||
String engine = opt.getString(OP_KEY_TAINT_QUERY_ENGINE, "");
|
String engine = opt.getString(OP_KEY_TAINT_QUERY_ENGINE, "").trim();
|
||||||
if (!engine.equals(taintQueryEngine)) {
|
if (!engine.equals(taintQueryEngine)) {
|
||||||
TaintPlugin plugin = (TaintPlugin) ownerPlugin;
|
TaintPlugin plugin = (TaintPlugin) ownerPlugin;
|
||||||
TaintState state = TaintState.newInstance(plugin, engine);
|
TaintState state = TaintState.newInstance(plugin, engine);
|
||||||
|
|
|
@ -23,9 +23,9 @@ import docking.action.MenuData;
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
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.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (tokenAtCursor instanceof ClangFieldToken) {
|
if (tokenAtCursor instanceof ClangFieldToken) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
if (tokenAtCursor.Parent() instanceof ClangReturnType) {
|
if (tokenAtCursor.Parent() instanceof ClangReturnType) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,6 +80,9 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction {
|
||||||
if (tokenAtCursor instanceof ClangFuncNameToken) {
|
if (tokenAtCursor instanceof ClangFuncNameToken) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (tokenAtCursor instanceof ClangOpToken) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!tokenAtCursor.isVariableRef()) {
|
if (!tokenAtCursor.isVariableRef()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +91,26 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
||||||
mark(context.getTokenAtCursor());
|
ClangToken tokenAtCursor = context.getTokenAtCursor();
|
||||||
|
if (tokenAtCursor instanceof ClangOpToken) {
|
||||||
|
markOp(tokenAtCursor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mark(tokenAtCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markOp(ClangToken tokenAtCursor) {
|
||||||
|
ClangLine line = tokenAtCursor.getLineParent();
|
||||||
|
for (ClangToken token : line.getAllTokens()) {
|
||||||
|
if (token instanceof ClangVariableToken varToken) {
|
||||||
|
if (varToken.isVariableRef()) {
|
||||||
|
Varnode varnode = varToken.getVarnode();
|
||||||
|
if (varnode != null && !varnode.isConstant()) {
|
||||||
|
mark(varToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class TaintSinkBySymbolAction extends TaintAbstractDecompilerAction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (tokenAtCursor instanceof ClangFieldToken) {
|
if (tokenAtCursor instanceof ClangFieldToken) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
if (tokenAtCursor.Parent() instanceof ClangReturnType) {
|
if (tokenAtCursor.Parent() instanceof ClangReturnType) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -22,9 +22,9 @@ import docking.action.MenuData;
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
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.MarkType;
|
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.UndefinedFunction;
|
import ghidra.util.UndefinedFunction;
|
||||||
|
|
||||||
|
@ -87,6 +87,9 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction {
|
||||||
if (tokenAtCursor instanceof ClangFuncNameToken) {
|
if (tokenAtCursor instanceof ClangFuncNameToken) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (tokenAtCursor instanceof ClangOpToken) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!tokenAtCursor.isVariableRef()) {
|
if (!tokenAtCursor.isVariableRef()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +98,26 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
||||||
mark(context.getTokenAtCursor());
|
ClangToken tokenAtCursor = context.getTokenAtCursor();
|
||||||
|
if (tokenAtCursor instanceof ClangOpToken) {
|
||||||
|
markOp(tokenAtCursor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mark(tokenAtCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markOp(ClangToken tokenAtCursor) {
|
||||||
|
ClangLine line = tokenAtCursor.getLineParent();
|
||||||
|
for (ClangToken token : line.getAllTokens()) {
|
||||||
|
if (token instanceof ClangVariableToken varToken) {
|
||||||
|
if (varToken.isVariableRef()) {
|
||||||
|
Varnode varnode = varToken.getVarnode();
|
||||||
|
if (!varnode.isConstant()) {
|
||||||
|
mark(varToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import ghidra.app.plugin.core.osgi.BundleHost;
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.pcode.HighParam;
|
|
||||||
import ghidra.program.model.pcode.HighVariable;
|
import ghidra.program.model.pcode.HighVariable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,18 +145,11 @@ public class CTADLTaintState extends AbstractTaintState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.println(method + "Vertex(\"" + mark.getLabel() + "\", vn, p) :-");
|
writer.println(method + "Vertex(\"" + mark.getLabel() + "\", vn, p) :-");
|
||||||
if (!mark.isGlobal()) {
|
writer.println("\t((HFUNC_NAME(m, \"" + mark.getFunctionName() + "\"),");
|
||||||
writer.println("\tHFUNC_NAME(m, \"" + mark.getFunctionName() + "\"),");
|
writer.println("\tCVar_InFunction(vn, m)) ; CVar_isGlobal(vn)),");
|
||||||
writer.println("\tCVar_InFunction(vn, m),");
|
|
||||||
}
|
|
||||||
if (addr != null && addr.getOffset() != 0 && !mark.bySymbol()) {
|
if (addr != null && addr.getOffset() != 0 && !mark.bySymbol()) {
|
||||||
if (!TaintState.isActualParam(token) && !(hv instanceof HighParam)) {
|
writer.println("\t(PCODE_INPUT(i, _, vn) ; PCODE_OUTPUT(i, vn)),");
|
||||||
writer.println("\tVNODE_PC_ADDRESS(vn, " + addr.getOffset() + "),");
|
writer.println("\tPCODE_TARGET(i, " + addr.getOffset() + "),");
|
||||||
}
|
|
||||||
else { // NB: we still want a local match
|
|
||||||
writer.println("\t(PCODE_INPUT(i, _, vn) ; PCODE_OUTPUT(i, vn)),");
|
|
||||||
writer.println("\tPCODE_TARGET(i, " + addr.getOffset() + "),");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (mark.bySymbol()) {
|
if (mark.bySymbol()) {
|
||||||
writer.println("\tSYMBOL_NAME(sym, \"" + token.getText() + "\"),");
|
writer.println("\tSYMBOL_NAME(sym, \"" + token.getText() + "\"),");
|
||||||
|
|
|
@ -242,17 +242,19 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||||
Address faddr = (Address) r.get("entry");
|
Address faddr = (Address) r.get("entry");
|
||||||
String fqname = (String) r.get("location");
|
String fqname = (String) r.get("location");
|
||||||
Set<TaintQueryResult> vset = getSet(map, faddr);
|
Set<TaintQueryResult> vset = getSet(map, faddr);
|
||||||
String edgeId = SarifUtils.getEdge(fqname);
|
Set<String> edgeIds = SarifUtils.getEdgeSet(fqname);
|
||||||
if (edgeId != null) {
|
if (edgeIds != null) {
|
||||||
String srcId = SarifUtils.getEdgeSource(edgeId);
|
for (String edgeId : edgeIds) {
|
||||||
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
String srcId = SarifUtils.getEdgeSource(edgeId);
|
||||||
for (LogicalLocation lloc : srcNodes) {
|
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
||||||
vset.add(new TaintQueryResult(r, run, lloc));
|
for (LogicalLocation lloc : srcNodes) {
|
||||||
}
|
vset.add(new TaintQueryResult(r, run, lloc));
|
||||||
String dstId = SarifUtils.getEdgeDest(edgeId);
|
}
|
||||||
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
String dstId = SarifUtils.getEdgeDest(edgeId);
|
||||||
for (LogicalLocation lloc : dstNodes) {
|
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
||||||
vset.add(new TaintQueryResult(r, run, lloc));
|
for (LogicalLocation lloc : dstNodes) {
|
||||||
|
vset.add(new TaintQueryResult(r, run, lloc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,19 +340,21 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||||
Address faddr = (Address) r.get("entry");
|
Address faddr = (Address) r.get("entry");
|
||||||
String fqname = (String) r.get("location");
|
String fqname = (String) r.get("location");
|
||||||
Set<TaintQueryResult> vset = getSet(map, faddr);
|
Set<TaintQueryResult> vset = getSet(map, faddr);
|
||||||
String edgeId = SarifUtils.getEdge(fqname);
|
Set<String> edgeIds = SarifUtils.getEdgeSet(fqname);
|
||||||
if (edgeId != null) {
|
if (edgeIds != null) {
|
||||||
String srcId = SarifUtils.getEdgeSource(edgeId);
|
for (String edgeId : edgeIds) {
|
||||||
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
String srcId = SarifUtils.getEdgeSource(edgeId);
|
||||||
for (LogicalLocation lloc : srcNodes) {
|
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
||||||
TaintQueryResult res = new TaintQueryResult(r, run, lloc);
|
for (LogicalLocation lloc : srcNodes) {
|
||||||
vset.remove(res);
|
TaintQueryResult res = new TaintQueryResult(r, run, lloc);
|
||||||
}
|
vset.remove(res);
|
||||||
String dstId = SarifUtils.getEdgeDest(edgeId);
|
}
|
||||||
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
String dstId = SarifUtils.getEdgeDest(edgeId);
|
||||||
for (LogicalLocation lloc : dstNodes) {
|
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
||||||
TaintQueryResult res = new TaintQueryResult(r, run, lloc);
|
for (LogicalLocation lloc : dstNodes) {
|
||||||
vset.remove(res);
|
TaintQueryResult res = new TaintQueryResult(r, run, lloc);
|
||||||
|
vset.remove(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
map.put(faddr, vset);
|
map.put(faddr, vset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,17 +226,19 @@ public class DecompilerTaintTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Address faddr = (Address) result.get("entry");
|
Address faddr = (Address) result.get("entry");
|
||||||
String fqname = (String) result.get("location");
|
String fqname = (String) result.get("location");
|
||||||
Set<TaintQueryResult> vset = getSet(map, faddr);
|
Set<TaintQueryResult> vset = getSet(map, faddr);
|
||||||
String edgeId = SarifUtils.getEdge(fqname);
|
Set<String> edgeIds = SarifUtils.getEdgeSet(fqname);
|
||||||
if (edgeId != null) {
|
if (edgeIds != null) {
|
||||||
String srcId = SarifUtils.getEdgeSource(edgeId);
|
for (String edgeId : edgeIds) {
|
||||||
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
String srcId = SarifUtils.getEdgeSource(edgeId);
|
||||||
for (LogicalLocation lloc : srcNodes) {
|
LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId);
|
||||||
vset.add(new TaintQueryResult(result, run, lloc));
|
for (LogicalLocation lloc : srcNodes) {
|
||||||
}
|
vset.add(new TaintQueryResult(result, run, lloc));
|
||||||
String dstId = SarifUtils.getEdgeDest(edgeId);
|
}
|
||||||
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
String dstId = SarifUtils.getEdgeDest(edgeId);
|
||||||
for (LogicalLocation lloc : dstNodes) {
|
LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId);
|
||||||
vset.add(new TaintQueryResult(result, run, lloc));
|
for (LogicalLocation lloc : dstNodes) {
|
||||||
|
vset.add(new TaintQueryResult(result, run, lloc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,43 +16,17 @@
|
||||||
package sarif;
|
package sarif;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.bouncycastle.util.encoders.Base64;
|
import org.bouncycastle.util.encoders.Base64;
|
||||||
|
|
||||||
import com.contrastsecurity.sarif.Artifact;
|
import com.contrastsecurity.sarif.*;
|
||||||
import com.contrastsecurity.sarif.ArtifactContent;
|
|
||||||
import com.contrastsecurity.sarif.ArtifactLocation;
|
|
||||||
import com.contrastsecurity.sarif.Edge;
|
|
||||||
import com.contrastsecurity.sarif.Graph;
|
|
||||||
import com.contrastsecurity.sarif.Location;
|
|
||||||
import com.contrastsecurity.sarif.LogicalLocation;
|
|
||||||
import com.contrastsecurity.sarif.Node;
|
|
||||||
import com.contrastsecurity.sarif.PhysicalLocation;
|
|
||||||
import com.contrastsecurity.sarif.ReportingDescriptor;
|
|
||||||
import com.contrastsecurity.sarif.ReportingDescriptorReference;
|
|
||||||
import com.contrastsecurity.sarif.Run;
|
|
||||||
import com.contrastsecurity.sarif.ToolComponent;
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import ghidra.framework.store.LockException;
|
import ghidra.framework.store.LockException;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.address.AddressFormatException;
|
|
||||||
import ghidra.program.model.address.AddressOverflowException;
|
|
||||||
import ghidra.program.model.address.AddressRange;
|
|
||||||
import ghidra.program.model.address.AddressRangeImpl;
|
|
||||||
import ghidra.program.model.address.AddressRangeIterator;
|
|
||||||
import ghidra.program.model.address.AddressSet;
|
|
||||||
import ghidra.program.model.address.AddressSetView;
|
|
||||||
import ghidra.program.model.address.AddressSpace;
|
|
||||||
import ghidra.program.model.address.OverlayAddressSpace;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
|
@ -77,7 +51,7 @@ public class SarifUtils {
|
||||||
private static Map<String, LogicalLocation[]> nodeLocs = new HashMap<>();
|
private static Map<String, LogicalLocation[]> nodeLocs = new HashMap<>();
|
||||||
private static Map<String, String> edgeSrcs = new HashMap<>();
|
private static Map<String, String> edgeSrcs = new HashMap<>();
|
||||||
private static Map<String, String> edgeDsts = new HashMap<>();
|
private static Map<String, String> edgeDsts = new HashMap<>();
|
||||||
private static Map<String, String> edgeDescs = new HashMap<>();
|
private static Map<String, Set<String>> edgeDescs = new HashMap<>();
|
||||||
private static boolean populating = false;
|
private static boolean populating = false;
|
||||||
|
|
||||||
public static JsonArray setLocations(Address min, Address max) {
|
public static JsonArray setLocations(Address min, Address max) {
|
||||||
|
@ -403,7 +377,12 @@ public class SarifUtils {
|
||||||
String desc = e.getLabel().getText();
|
String desc = e.getLabel().getText();
|
||||||
edgeSrcs.put(id, src);
|
edgeSrcs.put(id, src);
|
||||||
edgeDsts.put(id, dst);
|
edgeDsts.put(id, dst);
|
||||||
edgeDescs.put(desc, id);
|
Set<String> set = edgeDescs.get(desc);
|
||||||
|
if (set == null) {
|
||||||
|
set = new HashSet<>();
|
||||||
|
edgeDescs.put(desc, set);
|
||||||
|
}
|
||||||
|
set.add(id);
|
||||||
}
|
}
|
||||||
Set<Node> nodes = rg.getNodes();
|
Set<Node> nodes = rg.getNodes();
|
||||||
for (Node n : nodes) {
|
for (Node n : nodes) {
|
||||||
|
@ -428,7 +407,7 @@ public class SarifUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getEdge(String fqname) {
|
public static Set<String> getEdgeSet(String fqname) {
|
||||||
return edgeDescs.get(fqname);
|
return edgeDescs.get(fqname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,4 +435,8 @@ public class SarifUtils {
|
||||||
populating = b;
|
populating = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, Set<String>> getEdgeMap() {
|
||||||
|
return edgeDescs;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue