Add Rust decompiler widget plugin

This commit is contained in:
Dhruv Maroo
2023-04-21 01:04:29 +05:30
parent 27586dd822
commit 32ce329db1
2 changed files with 229 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
/* ###
* 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 ghidrust.decompiler;
import ghidra.app.plugin.PluginCategoryNames;
import docking.ActionContext;
import docking.action.DockingAction;
import ghidra.app.events.*;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.framework.plugintool.PluginEvent;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.util.Msg;
import ghidrust.analyzer.RustStdAnalyzer;
import docking.action.MenuData;
//@formatter:off
@PluginInfo(
status = PluginStatus.RELEASED,
packageName = "HELLO",
category = PluginCategoryNames.DECOMPILER,
shortDescription = "Rust Decompiler",
description = "Decompile Rust binaries' assembly to Rust code",
eventsConsumed = {
ProgramActivatedPluginEvent.class, ProgramLocationPluginEvent.class, ProgramClosedPluginEvent.class
}
)
//@formatter:on
public class RustDecPlugin extends Plugin {
Program program;
RustDecProvider provider;
public RustDecPlugin(PluginTool tool) {
super(tool);
provider = new RustDecProvider(this, getName(), null);
DockingAction dec_plugin = new DockingAction("GhidRust", getName()) {
@Override
public void actionPerformed(ActionContext context) {
provider.activateProvider();;
}
};
dec_plugin.setEnabled(true);
dec_plugin.setMenuBarData(new MenuData(new String[] { "GhidRust", "Open decompiler" }));
DockingAction check_plugin = new DockingAction("GhidRust", getName()) {
@Override
public void actionPerformed(ActionContext context) {
if (RustStdAnalyzer.isRustBinary(program)) {
Msg.info(this, "[+] Yes, this may be a Rust binary!");
} else {
Msg.info(this, "[-] No, this may not be a Rust binary!");
}
}
};
check_plugin.setEnabled(true);
check_plugin.setMenuBarData(new MenuData(new String[] { "GhidRust", "Check if Rust binary" }));
tool.addAction(dec_plugin);
tool.addAction(check_plugin);
}
@Override
public void processEvent(PluginEvent event) {
if (event instanceof ProgramActivatedPluginEvent) {
program = ((ProgramActivatedPluginEvent) event).getActiveProgram();
provider.setProgram(program);
provider.setLocation(null);
} else if (event instanceof ProgramLocationPluginEvent) {
ProgramLocation location = ((ProgramLocationPluginEvent) event).getLocation();
provider.setLocation(location.getAddress());
} else if (event instanceof ProgramClosedPluginEvent) {
program = null;
provider.setProgram(program);
provider.setLocation(null);
}
provider.reload();
}
}

View File

@@ -0,0 +1,130 @@
package ghidrust.decompiler;
import ghidra.program.model.listing.Program;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.app.decompiler.DecompInterface;
import ghidra.app.decompiler.DecompileResults;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JButton;
import javax.swing.Box;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import docking.ComponentProvider;
import ghidra.util.task.ConsoleTaskMonitor;
import resources.ResourceManager;
public class RustDecProvider extends ComponentProvider {
private JPanel panel;
private JTextArea code_area;
private JLabel func_title;
private JToolBar toolbar;
private JButton reload;
private Program prog;
private Address addr;
private DecompInterface decomp_ifc = null;
private static final String EMPTY_LABEL = "<none>";
public RustDecProvider(RustDecPlugin plugin, String owner, Program p) {
super(plugin.getTool(), owner, owner);
setIcon(ResourceManager.loadImage("images/icon.png"));
decomp_ifc = new DecompInterface();
setProgram(p);
buildPanel();
}
@Override
public JComponent getComponent() {
return panel;
}
private void buildPanel() {
panel = new JPanel(new BorderLayout());
func_title = new JLabel(EMPTY_LABEL);
reload = new JButton(ResourceManager.loadImage("images/reload.png"));
reload.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
reload();
}
});
toolbar = new JToolBar("GhidRust", JToolBar.HORIZONTAL);
toolbar.add(func_title);
toolbar.add(Box.createHorizontalGlue());
toolbar.add(reload);
code_area = new JTextArea();
panel.add(toolbar, BorderLayout.PAGE_START);
panel.add(code_area);
}
public void activateProvider() {
setVisible(true);
}
public void setProgram(Program p) {
prog = p;
decomp_ifc.closeProgram();
if (prog != null) {
decomp_ifc.openProgram(prog);
}
}
public void setLocation(Address a) {
addr = a;
}
public void reload() {
if (prog == null) {
func_title.setText(EMPTY_LABEL);
code_area.setText("[?] Open a program to see the decompilation!\n");
return;
}
if (addr == null) {
func_title.setText(EMPTY_LABEL);
code_area.setText("[?] Select a memory location to decompile!\n");
return;
}
Function func = prog.getFunctionManager().getFunctionContaining(addr);
if (func == null) {
func_title.setText(EMPTY_LABEL);
code_area.setText("[!] No function found at " + addr.toString() + "\n");
return;
}
func_title.setText(func.getName());
if (decomp_ifc == null) {
code_area.setText("[!] Decompiler has not been initialized!\n");
return;
}
DecompileResults results = decomp_ifc.decompileFunction(func, 0, new ConsoleTaskMonitor());
if (results == null || results.getDecompiledFunction() == null) {
code_area.setText("[!] Failed to decompile " + func.getName() + "\n");
return;
}
code_area.setText(results.getDecompiledFunction().getC());
}
}