From 00ef824dbd3861bf3297ff097f503dbe59934d03 Mon Sep 17 00:00:00 2001 From: S-S-P Date: Sun, 30 Jun 2019 20:17:24 -0400 Subject: [PATCH] Add support for copying bytes formatted as Python byte-string, Python list, and C/Java array --- .../CodeBrowserClipboardProvider.java | 18 +++++ .../main/java/ghidra/app/util/ByteCopier.java | 69 ++++++++++++++++++- .../ByteViewerClipboardProvider.java | 15 ++++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java index 0d4317b0f5..aef4821816 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java @@ -77,6 +77,9 @@ public class CodeBrowserClipboardProvider extends ByteCopier list.add(COMMENTS_TYPE); list.add(BYTE_STRING_TYPE); list.add(BYTE_STRING_NO_SPACE_TYPE); + list.add(PYTHON_BYTE_STRING_TYPE); + list.add(PYTHON_LIST_TYPE); + list.add(CPP_BYTE_ARRAY_TYPE); list.add(ADDRESS_TEXT_TYPE); return list; @@ -239,6 +242,21 @@ public class CodeBrowserClipboardProvider extends ByteCopier String byteString = copyBytesAsString(getSelectedAddresses(), false, monitor); return new ByteViewerTransferable(byteString); } + else if (copyType == PYTHON_BYTE_STRING_TYPE) { + String byteString = "b'" + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", "\\x") + "'"; + return new ByteViewerTransferable(byteString); + } + else if (copyType == PYTHON_LIST_TYPE) { + String byteString = "[ " + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", ", 0x") + " ]"; + return new ByteViewerTransferable(byteString); + } + else if (copyType == CPP_BYTE_ARRAY_TYPE) { + String byteString = "{ " + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", ", 0x") + " }"; + return new ByteViewerTransferable(byteString); + } return null; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java index 7bec236ec0..9e0d8a4971 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java @@ -46,12 +46,23 @@ public abstract class ByteCopier { public static DataFlavor BYTE_STRING_FLAVOR = createByteStringLocalDataTypeFlavor(); public static DataFlavor BYTE_STRING_NO_SPACES_FLAVOR = createByteStringNoSpacesLocalDataTypeFlavor(); + public static DataFlavor PYTHON_BYTE_STRING_FLAVOR = + createPythonByteStringLocalDataTypeFlavor(); + public static DataFlavor PYTHON_LIST_FLAVOR = createPythonListLocalDataTypeFlavor(); + public static DataFlavor CPP_BYTE_ARRAY_FLAVOR = + createCppByteArrayLocalDataTypeFlavor(); protected static final List EMPTY_LIST = Collections.emptyList(); public static final ClipboardType BYTE_STRING_TYPE = new ClipboardType(BYTE_STRING_FLAVOR, "Byte String"); public static final ClipboardType BYTE_STRING_NO_SPACE_TYPE = new ClipboardType(BYTE_STRING_NO_SPACES_FLAVOR, "Byte String (No Spaces)"); + public static final ClipboardType PYTHON_BYTE_STRING_TYPE = + new ClipboardType(PYTHON_BYTE_STRING_FLAVOR, "Python Byte String"); + public static final ClipboardType PYTHON_LIST_TYPE = + new ClipboardType(PYTHON_LIST_FLAVOR, "Python List"); + public static final ClipboardType CPP_BYTE_ARRAY_TYPE = + new ClipboardType(CPP_BYTE_ARRAY_FLAVOR, "C Array"); private static DataFlavor createByteStringLocalDataTypeFlavor() { @@ -83,6 +94,51 @@ public abstract class ByteCopier { return null; } + private static DataFlavor createPythonByteStringLocalDataTypeFlavor() { + + try { + return new GenericDataFlavor( + DataFlavor.javaJVMLocalObjectMimeType + "; class=java.lang.String", + "Local flavor--Python byte string"); + } + catch (Exception e) { + Msg.showError(ByteCopier.class, null, "Could Not Create Data Flavor", + "Unexpected exception creating data flavor for Python byte string", e); + } + + return null; + } + + private static DataFlavor createPythonListLocalDataTypeFlavor() { + + try { + return new GenericDataFlavor( + DataFlavor.javaJVMLocalObjectMimeType + "; class=java.lang.String", + "Local flavor--Python list"); + } + catch (Exception e) { + Msg.showError(ByteCopier.class, null, "Could Not Create Data Flavor", + "Unexpected exception creating data flavor for Python list", e); + } + + return null; + } + + private static DataFlavor createCppByteArrayLocalDataTypeFlavor() { + + try { + return new GenericDataFlavor( + DataFlavor.javaJVMLocalObjectMimeType + "; class=java.lang.String", + "Local flavor--C++ array"); + } + catch (Exception e) { + Msg.showError(ByteCopier.class, null, "Could Not Create Data Flavor", + "Unexpected exception creating data flavor for C array", e); + } + + return null; + } + protected PluginTool tool; protected Program currentProgram; protected ProgramSelection currentSelection; @@ -392,7 +448,9 @@ public abstract class ByteCopier { public static class ByteViewerTransferable implements Transferable { private final DataFlavor[] flavors = { BYTE_STRING_NO_SPACE_TYPE.getFlavor(), - BYTE_STRING_TYPE.getFlavor(), DataFlavor.stringFlavor }; + BYTE_STRING_TYPE.getFlavor(), PYTHON_BYTE_STRING_TYPE.getFlavor(), + PYTHON_LIST_TYPE.getFlavor(), CPP_BYTE_ARRAY_TYPE.getFlavor(), + DataFlavor.stringFlavor }; private final List flavorList = Arrays.asList(flavors); private final String byteString; @@ -423,6 +481,15 @@ public abstract class ByteCopier { if (flavor.equals(BYTE_STRING_NO_SPACE_TYPE.getFlavor())) { return byteString; } + if (flavor.equals(PYTHON_BYTE_STRING_TYPE.getFlavor())) { + return byteString; + } + if (flavor.equals(PYTHON_LIST_TYPE.getFlavor())) { + return byteString; + } + if (flavor.equals(CPP_BYTE_ARRAY_TYPE.getFlavor())) { + return byteString; + } throw new UnsupportedFlavorException(flavor); } diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java index d14d14e97e..6b778b4974 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java @@ -43,6 +43,9 @@ public class ByteViewerClipboardProvider extends ByteCopier List copyTypesList = new LinkedList<>(); copyTypesList.add(BYTE_STRING_TYPE); copyTypesList.add(BYTE_STRING_NO_SPACE_TYPE); + copyTypesList.add(PYTHON_BYTE_STRING_TYPE); + copyTypesList.add(PYTHON_LIST_TYPE); + copyTypesList.add(CPP_BYTE_ARRAY_TYPE); return copyTypesList; } @@ -117,6 +120,18 @@ public class ByteViewerClipboardProvider extends ByteCopier else if (copyType == BYTE_STRING_NO_SPACE_TYPE) { byteString = copyBytesAsString(currentSelection, false, monitor); } + else if (copyType == PYTHON_BYTE_STRING_TYPE) { + byteString = "b'" + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", "\\x") + "'"; + } + else if (copyType == PYTHON_LIST_TYPE) { + byteString = "[ " + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", ", 0x") + " ]"; + } + else if (copyType == CPP_BYTE_ARRAY_TYPE) { + byteString = "{ " + + copyBytesAsString(currentSelection, true, monitor).replaceAll(" ", ", 0x") + " }"; + } else { return null; }