GP-5566: first/last? changes for ghidra

GP-5566: fix for J

GP-5566: minor fixes

GP-5566: icons decl proper

GP-5566: minor tweaks

GP-5566: post-review

GP-5566: minor

GP-5566: mo better monitor logic

GP-5566: minor fix
This commit is contained in:
d-millar 2025-07-25 15:15:47 +00:00
parent b25e7c12a1
commit f5572ede99
21 changed files with 229 additions and 26 deletions

View file

@ -184,6 +184,10 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
funcName = syscallNumbersToNames.get(offset); funcName = syscallNumbersToNames.get(offset);
} }
callee = createFunction(callTarget, funcName); callee = createFunction(callTarget, funcName);
if (callee == null) {
Msg.warn(this, "Unable to create function at "+callTarget);
continue;
}
callee.setCallingConvention(callingConvention); callee.setCallingConvention(callingConvention);
//check if the function name is one of the non-returning syscalls //check if the function name is one of the non-returning syscalls

View file

@ -8,3 +8,5 @@ src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html||GHIDRA||||END|
src/main/help/help/topics/DecompilerTextFinderPlugin/Decompiler_Text_Finder.html||GHIDRA||||END| src/main/help/help/topics/DecompilerTextFinderPlugin/Decompiler_Text_Finder.html||GHIDRA||||END|
src/main/help/help/topics/DecompilerTextFinderPlugin/images/DecompilerTextFinderDialog.png||GHIDRA||||END| src/main/help/help/topics/DecompilerTextFinderPlugin/images/DecompilerTextFinderDialog.png||GHIDRA||||END|
src/main/help/help/topics/DecompilerTextFinderPlugin/images/DecompilerTextFinderResultsTable.png||GHIDRA||||END| src/main/help/help/topics/DecompilerTextFinderPlugin/images/DecompilerTextFinderResultsTable.png||GHIDRA||||END|
src/main/resources/images/default-query.png||GHIDRA||||END|
src/main/resources/images/gate-set.png||GHIDRA||||END|

View file

@ -8,5 +8,7 @@ color.bg.decompiler.highlights.sourcesink = color.palette.darkcyan
color.bg.decompiler.highlights.path = color.palette.yellow color.bg.decompiler.highlights.path = color.palette.yellow
icon.plugin.decompiler.text.finder.select.functions = icon.make.selection {FunctionScope.gif[size(12,12)][move(6,6)]} icon.plugin.decompiler.text.finder.select.functions = icon.make.selection {FunctionScope.gif[size(12,12)][move(6,6)]}
icon.plugin.decompiler.taint.gate.set = gate-set.png
icon.plugin.decompiler.taint.default.query = default-query.png
[Dark Defaults] [Dark Defaults]

View file

@ -0,0 +1,29 @@
/* ###
* 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.absint;
import ghidra.framework.plugintool.ServiceInfo;
/**
* The AbstractInterpretationService provides a general service for generating results from an external engine
*/
@ServiceInfo(description = "supply abstract interpretation")
public interface AbstractInterpretationService {
public String getActiveQueryName();
}

View file

@ -33,6 +33,7 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.HighVariable; import ghidra.program.model.pcode.HighVariable;
import ghidra.program.model.pcode.PcodeException; import ghidra.program.model.pcode.PcodeException;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
import sarif.SarifService; import sarif.SarifService;
/** /**
@ -59,10 +60,11 @@ public abstract class AbstractTaintState implements TaintState {
protected TaintOptions taintOptions; protected TaintOptions taintOptions;
protected TaintPlugin plugin; protected TaintPlugin plugin;
protected boolean usesIndex = true; protected boolean usesIndex = true;
private boolean cancellation; protected TaskMonitor monitor = TaskMonitor.DUMMY;
private TaskType taskType = TaskType.SET_TAINT; private TaskType taskType = TaskType.SET_TAINT;
public AbstractTaintState(TaintPlugin plugin) { public AbstractTaintState(TaintPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
@ -83,13 +85,22 @@ public abstract class AbstractTaintState implements TaintState {
protected abstract void writeFooter(PrintWriter writer); protected abstract void writeFooter(PrintWriter writer);
@Override @Override
public boolean wasCancelled() { public void setMonitor(TaskMonitor monitor) {
return this.cancellation; if (monitor != null) {
monitor.setIndeterminate(true);
monitor.setShowProgressValue(false);
}
this.monitor = monitor;
} }
@Override @Override
public void setCancellation(boolean status) { public boolean isCancelled() {
this.cancellation = status; return monitor != null && monitor.isCancelled();
}
@Override
public void cancel() {
monitor.cancel();
} }
@Override @Override
@ -320,6 +331,10 @@ public abstract class AbstractTaintState implements TaintState {
pb.redirectError(Redirect.INHERIT); pb.redirectError(Redirect.INHERIT);
Process p = pb.start(); Process p = pb.start();
monitor.addCancelledListener(() -> {
p.destroyForcibly();
});
readQueryResultsIntoDataFrame(program, p.getInputStream()); readQueryResultsIntoDataFrame(program, p.getInputStream());
// We wait for the process to finish after starting to read the input stream, // We wait for the process to finish after starting to read the input stream,
@ -555,4 +570,9 @@ public abstract class AbstractTaintState implements TaintState {
return ENGINE_NAME; return ENGINE_NAME;
} }
@Override
public String getQueryName() {
return null;
}
} }

View file

@ -57,7 +57,7 @@ public class TaintDecompilerMarginProvider extends JPanel
private Icon sourceIcon = new GIcon("icon.plugin.scriptmanager.run"); private Icon sourceIcon = new GIcon("icon.plugin.scriptmanager.run");
private Icon sinkIcon = new GIcon("icon.stop"); private Icon sinkIcon = new GIcon("icon.stop");
private Icon gateIcon = new GIcon("icon.debugger.breakpoint.set"); private Icon gateIcon = new GIcon("icon.plugin.decompiler.taint.gate.set");
public TaintDecompilerMarginProvider(TaintPlugin plugin) { public TaintDecompilerMarginProvider(TaintPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;

View file

@ -160,15 +160,16 @@ public class TaintLabelsTableProvider extends ComponentProviderAdapter {
TaintState state = plugin.getTaintState(); TaintState state = plugin.getTaintState();
Task queryTask = new Task("Source-Sink Query Task", true, true, true, true) { Task queryTask = new Task("Source-Sink Query Task", true, false, false, true) {
@Override @Override
public void run(TaskMonitor monitor) { public void run(TaskMonitor monitor) {
state.setCancellation(false);
monitor.initialize(program.getFunctionManager().getFunctionCount()); monitor.initialize(program.getFunctionManager().getFunctionCount());
// query index NOT the default query; use table data. // query index NOT the default query; use table data.
boolean successful = boolean successful =
state.queryIndex(currentProgram, tool, QueryType.SRCSINK); state.queryIndex(currentProgram, tool, QueryType.SRCSINK);
state.setCancellation(!successful || monitor.isCancelled()); if (!successful) {
state.cancel();
}
monitor.clearCancelled(); monitor.clearCancelled();
} }
}; };
@ -180,7 +181,7 @@ public class TaintLabelsTableProvider extends ComponentProviderAdapter {
// 1. Query Index. // 1. Query Index.
tool.execute(queryTask); tool.execute(queryTask);
if (!state.wasCancelled()) { if (!state.isCancelled()) {
// 2. Show Table. // 2. Show Table.
SarifService sarifService = plugin.getSarifService(); SarifService sarifService = plugin.getSarifService();
sarifService.getController() sarifService.getController()
@ -192,8 +193,6 @@ public class TaintLabelsTableProvider extends ComponentProviderAdapter {
TaintProvider provider = plugin.getProvider(); TaintProvider provider = plugin.getProvider();
provider.setTaint(); provider.setTaint();
plugin.consoleMessage("query complete"); plugin.consoleMessage("query complete");
state.setCancellation(false);
} }
else { else {
plugin.consoleMessage("Source-Sink query was cancelled."); plugin.consoleMessage("Source-Sink query was cancelled.");

View file

@ -265,7 +265,7 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
state.setTaskType(taskType); state.setTaskType(taskType);
AddressSet taintAddressSet = state.getTaintAddressSet(); AddressSet taintAddressSet = state.getTaintAddressSet();
Msg.info(this, "setTaint(): " + taintAddressSet.toString()); //Msg.info(this, "setTaint(): " + taintAddressSet.toString());
// sets the selection in the LISTING? // sets the selection in the LISTING?
// TODO: should we not set select and only highlight in the decompilation. // TODO: should we not set select and only highlight in the decompilation.

View file

@ -119,6 +119,9 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address
if (fqname.contains(":"+hvName)) { if (fqname.contains(":"+hvName)) {
return hvName; return hvName;
} }
if (fqname.contains(":"+ast.getAddress())) {
return hvName;
}
} }
} }

View file

@ -35,6 +35,7 @@ import ghidra.program.model.symbol.SymbolTable;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.classfinder.ExtensionPoint; import ghidra.util.classfinder.ExtensionPoint;
import ghidra.util.task.TaskMonitor;
/** /**
* 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
@ -92,6 +93,8 @@ public interface TaintState extends ExtensionPoint {
*/ */
public boolean queryIndex(Program program, PluginTool tool, QueryType queryType); public boolean queryIndex(Program program, PluginTool tool, QueryType queryType);
public String getQueryName();
public TaintLabel toggleMark(MarkType mtype, ClangToken token) throws PcodeException; public TaintLabel toggleMark(MarkType mtype, ClangToken token) throws PcodeException;
public Set<TaintLabel> getTaintLabels(MarkType mtype); public Set<TaintLabel> getTaintLabels(MarkType mtype);
@ -121,9 +124,11 @@ public interface TaintState extends ExtensionPoint {
// predicate that indicates there are sources, sinks, or gates. // predicate that indicates there are sources, sinks, or gates.
public boolean hasMarks(); public boolean hasMarks();
public boolean wasCancelled(); public void setMonitor(TaskMonitor monitor);
public void setCancellation(boolean status); public boolean isCancelled();
public void cancel();
public void setTaintVarnodeMap(Map<Address, Set<TaintQueryResult>> vmap, TaskType delta); public void setTaintVarnodeMap(Map<Address, Set<TaintQueryResult>> vmap, TaskType delta);

View file

@ -76,11 +76,9 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
@Override @Override
public void run(TaskMonitor monitor) { public void run(TaskMonitor monitor) {
TaintState state = plugin.getTaintState(); TaintState state = plugin.getTaintState();
state.setCancellation(false); state.setMonitor(monitor);
monitor.initialize(program.getFunctionManager().getFunctionCount());
state.queryIndex(program, tool, queryType); state.queryIndex(program, tool, queryType);
state.setCancellation(monitor.isCancelled()); state.setMonitor(null);
monitor.clearCancelled();
} }
}; };
@ -91,11 +89,15 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
tool.execute(defaultQueryTask); tool.execute(defaultQueryTask);
TaintState state = plugin.getTaintState(); TaintState state = plugin.getTaintState();
if (!state.wasCancelled()) { if (!defaultQueryTask.isCancelled()) {
TaintFormat format = state.getOptions().getTaintOutputForm(); TaintFormat format = state.getOptions().getTaintOutputForm();
if (!format.equals(TaintFormat.NONE)) { if (!format.equals(TaintFormat.NONE)) {
SarifService sarifService = plugin.getSarifService(); SarifService sarifService = plugin.getSarifService();
sarifService.getController().setDefaultGraphHander(SarifTaintGraphRunHandler.class); sarifService.getController().setDefaultGraphHander(SarifTaintGraphRunHandler.class);
String queryName = state.getQueryName();
if (queryName != null) {
desc = queryName;
}
sarifService.showSarif(desc, state.getData()); sarifService.showSarif(desc, state.getData());
} }
@ -104,11 +106,9 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
provider.setTaint(); provider.setTaint();
plugin.consoleMessage("query complete"); plugin.consoleMessage("query complete");
state.setCancellation(false);
} }
else { else {
plugin.consoleMessage("Source-Sink query was cancelled."); plugin.consoleMessage("Source-Sink query was cancelled.");
} }
} }
} }

