Skip to content

Commit

Permalink
Added ElfExporter and PeExporter
Browse files Browse the repository at this point in the history
  • Loading branch information
astrelsky committed Feb 4, 2020
1 parent dc16f29 commit 450b454
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
@@ -0,0 +1,109 @@
/* ###
* 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;

public class ElfExporter extends Exporter {

public ElfExporter() {
super("Elf", "", new HelpLocation("ExporterPlugin", "elf"));
}

@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 {
Optional<FileBytes> fileBytes =
memory.getAllFileBytes().stream()
.filter((fb) -> fb.getFilename().equals(program.getName()))
.findFirst();
if (fileBytes.isPresent()) {
FileBytesInputStream byteStream = new FileBytesInputStream(fileBytes.get());
FileUtilities.copyStreamToFile(byteStream, file, false, monitor);
}
} catch (IOException e) {
throw new ExporterException(e);
}
try (RandomAccessFile fout = new RandomAccessFile(file, "rw")){
final Iterable<Relocation> relocs =
() -> program.getRelocationTable().getRelocations();
for (Relocation reloc : relocs) {
final 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<Option> getOptions(DomainObjectService domainObjectService) {
return EMPTY_OPTIONS;
}

@Override
public void setOptions(List<Option> options) {
}

private static class FileBytesInputStream extends InputStream {

private int pos = 0;
private final FileBytes bytes;

FileBytesInputStream(FileBytes bytes) {
this.bytes = bytes;
}

@Override
public int read() throws IOException {
if (pos < bytes.getSize()) {
return bytes.getModifiedByte(pos++) & 0xff;
}
return -1;
}

}
}
@@ -0,0 +1,109 @@
/* ###
* 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;

public class PeExporter extends Exporter {

public PeExporter() {
super("PE", "exe", new HelpLocation("ExporterPlugin", "pe"));
}

@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 {
Optional<FileBytes> fileBytes =
memory.getAllFileBytes().stream()
.filter((fb) -> fb.getFilename().equals(program.getName()))
.findFirst();
if (fileBytes.isPresent()) {
FileBytesInputStream byteStream = new FileBytesInputStream(fileBytes.get());
FileUtilities.copyStreamToFile(byteStream, file, false, monitor);
}
} catch (IOException e) {
throw new ExporterException(e);
}
try (RandomAccessFile fout = new RandomAccessFile(file, "rw")){
final Iterable<Relocation> relocs =
() -> program.getRelocationTable().getRelocations();
for (Relocation reloc : relocs) {
final 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<Option> getOptions(DomainObjectService domainObjectService) {
return EMPTY_OPTIONS;
}

@Override
public void setOptions(List<Option> options) {
}

private static class FileBytesInputStream extends InputStream {

private int pos = 0;
private final FileBytes bytes;

FileBytesInputStream(FileBytes bytes) {
this.bytes = bytes;
}

@Override
public int read() throws IOException {
if (pos < bytes.getSize()) {
return bytes.getModifiedByte(pos++) & 0xff;
}
return -1;
}

}
}

0 comments on commit 450b454

Please sign in to comment.