mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-4103: Fixing issue with loading Mach-O Rust binaries
This commit is contained in:
parent
53275c92f8
commit
9dd1a3fb10
8 changed files with 61 additions and 49 deletions
|
@ -21,7 +21,8 @@ public class RustConstants {
|
|||
public static final CategoryPath RUST_CATEGORYPATH = new CategoryPath("/rust");
|
||||
public static final byte[] RUST_SIGNATURE_1 = "RUST_BACKTRACE".getBytes();
|
||||
public static final byte[] RUST_SIGNATURE_2 = "/rustc/".getBytes();
|
||||
public static final String RUST_EXTENSIONS_PATH = "/extensions/rust/";
|
||||
public static final String RUST_EXTENSIONS_PATH = "extensions/rust/";
|
||||
public static final String RUST_EXTENSIONS_UNIX = "unix";
|
||||
public static final String RUST_EXTENSIONS_WINDOWS = "windows";
|
||||
public static final String RUST_COMPILER = "rustc";
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public class RustStringAnalyzer extends AbstractAnalyzer {
|
|||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
String name = program.getCompiler();
|
||||
return name.contains("rustc");
|
||||
return name.contains(RustConstants.RUST_COMPILER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,9 +98,9 @@ public class RustStringAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
/**
|
||||
* Get the number of bytes to the next reference, or the max length
|
||||
* @param program
|
||||
* @param address
|
||||
* @param maxLen
|
||||
* @param program The {@link Program}
|
||||
* @param address The {@link Address}
|
||||
* @param maxLen The maximum length
|
||||
* @return maximum length to create the string
|
||||
*/
|
||||
private static int getMaxStringLength(Program program, Address address, int maxLen) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import ghidra.app.plugin.processors.sleigh.SleighException;
|
|||
import ghidra.framework.Application;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.SpecExtension;
|
||||
import ghidra.program.model.lang.Processor;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -36,50 +37,51 @@ import ghidra.xml.XmlParseException;
|
|||
*/
|
||||
public class RustUtilities {
|
||||
/**
|
||||
* Checks if a given {@link Program} was written in Rust
|
||||
* Checks if a given {@link MemoryBlock} contains a Rust signature
|
||||
*
|
||||
* @param program The {@link Program} to check
|
||||
* @param blockName The name of the {@link MemoryBlock} to scan for Rust signatures
|
||||
* @return True if the given {@link Program} was written in Rust; otherwise, false
|
||||
* @param block The {@link MemoryBlock} to scan for Rust signatures
|
||||
* @return True if the given {@link MemoryBlock} is not null and contains a Rust signature;
|
||||
* otherwise, false
|
||||
* @throws IOException if there was an IO-related error
|
||||
*/
|
||||
public static boolean isRust(Program program, String blockName) throws IOException {
|
||||
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||
for (MemoryBlock block : blocks) {
|
||||
if (block.getName().equals(blockName)) {
|
||||
byte[] bytes = block.getData().readAllBytes();
|
||||
if (containsBytes(bytes, RustConstants.RUST_SIGNATURE_1)) {
|
||||
return true;
|
||||
}
|
||||
if (containsBytes(bytes, RustConstants.RUST_SIGNATURE_2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public static boolean isRust(MemoryBlock block) throws IOException {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
byte[] bytes = block.getData().readAllBytes();
|
||||
if (containsBytes(bytes, RustConstants.RUST_SIGNATURE_1)) {
|
||||
return true;
|
||||
}
|
||||
if (containsBytes(bytes, RustConstants.RUST_SIGNATURE_2)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int addExtensions(Program program, TaskMonitor monitor, String subPath)
|
||||
throws IOException {
|
||||
var processor = program.getLanguageCompilerSpecPair().getLanguage().getProcessor();
|
||||
Processor processor = program.getLanguageCompilerSpecPair().getLanguage().getProcessor();
|
||||
ResourceFile module = Application.getModuleDataSubDirectory(processor.toString(),
|
||||
RustConstants.RUST_EXTENSIONS_PATH + subPath);
|
||||
|
||||
int extensionCount = 0;
|
||||
|
||||
ResourceFile[] files = module.listFiles();
|
||||
for (ResourceFile file : files) {
|
||||
InputStream stream = file.getInputStream();
|
||||
byte[] bytes = stream.readAllBytes();
|
||||
String xml = new String(bytes);
|
||||
if (files != null) {
|
||||
for (ResourceFile file : files) {
|
||||
InputStream stream = file.getInputStream();
|
||||
byte[] bytes = stream.readAllBytes();
|
||||
String xml = new String(bytes);
|
||||
|
||||
try {
|
||||
SpecExtension extension = new SpecExtension(program);
|
||||
extension.addReplaceCompilerSpecExtension(xml, monitor);
|
||||
extensionCount += 1;
|
||||
}
|
||||
catch (SleighException | SAXException | XmlParseException | LockException e) {
|
||||
Msg.error(program, "Failed to load load cspec extensions");
|
||||
try {
|
||||
SpecExtension extension = new SpecExtension(program);
|
||||
extension.addReplaceCompilerSpecExtension(xml, monitor);
|
||||
extensionCount++;
|
||||
}
|
||||
catch (SleighException | SAXException | XmlParseException | LockException e) {
|
||||
Msg.error(RustUtilities.class,
|
||||
"Failed to load Rust cspec extension: " + file.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.analysis.rust.demangler;
|
||||
|
||||
import ghidra.app.plugin.core.analysis.rust.RustConstants;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
|
@ -35,7 +36,7 @@ public class RustDemangler implements Demangler {
|
|||
@Override
|
||||
public boolean canDemangle(Program program) {
|
||||
String name = program.getCompiler();
|
||||
return name != null && name.contains("rustc");
|
||||
return name != null && name.contains(RustConstants.RUST_COMPILER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.plugin.core.datamgr.util;
|
|||
import java.util.*;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.plugin.core.analysis.rust.RustConstants;
|
||||
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
|
||||
import ghidra.app.util.opinion.*;
|
||||
import ghidra.framework.Application;
|
||||
|
@ -144,7 +145,7 @@ public class DataTypeArchiveUtility {
|
|||
list.add("generic_clib");
|
||||
}
|
||||
|
||||
if (program.getCompiler().contains("rustc")) {
|
||||
if (program.getCompiler().contains(RustConstants.RUST_COMPILER)) {
|
||||
list.add("rust-common");
|
||||
}
|
||||
|
||||
|
|
|
@ -2443,15 +2443,15 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
private void setCompiler(TaskMonitor monitor) {
|
||||
// Check for Rust
|
||||
try {
|
||||
if (RustUtilities.isRust(program, ElfSectionHeaderConstants.dot_rodata)) {
|
||||
if (RustUtilities.isRust(memory.getBlock(ElfSectionHeaderConstants.dot_rodata))) {
|
||||
program.setCompiler(RustConstants.RUST_COMPILER);
|
||||
int extensionCount = RustUtilities.addExtensions(program, monitor,
|
||||
RustConstants.RUST_EXTENSIONS_UNIX);
|
||||
log.appendMsg("Installed " + extensionCount + " Rust cspec extensions");
|
||||
program.setCompiler("rustc");
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.appendException(e);
|
||||
log.appendMsg("Rust error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1694,16 +1694,23 @@ public class MachoProgramBuilder {
|
|||
protected void setCompiler() {
|
||||
// Check for Rust
|
||||
try {
|
||||
if (RustUtilities.isRust(program,
|
||||
SegmentNames.SEG_TEXT + "." + SectionNames.TEXT_CONST)) {
|
||||
SegmentCommand segment = machoHeader.getSegment(SegmentNames.SEG_TEXT);
|
||||
if (segment == null) {
|
||||
return;
|
||||
}
|
||||
Section section = segment.getSectionByName(SectionNames.TEXT_CONST);
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
if (RustUtilities.isRust(memory.getBlock(space.getAddress(section.getAddress())))) {
|
||||
program.setCompiler(RustConstants.RUST_COMPILER);
|
||||
int extensionCount = RustUtilities.addExtensions(program, monitor,
|
||||
RustConstants.RUST_EXTENSIONS_UNIX);
|
||||
log.appendMsg("Installed " + extensionCount + " Rust cspec extensions");
|
||||
program.setCompiler("rustc");
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.appendException(e);
|
||||
log.appendMsg("Rust error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -902,7 +902,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
BorlandCpp("borland:c++", "borlandcpp"),
|
||||
BorlandUnk("borland:unknown", "borlandcpp"),
|
||||
CLI("cli", "cli"),
|
||||
Rustc("rustc", "rustc"),
|
||||
Rustc(RustConstants.RUST_COMPILER, RustConstants.RUST_COMPILER),
|
||||
GOLANG("golang", "golang"),
|
||||
Unknown("unknown", "unknown"),
|
||||
|
||||
|
@ -958,16 +958,16 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
DOSHeader dh = pe.getDOSHeader();
|
||||
|
||||
// Check for Rust. Program object is required, which may be null.
|
||||
try {
|
||||
if (program != null && RustUtilities.isRust(program, ".rdata")) {
|
||||
if (program != null && RustUtilities.isRust(program.getMemory().getBlock(".rdata"))) {
|
||||
try {
|
||||
int extensionCount = RustUtilities.addExtensions(program, monitor,
|
||||
RustConstants.RUST_EXTENSIONS_WINDOWS);
|
||||
log.appendMsg("Installed " + extensionCount + " Rust cspec extensions");
|
||||
return CompilerEnum.Rustc;
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.appendException(e);
|
||||
catch (IOException e) {
|
||||
log.appendMsg("Rust error: " + e.getMessage());
|
||||
}
|
||||
return CompilerEnum.Rustc;
|
||||
}
|
||||
|
||||
// Check for managed code (.NET)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue