From 0fac9cc4918ef38c7b7603be78e4215e329af467 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Mon, 10 Feb 2025 13:15:57 -0500 Subject: [PATCH] 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 --- .../core/debug/taint/AngrTaintState.java | 1 - .../ghidra_scripts/ExportSourceSetScript.java | 197 ++++++++++++++++++ .../decompiler/taint/AbstractTaintState.java | 2 +- .../taint/CreateTargetIndexTask.java | 8 +- .../core/decompiler/taint/PurgeIndexTask.java | 6 +- .../taint/RunPCodeExportScriptTask.java | 2 +- .../core/decompiler/taint/TaintOptions.java | 2 +- .../taint/actions/TaintSinkAction.java | 29 ++- .../actions/TaintSinkBySymbolAction.java | 2 +- .../taint/actions/TaintSourceAction.java | 27 ++- .../taint/ctadl/CTADLTaintState.java | 16 +- .../taint/sarif/SarifTaintResultHandler.java | 52 ++--- .../decompiler/taint/DecompilerTaintTest.java | 24 ++- .../Sarif/src/main/java/sarif/SarifUtils.java | 47 ++--- 14 files changed, 319 insertions(+), 96 deletions(-) create mode 100644 Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportSourceSetScript.java diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/taint/AngrTaintState.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/taint/AngrTaintState.java index 748003b4f8..b45ba7c534 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/taint/AngrTaintState.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/taint/AngrTaintState.java @@ -202,7 +202,6 @@ public class AngrTaintState extends AbstractTaintState { return NumericUtilities.convertBytesToString(bytes); } - @Override protected void readQueryResultsIntoDataFrame(Program program, InputStream is) { diff --git a/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportSourceSetScript.java b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportSourceSetScript.java new file mode 100644 index 0000000000..5e9857dbad --- /dev/null +++ b/Ghidra/Features/DecompilerDependent/ghidra_scripts/ExportSourceSetScript.java @@ -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 nodeMap = new HashMap(); + private Map 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> parse() { + GDirectedGraph> graph = new JungDirectedGraph<>(); + Map> edgeMap = SarifUtils.getEdgeMap(); + for (Set 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> g = parse(); + Collection vertices = g.getVertices(); + Map toFrom = new HashMap<>(); + Collection> edges = g.getEdges(); + for (GEdge edge : edges) { + AttributedVertex end = edge.getEnd(); + AttributedVertex start = edge.getStart(); + toFrom.put(end, start); + } + Set sources = new HashSet<>(); + Set nonSources = new HashSet<>(); + Set> components = GraphAlgorithms.getStronglyConnectedComponents(g); + for (Set c : components) { + Iterator 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 srcList = new ArrayList<>(); + AttributedGraph graph = new AttributedGraph("BOB", new EmptyGraphType()); + for (GEdge 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()); + } + } + +} diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java index 21586b4170..205540c03d 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java @@ -61,7 +61,7 @@ public abstract class AbstractTaintState implements TaintState { protected boolean usesIndex = true; private boolean cancellation; - private TaskType taskType; + private TaskType taskType = TaskType.SET_TAINT; public AbstractTaintState(TaintPlugin plugin) { this.plugin = plugin; diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/CreateTargetIndexTask.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/CreateTargetIndexTask.java index 0a5d58867e..5bd7462462 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/CreateTargetIndexTask.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/CreateTargetIndexTask.java @@ -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. String enginePathName = options.getString(TaintOptions.OP_KEY_TAINT_ENGINE_PATH, - "/home/user/workspace/engine_binary"); + "/home/user/workspace/engine_binary").trim(); 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 = - options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output"); - String indexDBName = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db"); + options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output").trim(); + 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. indexDBName = TaintOptions.makeDBName(indexDBName, program.getName()); diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/PurgeIndexTask.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/PurgeIndexTask.java index ebeb8f4b3e..4531cf96bb 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/PurgeIndexTask.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/PurgeIndexTask.java @@ -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. 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 = - options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output"); - String index_db_name = options.getString(TaintOptions.OP_KEY_TAINT_DB, "ctadlir.db"); + options.getString(TaintOptions.OP_KEY_TAINT_OUTPUT_DIR, "/tmp/output").trim(); + 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. index_db_name = TaintOptions.makeDBName(index_db_name, program.getName()); diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/RunPCodeExportScriptTask.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/RunPCodeExportScriptTask.java index dd1136fd09..62f90f1ad7 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/RunPCodeExportScriptTask.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/RunPCodeExportScriptTask.java @@ -56,7 +56,7 @@ public class RunPCodeExportScriptTask extends Task { ToolOptions options = tool.getOptions("Decompiler"); 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); if (!facts_path.toFile().exists() || !facts_path.toFile().isDirectory()) { Msg.info(this, "Facts Path: " + facts_path.toString() + " does not exists."); diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java index d249163c0b..93b15ec487 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java @@ -182,7 +182,7 @@ public class TaintOptions { */ 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)) { TaintPlugin plugin = (TaintPlugin) ownerPlugin; TaintState state = TaintState.newInstance(plugin, engine); diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkAction.java index d4836f4d16..a630f767d1 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkAction.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkAction.java @@ -23,9 +23,9 @@ import docking.action.MenuData; import ghidra.app.decompiler.*; import ghidra.app.plugin.core.decompile.DecompilerActionContext; 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.program.model.listing.Function; +import ghidra.program.model.pcode.Varnode; import ghidra.util.HelpLocation; import ghidra.util.UndefinedFunction; @@ -72,7 +72,7 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction { return false; } if (tokenAtCursor instanceof ClangFieldToken) { - return false; + return true; } if (tokenAtCursor.Parent() instanceof ClangReturnType) { return false; @@ -80,6 +80,9 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction { if (tokenAtCursor instanceof ClangFuncNameToken) { return true; } + if (tokenAtCursor instanceof ClangOpToken) { + return true; + } if (!tokenAtCursor.isVariableRef()) { return false; } @@ -88,6 +91,26 @@ public class TaintSinkAction extends TaintAbstractDecompilerAction { @Override 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); + } + } + } + } } } diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkBySymbolAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkBySymbolAction.java index d743631b8a..0756e40647 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkBySymbolAction.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSinkBySymbolAction.java @@ -67,7 +67,7 @@ public class TaintSinkBySymbolAction extends TaintAbstractDecompilerAction { return false; } if (tokenAtCursor instanceof ClangFieldToken) { - return false; + return true; } if (tokenAtCursor.Parent() instanceof ClangReturnType) { return false; diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSourceAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSourceAction.java index 792a61edb5..1fe67d17d9 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSourceAction.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintSourceAction.java @@ -22,9 +22,9 @@ import docking.action.MenuData; import ghidra.app.decompiler.*; import ghidra.app.plugin.core.decompile.DecompilerActionContext; 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.program.model.listing.Function; +import ghidra.program.model.pcode.Varnode; import ghidra.util.HelpLocation; import ghidra.util.UndefinedFunction; @@ -87,6 +87,9 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction { if (tokenAtCursor instanceof ClangFuncNameToken) { return true; } + if (tokenAtCursor instanceof ClangOpToken) { + return true; + } if (!tokenAtCursor.isVariableRef()) { return false; } @@ -95,6 +98,26 @@ public class TaintSourceAction extends TaintAbstractDecompilerAction { @Override 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); + } + } + } + } } } diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/CTADLTaintState.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/CTADLTaintState.java index fe65000da6..2df6c11bf4 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/CTADLTaintState.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/CTADLTaintState.java @@ -28,7 +28,6 @@ import ghidra.app.plugin.core.osgi.BundleHost; import ghidra.app.script.*; import ghidra.app.services.ConsoleService; import ghidra.program.model.address.Address; -import ghidra.program.model.pcode.HighParam; import ghidra.program.model.pcode.HighVariable; /** @@ -146,18 +145,11 @@ public class CTADLTaintState extends AbstractTaintState { } } writer.println(method + "Vertex(\"" + mark.getLabel() + "\", vn, p) :-"); - if (!mark.isGlobal()) { - writer.println("\tHFUNC_NAME(m, \"" + mark.getFunctionName() + "\"),"); - writer.println("\tCVar_InFunction(vn, m),"); - } + writer.println("\t((HFUNC_NAME(m, \"" + mark.getFunctionName() + "\"),"); + writer.println("\tCVar_InFunction(vn, m)) ; CVar_isGlobal(vn)),"); if (addr != null && addr.getOffset() != 0 && !mark.bySymbol()) { - if (!TaintState.isActualParam(token) && !(hv instanceof HighParam)) { - writer.println("\tVNODE_PC_ADDRESS(vn, " + 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() + "),"); - } + writer.println("\t(PCODE_INPUT(i, _, vn) ; PCODE_OUTPUT(i, vn)),"); + writer.println("\tPCODE_TARGET(i, " + addr.getOffset() + "),"); } if (mark.bySymbol()) { writer.println("\tSYMBOL_NAME(sym, \"" + token.getText() + "\"),"); diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintResultHandler.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintResultHandler.java index b2ec2bb5d0..3998ce66f3 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintResultHandler.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintResultHandler.java @@ -242,17 +242,19 @@ public class SarifTaintResultHandler extends SarifResultHandler { Address faddr = (Address) r.get("entry"); String fqname = (String) r.get("location"); Set vset = getSet(map, faddr); - String edgeId = SarifUtils.getEdge(fqname); - if (edgeId != null) { - String srcId = SarifUtils.getEdgeSource(edgeId); - LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); - for (LogicalLocation lloc : srcNodes) { - vset.add(new TaintQueryResult(r, run, lloc)); - } - String dstId = SarifUtils.getEdgeDest(edgeId); - LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); - for (LogicalLocation lloc : dstNodes) { - vset.add(new TaintQueryResult(r, run, lloc)); + Set edgeIds = SarifUtils.getEdgeSet(fqname); + if (edgeIds != null) { + for (String edgeId : edgeIds) { + String srcId = SarifUtils.getEdgeSource(edgeId); + LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); + for (LogicalLocation lloc : srcNodes) { + vset.add(new TaintQueryResult(r, run, lloc)); + } + String dstId = SarifUtils.getEdgeDest(edgeId); + LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); + 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"); String fqname = (String) r.get("location"); Set vset = getSet(map, faddr); - String edgeId = SarifUtils.getEdge(fqname); - if (edgeId != null) { - String srcId = SarifUtils.getEdgeSource(edgeId); - LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); - for (LogicalLocation lloc : srcNodes) { - TaintQueryResult res = new TaintQueryResult(r, run, lloc); - vset.remove(res); - } - String dstId = SarifUtils.getEdgeDest(edgeId); - LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); - for (LogicalLocation lloc : dstNodes) { - TaintQueryResult res = new TaintQueryResult(r, run, lloc); - vset.remove(res); + Set edgeIds = SarifUtils.getEdgeSet(fqname); + if (edgeIds != null) { + for (String edgeId : edgeIds) { + String srcId = SarifUtils.getEdgeSource(edgeId); + LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); + for (LogicalLocation lloc : srcNodes) { + TaintQueryResult res = new TaintQueryResult(r, run, lloc); + vset.remove(res); + } + String dstId = SarifUtils.getEdgeDest(edgeId); + LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); + for (LogicalLocation lloc : dstNodes) { + TaintQueryResult res = new TaintQueryResult(r, run, lloc); + vset.remove(res); + } } map.put(faddr, vset); } diff --git a/Ghidra/Features/DecompilerDependent/src/test/java/ghidra/app/plugin/core/decompiler/taint/DecompilerTaintTest.java b/Ghidra/Features/DecompilerDependent/src/test/java/ghidra/app/plugin/core/decompiler/taint/DecompilerTaintTest.java index 67c2479e71..42117290e6 100644 --- a/Ghidra/Features/DecompilerDependent/src/test/java/ghidra/app/plugin/core/decompiler/taint/DecompilerTaintTest.java +++ b/Ghidra/Features/DecompilerDependent/src/test/java/ghidra/app/plugin/core/decompiler/taint/DecompilerTaintTest.java @@ -226,17 +226,19 @@ public class DecompilerTaintTest extends AbstractGhidraHeadedIntegrationTest { Address faddr = (Address) result.get("entry"); String fqname = (String) result.get("location"); Set vset = getSet(map, faddr); - String edgeId = SarifUtils.getEdge(fqname); - if (edgeId != null) { - String srcId = SarifUtils.getEdgeSource(edgeId); - LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); - for (LogicalLocation lloc : srcNodes) { - vset.add(new TaintQueryResult(result, run, lloc)); - } - String dstId = SarifUtils.getEdgeDest(edgeId); - LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); - for (LogicalLocation lloc : dstNodes) { - vset.add(new TaintQueryResult(result, run, lloc)); + Set edgeIds = SarifUtils.getEdgeSet(fqname); + if (edgeIds != null) { + for (String edgeId : edgeIds) { + String srcId = SarifUtils.getEdgeSource(edgeId); + LogicalLocation[] srcNodes = SarifUtils.getNodeLocs(srcId); + for (LogicalLocation lloc : srcNodes) { + vset.add(new TaintQueryResult(result, run, lloc)); + } + String dstId = SarifUtils.getEdgeDest(edgeId); + LogicalLocation[] dstNodes = SarifUtils.getNodeLocs(dstId); + for (LogicalLocation lloc : dstNodes) { + vset.add(new TaintQueryResult(result, run, lloc)); + } } } } diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/SarifUtils.java b/Ghidra/Features/Sarif/src/main/java/sarif/SarifUtils.java index b7270e8138..0c5761aa05 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/SarifUtils.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/SarifUtils.java @@ -16,43 +16,17 @@ package sarif; import java.io.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.bouncycastle.util.encoders.Base64; -import com.contrastsecurity.sarif.Artifact; -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.contrastsecurity.sarif.*; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import ghidra.framework.store.LockException; +import ghidra.program.model.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.Program; import ghidra.util.InvalidNameException; @@ -77,7 +51,7 @@ public class SarifUtils { private static Map nodeLocs = new HashMap<>(); private static Map edgeSrcs = new HashMap<>(); private static Map edgeDsts = new HashMap<>(); - private static Map edgeDescs = new HashMap<>(); + private static Map> edgeDescs = new HashMap<>(); private static boolean populating = false; public static JsonArray setLocations(Address min, Address max) { @@ -403,7 +377,12 @@ public class SarifUtils { String desc = e.getLabel().getText(); edgeSrcs.put(id, src); edgeDsts.put(id, dst); - edgeDescs.put(desc, id); + Set set = edgeDescs.get(desc); + if (set == null) { + set = new HashSet<>(); + edgeDescs.put(desc, set); + } + set.add(id); } Set nodes = rg.getNodes(); for (Node n : nodes) { @@ -428,7 +407,7 @@ public class SarifUtils { } } - public static String getEdge(String fqname) { + public static Set getEdgeSet(String fqname) { return edgeDescs.get(fqname); } @@ -456,4 +435,8 @@ public class SarifUtils { populating = b; } + public static Map> getEdgeMap() { + return edgeDescs; + } + }