Skip to content

Instantly share code, notes, and snippets.

@AFranzo
Created January 20, 2025 11:07
//decrypt keystream XOR data given the address of the key and of the cipher
//@author
//@category Functions
//@keybinding
//@menupath
//@toolbar
//@runtime Java
import ghidra.app.script.GhidraScript;
import ghidra.util.exception.InvalidInputException;
import ghidra.program.model.address.Address;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JCheckBox;
import java.awt.GridLayout;
public class XORcustom extends GhidraScript {
@Override
public void run() throws Exception {
// Create a panel for the dialog box with separate fields
JPanel panel = new JPanel(new GridLayout(5, 2));
// Add fields for key address and key length
JLabel keyAddressLabel = new JLabel("Key Address (Hex):");
JTextField keyAddressField = new JTextField(currentLocation!=null?currentLocation.getAddress().toString():"");
JLabel keyLengthLabel = new JLabel("Key Length (Decimal):");
JTextField keyLengthField = new JTextField("16"); // Default value
JLabel cipherAddressLabel = new JLabel("Cipher Address");
JTextField cipherAddressField = new JTextField();
JLabel cipherLengthLabel = new JLabel("Cipher Length (Decimal)");
JTextField cipherLengthField = new JTextField("16"); // Default value
JCheckBox renameCheckBox = new JCheckBox("Rename symbol");
// Add components to the panel
panel.add(keyAddressLabel);
panel.add(keyAddressField);
panel.add(keyLengthLabel);
panel.add(keyLengthField);
panel.add(cipherAddressLabel);
panel.add(cipherAddressField);
panel.add(cipherLengthLabel);
panel.add(cipherLengthField);
panel.add(renameCheckBox);
// Show dialog box to get user input
int result = JOptionPane.showConfirmDialog(null, panel, "Custom XOR decrypt",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
try {
// Parse and validate
String keyAddressInput = keyAddressField.getText().trim();
String keyLengthInput = keyLengthField.getText().trim();
String cipherAddressInput = cipherAddressField.getText().trim();
String cipherLengthInput = cipherLengthField.getText().trim();
boolean rename = renameCheckBox.isSelected();
// Convert fields
Address keyAddress = toAddr(parseHexAddress(keyAddressInput));
Address cipherAddress = toAddr(parseHexAddress(cipherAddressInput));
int keyLength = Integer.parseInt(keyLengthInput);
int cipherLength = Integer.parseInt(cipherLengthInput);
// Extract and display the key data from memory
byte[] keyData = getBytes(keyAddress, keyLength);
byte[] cipherData = getBytes(cipherAddress,cipherLength);
char[] res =new char[cipherData.length];
for(int i=0;i<cipherData.length;++i) {
res[i]=(char)((cipherData[i]^keyData[i]));
}
setPreComment(cipherAddress,String.valueOf(res));
if (rename) {
Symbol sym = currentProgram.getSymbolTable().getPrimarySymbol(cipherAddress);
sym.setName(String.valueOf(res),SourceType.USER_DEFINED);
}
} catch (NumberFormatException e) {
println("Error: Invalid length format.");
} catch (InvalidInputException e) {
println("Error: Invalid address format.");
} catch (Exception e) {
println("Unexpected error: " + e.getMessage());
}
}
}
// Helper function to parse a hex string and return its long value
private long parseHexAddress(String hexAddress) throws InvalidInputException {
if (hexAddress.startsWith("0x")) {
hexAddress = hexAddress.substring(2); // Remove "0x" prefix
}
try {
return Long.parseLong(hexAddress, 16);
} catch (NumberFormatException e) {
throw new InvalidInputException("Invalid hexadecimal address format.");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment