mirror of
https://github.com/DMaroo/GhidRust.git
synced 2025-09-10 04:53:36 +02:00
Add Rust decompiler widget plugin
This commit is contained in:
99
src/main/java/ghidrust/decompiler/RustDecPlugin.java
Normal file
99
src/main/java/ghidrust/decompiler/RustDecPlugin.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
130
src/main/java/ghidrust/decompiler/RustDecProvider.java
Normal file
130
src/main/java/ghidrust/decompiler/RustDecProvider.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user