Skip to content

Commit

Permalink
Step over feature added, more visual emulation highlighting
Browse files Browse the repository at this point in the history
This will be the start of a new release, 2.1. What has been implemented:

* added a more visual highlight during the emulation in orange, which now plays
the role of a mark where you are now in accordance with your PC value

* step over feature added

* README updated

* fixed various bugs
  • Loading branch information
Nalen98 committed Dec 29, 2022
1 parent 1042ef2 commit 05e73b3
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 102 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ If you changed something, let emulator know about changed bytes (stack updates a
![GhidraEmu apply patched bytes](./images/ApplyPatchedBytes.png)

#### Console
Here plugin prints output information.
Here plugin prints output information. For example, emulation error messages like that:

![GhidraEmu console](./images/Console.png)

Expand All @@ -84,11 +84,17 @@ We'll just try to cheat a little and jump over it by increasing the PC value. To

![Jump Over](./images/JumpOver.gif)


### New feature - Step Over

If you stop at an instruction that leads to a subroutine (internal call) and you want to emulate everything up to the next instruction (classic "step over"), press the `F6` hotkey and it will certainly happen:

![Step Over](./images/StepOver.gif)

# Before you start
**A few important points to consider**:
* Don't forget to analyze your program in Ghidra, emulator depends on it.
* As already mentioned, set the link register if you have an exotic processor/vm.
* If the processor of your binary needs certain memory segments according to the specification, don't forget to create them in the Ghidra MemoryMap Window and initialize them to zeros. Otherwise, the emulator will complain about unknown memory spaces during read/write and stop the emualtion process. If the memory block exists, but is not initialized with zeros and is needed by the emulator, the plugin will try to make it initialized so that the emulation continues.
* If you have changed any bytes through the ByteViewer, the plugin won't restore them to their original values during resetting emulation state.
* Before closing the project in Ghidra, you should press the "Reset" button and reset the state of the last emulation, if such an action was not performed. This is important, because at the moment of closing, transactions for repainting traced instructions in the listing will not be executed, as well as transactions for restoring program bytes after emulation. This can lead in the future not only to the contemplation of the "old yellow parrot", which is the least problem, but the bytes modified as a result of emulation will remain as such and will not return to their original values (unless the project is rolled back in Ghidra, of course).

Expand Down
Binary file modified images/ApplyPatchedBytes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/Console.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/JumpOver.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/StepOver.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/emuExample.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 8 additions & 3 deletions src/main/java/ghidraemu/AddBreakpointPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.math.BigInteger;
import java.awt.event.ActionEvent;
import docking.widgets.textfield.IntegerTextField;
import ghidra.program.model.address.Address;
import resources.ResourceManager;

public class AddBreakpointPanel {
Expand Down Expand Up @@ -52,12 +53,16 @@ private void initialize() {
JButton AddBtn = new JButton("Add");
AddBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (!GhidraEmuProvider.breaks.contains(GhidraEmuProvider.program.getAddressFactory().getAddress(AddrTF.getText()))) {
GhidraEmuProvider.breaks.add(GhidraEmuProvider.program.getAddressFactory().getAddress(AddrTF.getText()));
Address currentAddress = GhidraEmuProvider.program.getAddressFactory().getAddress(AddrTF.getText());
if (!GhidraEmuProvider.breaks.contains(currentAddress)) {
GhidraEmuProvider.breaks.add(currentAddress);
BreakpointProvider.breakModel.addRow(new Object[] {
BreakpointProvider.breakpointIcon, BigInteger.valueOf(AddrTF.getLongValue())
});
GhidraEmuPopup.setColor(GhidraEmuProvider.program.getAddressFactory().getAddress(AddrTF.getText()), Color.RED);
GhidraEmuPopup.setColor(currentAddress, Color.RED);
if (GhidraEmuProvider.emuHelper != null){
GhidraEmuProvider.emuHelper.setBreakpoint(currentAddress);
}
}
frame.dispose();
}
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/ghidraemu/BreakpointProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ public void actionPerformed(ActionContext context) {
public void actionPerformed(ActionContext context) {
try {
int selected = breakTable.getSelectedRow();
GhidraEmuPopup.unsetColor(GhidraEmuProvider.breaks.get(selected));
GhidraEmuProvider.breaks.remove(selected);
Address currentAddress = GhidraEmuProvider.breaks.get(selected);
GhidraEmuPopup.unsetColor(currentAddress);
GhidraEmuProvider.breaks.remove(currentAddress);
breakModel.removeRow(selected);
if (GhidraEmuProvider.emuHelper != null){
GhidraEmuProvider.emuHelper.clearBreakpoint(currentAddress);
}
} catch (Exception ex) {}
}
};
Expand Down
32 changes: 25 additions & 7 deletions src/main/java/ghidraemu/GhidraEmuPopup.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
import ghidra.program.model.mem.MemoryAccessException;

public class GhidraEmuPopup extends ListingContextAction {
public GhidraEmuPlugin ghidraEmuPlugin;
public final String menuName = "GhidraEmu";
public final String groupName = "GhidraEmu";
public static PluginTool tool;
public static PluginTool tool;
public static Program program;
public static Address start_address = null;
public static Address stop_address = null;
Expand All @@ -31,6 +32,7 @@ public GhidraEmuPopup(GhidraEmuPlugin plugin, Program program) {
setProgram(program);
tool = plugin.getTool();
setupActions();
ghidraEmuPlugin = plugin;
}

public void setProgram(Program p) {
Expand Down Expand Up @@ -153,6 +155,9 @@ protected void actionPerformed(ListingActionContext context) {
BreakpointProvider.breakModel.removeRow(i);
}
}
if (GhidraEmuProvider.emuHelper != null){
GhidraEmuProvider.emuHelper.clearBreakpoint(address);
}
}
};
unsetBreak.setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, 0));
Expand All @@ -166,12 +171,9 @@ protected void actionPerformed(ListingActionContext context) {
NavigatableContextAction jumpOver = new NavigatableContextAction("Jump over the instruction", getName()) {
@Override
protected void actionPerformed(NavigatableActionContext context) {
Address badPlace = GhidraEmuProvider.emuHelper.getExecutionAddress();
unsetColor(badPlace);
GhidraEmuProvider.setNextPC();
Address newPC = GhidraEmuProvider.emuHelper.getExecutionAddress();
setColor(newPC, Color.getHSBColor(247, 224, 98));
GhidraEmuProvider.traced.add(newPC);
if (GhidraEmuProvider.emuHelper != null && ghidraEmuPlugin != null) {
ghidraEmuPlugin.provider.jumpOver();
}
}
};
jumpOver.setKeyBindingData(new KeyBindingData(KeyEvent.VK_J, 0));
Expand All @@ -180,6 +182,22 @@ protected void actionPerformed(NavigatableActionContext context) {
"Jump over"
}, null, groupName));
tool.addAction(jumpOver);

// new feature - step over the subroutine
NavigatableContextAction stepOver = new NavigatableContextAction("Step over the subroutine", getName()) {
@Override
protected void actionPerformed(NavigatableActionContext context) {
if (GhidraEmuProvider.emuHelper != null && ghidraEmuPlugin != null) {
ghidraEmuPlugin.provider.stepOver();
}
}
};
stepOver.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F6, 0));
stepOver.setPopupMenuData(new MenuData(new String[] {
menuName,
"Step over"
}, null, groupName));
tool.addAction(stepOver);
}

public static void unsetColor(Address address) {
Expand Down
Loading

0 comments on commit 05e73b3

Please sign in to comment.