From 6e19466dc618a6fc916a58cd3efdb1c08b32bd36 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 19 Mar 2021 10:43:34 -0400 Subject: [PATCH] GP-786: Some improvements and docs for the PE and ELF exporters --- .../help/topics/ExporterPlugin/exporter.htm | 30 +++- .../exporter/AbstractExecutableExporter.java | 107 ------------ .../util/exporter/AbstractLoaderExporter.java | 161 ++++++++++++++++++ .../ghidra/app/util/exporter/ElfExporter.java | 18 +- .../ghidra/app/util/exporter/PeExporter.java | 14 +- 5 files changed, 216 insertions(+), 114 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractLoaderExporter.java diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm index 1509a09ba1..4a8ff89bdd 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm @@ -284,6 +284,20 @@ + +

ELF

+ +
+

Writes an ELF program that was imported with the ELF loader back to its original file + layout. Any file-backed bytes that were modified by the user in the program database will + be reflected in the new file.

+ +

Writing back a modified Memory + Map is not supported.

+ +

Relocation bytes are always + restored to their original values, even if the user modifies them.

+

Ghidra Zip File (.gzf)

@@ -320,7 +334,7 @@ + +

PE

+ +
+

Writes a PE program that was imported with the PE loader back to its original file + layout. Any file-backed bytes that were modified by the user in the program database will + be reflected in the new file.

+ +

Writing back a modified Memory + Map is not supported.

+ +

Relocation bytes are always + restored to their original values, even if the user modifies them.

+

XML

diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java deleted file mode 100644 index 490bfda798..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AbstractExecutableExporter.java +++ /dev/null @@ -1,107 +0,0 @@ -/* ### - * 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 ghidra.app.util.exporter; - -import java.io.*; -import java.util.List; -import java.util.Optional; - -import ghidra.app.script.GhidraScript; -import ghidra.app.util.DomainObjectService; -import ghidra.app.util.Option; -import ghidra.framework.model.DomainObject; -import ghidra.program.database.mem.AddressSourceInfo; -import ghidra.program.database.mem.FileBytes; -import ghidra.program.model.address.*; -import ghidra.program.model.listing.Program; -import ghidra.program.model.mem.*; -import ghidra.program.model.reloc.Relocation; -import ghidra.util.HelpLocation; -import ghidra.util.task.TaskMonitor; -import utilities.util.FileUtilities; - -abstract class AbstractExecutableExporter extends Exporter { - - protected AbstractExecutableExporter(String name, String extension, HelpLocation help) { - super(name, extension, help); - } - - @Override - public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, - TaskMonitor monitor) throws IOException, ExporterException { - - if (!(domainObj instanceof Program)) { - log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); - return false; - } - Program program = (Program) domainObj; - Memory memory = program.getMemory(); - - try (OutputStream out = new FileOutputStream(file, false)) { - FileBytes[] fileBytes = memory.getAllFileBytes() - .stream() - .filter((fb) -> fb.getFilename().equals(program.getName())) - .toArray(FileBytes[]::new); - for (FileBytes bytes : fileBytes) { - FileBytesInputStream byteStream = new FileBytesInputStream(bytes); - FileUtilities.copyStreamToStream(byteStream, out, monitor); - } - } - try (RandomAccessFile fout = new RandomAccessFile(file, "rw")) { - Iterable relocs = - () -> program.getRelocationTable().getRelocations(); - for (Relocation reloc : relocs) { - AddressSourceInfo info = memory.getAddressSourceInfo(reloc.getAddress()); - // some relocations report negative offsets - if (info.getFileOffset() >= 0) { - // seek incase we are larger than an int - fout.seek(info.getFileOffset()); - fout.write(reloc.getBytes()); - } - } - } - - return true; - } - - @Override - public List