View file

@ -28,7 +28,7 @@ public class TaintQueryDefaultAction extends TaintAbstractQueryAction {
public TaintQueryDefaultAction(TaintPlugin plugin) { public TaintQueryDefaultAction(TaintPlugin plugin) {
super(plugin, "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.plugin.decompiler.taint.default.query";
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString); executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
queryType = QueryType.DEFAULT; queryType = QueryType.DEFAULT;

View file

@ -23,6 +23,7 @@ import ghidra.app.plugin.core.decompiler.taint.TaintLabel;
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin; import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
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.util.HelpLocation;
import ghidra.util.UndefinedFunction; import ghidra.util.UndefinedFunction;
/** /**
@ -46,6 +47,7 @@ public class TaintSetSizeAction extends TaintAbstractDecompilerAction {
public TaintSetSizeAction(TaintPlugin plugin) { public TaintSetSizeAction(TaintPlugin plugin) {
super("Set length"); super("Set length");
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, TaintPlugin.HELP_LOCATION));
// Taint Menu -> Source sub item. // Taint Menu -> Source sub item.
setPopupMenuData(new MenuData(new String[] { "Taint", "Set length" }, "Decompile")); setPopupMenuData(new MenuData(new String[] { "Taint", "Set length" }, "Decompile"));
this.plugin = plugin; this.plugin = plugin;

View file

@ -216,6 +216,7 @@ public class SarifTaintResultHandler extends SarifResultHandler {
protected void doRun(TaskMonitor monitor) { protected void doRun(TaskMonitor monitor) {
int[] selected = tableProvider.filterTable.getTable().getSelectedRows(); int[] selected = tableProvider.filterTable.getTable().getSelectedRows();
Map<Address, Set<TaintQueryResult>> map = new HashMap<>(); Map<Address, Set<TaintQueryResult>> map = new HashMap<>();
AddressSet set = new AddressSet();
for (int row : selected) { for (int row : selected) {
Map<String, Object> r = tableProvider.getRow(row); Map<String, Object> r = tableProvider.getRow(row);
String kind = (String) r.get("kind"); String kind = (String) r.get("kind");
@ -225,12 +226,17 @@ public class SarifTaintResultHandler extends SarifResultHandler {
if (kind.equals("variable")) { if (kind.equals("variable")) {
getTaintedVariable(map, r); getTaintedVariable(map, r);
} }
Address addr = (Address) r.get("Address");
if (addr != null) {
set.add(addr);
}
} }
PluginTool tool = tableProvider.getController().getPlugin().getTool(); PluginTool tool = tableProvider.getController().getPlugin().getTool();
TaintService service = tool.getService(TaintService.class); TaintService service = tool.getService(TaintService.class);
if (service != null) { if (service != null) {
service.setVarnodeMap(map, true, taskType); service.setVarnodeMap(map, true, taskType);
service.setAddressSet(set, false);
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

View file

@ -111,6 +111,10 @@ public class SarifController implements ObjectSelectedListener<Map<String, Objec
public void showTable(String logName, SarifSchema210 sarif) { public void showTable(String logName, SarifSchema210 sarif) {
SarifDataFrame df = new SarifDataFrame(sarif, this, false); SarifDataFrame df = new SarifDataFrame(sarif, this, false);
int size = df.getTableResults().size();
if (size != 0) {
logName += " ["+size+"]";
}
SarifResultsTableProvider provider = SarifResultsTableProvider provider =
new SarifResultsTableProvider(logName, getPlugin(), this, df); new SarifResultsTableProvider(logName, getPlugin(), this, df);
provider.filterTable.addSelectionListener(this); provider.filterTable.addSelectionListener(this);
@ -278,7 +282,6 @@ public class SarifController implements ObjectSelectedListener<Map<String, Objec
return defaultGraphHandler; return defaultGraphHandler;
} }
@SuppressWarnings("unchecked")
public void setDefaultGraphHander(Class<? extends SarifGraphRunHandler> clazz) { public void setDefaultGraphHander(Class<? extends SarifGraphRunHandler> clazz) {
defaultGraphHandler = clazz; defaultGraphHandler = clazz;
} }

View file

@ -92,6 +92,31 @@ public class SarifUtils {
return locations; return locations;
} }
public static JsonArray setLocation(Address addr, String kind, String uri, String name, String fqname, int index) {
JsonArray locations = new JsonArray();
JsonObject element = new JsonObject();
locations.add(element);
JsonObject ploc = new JsonObject();
JsonArray lloc = new JsonArray();
element.add("physicalLocation", ploc);
element.add("logicalLocations", lloc);
JsonObject artifact = new JsonObject();
artifact.addProperty("uri", uri);
JsonObject address = new JsonObject();
ploc.add("artifactLocation", artifact);
ploc.add("address", address);
address.addProperty("absoluteAddress", addr.getOffset());
if (name != null) {
address.addProperty("name", name);
}
address.addProperty("kind", kind);
address.addProperty("fullyQualifiedName", fqname);
JsonObject ll = new JsonObject();
lloc.add(ll);
ll.addProperty("index", index);
return locations;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static AddressSet getLocations(Map<String, Object> result, Program program, AddressSet set) public static AddressSet getLocations(Map<String, Object> result, Program program, AddressSet set)
throws AddressOverflowException { throws AddressOverflowException {

View file

@ -0,0 +1,49 @@
/* ###
* 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 sarif.export;
import ghidra.program.model.data.ISF.IsfObject;
import ghidra.program.model.listing.Function;
public class ExtLogicalLocation implements IsfObject {
String name;
String kind;
String decoratedName;
String fullyQualifiedName;
String uri;
public ExtLogicalLocation(String key, Function function, String location, String op) {
this.name = key;
this.kind = "variable";
this.decoratedName = op;
this.fullyQualifiedName = location + ":" + name;
this.uri = function.getProgram().getExecutablePath();
}
public String getName() {
return name;
}
public String getDecoratedName() {
return decoratedName;
}
public String getFullyQualfiedName() {
return fullyQualifiedName;
}
}

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -67,6 +67,13 @@ public class SarifObject implements IsfObject {
} }
} }
public SarifObject(String key, String ruleKey, ExtLogicalLocation lloc, JsonElement tree, Address addr, int index) {
this(key, ruleKey, tree);
if (addr != null) {
locations = SarifUtils.setLocation(addr, "data", lloc.uri, lloc.name, lloc.fullyQualifiedName, index);
}
}
protected void writeLocations(Address min, Address max) { protected void writeLocations(Address min, Address max) {
if (SARIF) { if (SARIF) {
locations = SarifUtils.setLocations(min, max); locations = SarifUtils.setLocations(min, max);

View file

@ -0,0 +1,47 @@
/* ###
* 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 sarif.export;
import ghidra.program.model.address.Address;
public class WrappedLogicalLocation {
private ExtLogicalLocation lloc;
private Address addr;
private int index;
public WrappedLogicalLocation(ExtLogicalLocation lloc, Address addr) {
this.lloc = lloc;
this.addr = addr;
}
public ExtLogicalLocation getLogicalLocation() {
return lloc;
}
public Address getAddress() {
return addr;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}