Merge remote-tracking branch 'origin/GP-3912_ryanmkurtz_macholibs'

This commit is contained in:
Ryan Kurtz
2023-10-05 06:54:55 -04:00
2 changed files with 66 additions and 19 deletions
@@ -29,19 +29,22 @@ import ghidra.app.util.bin.format.macho.dyld.DyldChainedPtr.DyldChainType;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.Library;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.Relocation.Status; import ghidra.program.model.reloc.Relocation.Status;
import ghidra.program.model.reloc.RelocationResult; import ghidra.program.model.reloc.RelocationResult;
import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class DyldChainedFixups { public class DyldChainedFixups {
private MachHeader machoHeader; private MachHeader machoHeader;
private Program program; private Program program;
private List<String> libraryPaths;
private MessageLog log; private MessageLog log;
private TaskMonitor monitor; private TaskMonitor monitor;
private Memory memory; private Memory memory;
@@ -52,13 +55,15 @@ public class DyldChainedFixups {
* *
* @param program The {@link Program} * @param program The {@link Program}
* @param header The Mach-O header * @param header The Mach-O header
* @param libraryPaths A {@link List} of the library paths
* @param log The log * @param log The log
* @param monitor A cancelable task monitor. * @param monitor A cancelable task monitor.
*/ */
public DyldChainedFixups(Program program, MachHeader header, MessageLog log, public DyldChainedFixups(Program program, MachHeader header, List<String> libraryPaths,
TaskMonitor monitor) { MessageLog log, TaskMonitor monitor) {
this.program = program; this.program = program;
this.machoHeader = header; this.machoHeader = header;
this.libraryPaths = libraryPaths;
this.log = log; this.log = log;
this.monitor = monitor; this.monitor = monitor;
this.memory = program.getMemory(); this.memory = program.getMemory();
@@ -265,12 +270,13 @@ public class DyldChainedFixups {
int chainOrdinal = (int) DyldChainedPtr.getOrdinal(pointerFormat, chainValue); int chainOrdinal = (int) DyldChainedPtr.getOrdinal(pointerFormat, chainValue);
long addend = DyldChainedPtr.getAddend(pointerFormat, chainValue); long addend = DyldChainedPtr.getAddend(pointerFormat, chainValue);
DyldChainedImport chainedImport = chainedImports.getChainedImport(chainOrdinal); DyldChainedImport chainedImport = chainedImports.getChainedImport(chainOrdinal);
//int libOrdinal = chainedImport.getLibOrdinal();
symName = chainedImport.getName(); symName = chainedImport.getName();
// lookup the symbol, and then add addend // lookup the symbol, and then add addend
List<Symbol> globalSymbols = program.getSymbolTable().getGlobalSymbols(symName); List<Symbol> globalSymbols = program.getSymbolTable().getGlobalSymbols(symName);
if (globalSymbols.size() == 1) { if (globalSymbols.size() == 1) {
newChainValue = globalSymbols.get(0).getAddress().getOffset(); Symbol symbol = globalSymbols.get(0);
newChainValue = symbol.getAddress().getOffset();
fixupExternalLibrary(chainedImport.getLibOrdinal(), symbol);
} }
newChainValue += addend; newChainValue += addend;
} }
@@ -288,7 +294,9 @@ public class DyldChainedFixups {
// lookup the symbol, and then add addend // lookup the symbol, and then add addend
List<Symbol> globalSymbols = program.getSymbolTable().getGlobalSymbols(symName); List<Symbol> globalSymbols = program.getSymbolTable().getGlobalSymbols(symName);
if (globalSymbols.size() == 1) { if (globalSymbols.size() == 1) {
newChainValue = globalSymbols.get(0).getAddress().getOffset(); Symbol symbol = globalSymbols.get(0);
newChainValue = symbol.getAddress().getOffset();
fixupExternalLibrary(chainedImport.getLibOrdinal(), symbol);
} }
newChainValue = newChainValue + auth_value_add; newChainValue = newChainValue + auth_value_add;
} }
@@ -326,6 +334,24 @@ public class DyldChainedFixups {
} }
} }
private void fixupExternalLibrary(int libraryOrdinal, Symbol symbol) {
ExternalManager extManager = program.getExternalManager();
int libraryIndex = libraryOrdinal - 1;
if (libraryIndex >= 0 && libraryIndex < libraryPaths.size()) {
Library library = extManager.getExternalLibrary(libraryPaths.get(libraryIndex));
ExternalLocation loc =
extManager.getUniqueExternalLocation(Library.UNKNOWN, symbol.getName());
if (loc != null) {
try {
loc.setName(library, symbol.getName(), SourceType.IMPORTED);
}
catch (InvalidInputException e) {
log.appendException(e);
}
}
}
}
/** /**
* Fixes up any chained pointers, starting at the given address. * Fixes up any chained pointers, starting at the given address.
* *
@@ -127,12 +127,12 @@ public class MachoProgramBuilder {
processStubs(); processStubs();
processUndefinedSymbols(); processUndefinedSymbols();
processAbsoluteSymbols(); processAbsoluteSymbols();
List<Address> chainedFixups = processChainedFixups(machoHeader); List<String> libraryPaths = processLibraries();
processBindings(false); List<Address> chainedFixups = processChainedFixups(libraryPaths);
processBindings(false, libraryPaths);
processSectionRelocations(); processSectionRelocations();
processExternalRelocations(); processExternalRelocations();
processLocalRelocations(); processLocalRelocations();
processLibraries();
processEncryption(); processEncryption();
processUnsupportedLoadCommands(); processUnsupportedLoadCommands();
@@ -742,18 +742,19 @@ public class MachoProgramBuilder {
} }
} }
public List<Address> processChainedFixups(MachHeader header) throws Exception { public List<Address> processChainedFixups(List<String> libraryPaths) throws Exception {
DyldChainedFixups dyldChainedFixups = new DyldChainedFixups(program, header, log, monitor); DyldChainedFixups dyldChainedFixups =
new DyldChainedFixups(program, machoHeader, libraryPaths, log, monitor);
return dyldChainedFixups.processChainedFixups(); return dyldChainedFixups.processChainedFixups();
} }
protected void processBindings(boolean doClassic) throws Exception { protected void processBindings(boolean doClassic, List<String> libraryPaths) throws Exception {
List<DyldInfoCommand> commands = machoHeader.getLoadCommands(DyldInfoCommand.class); List<DyldInfoCommand> commands = machoHeader.getLoadCommands(DyldInfoCommand.class);
for (DyldInfoCommand command : commands) { for (DyldInfoCommand command : commands) {
processBindings(command.getBindingTable()); processBindings(command.getBindingTable(), libraryPaths);
processBindings(command.getLazyBindingTable()); processBindings(command.getLazyBindingTable(), libraryPaths);
processBindings(command.getWeakBindingTable()); processBindings(command.getWeakBindingTable(), libraryPaths);
} }
if (commands.size() == 0 && doClassic) { if (commands.size() == 0 && doClassic) {
@@ -777,7 +778,7 @@ public class MachoProgramBuilder {
} }
} }
private void processBindings(BindingTable bindingTable) throws Exception { private void processBindings(BindingTable bindingTable, List<String> libraryPaths) throws Exception {
DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian()); DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
SymbolTable symbolTable = program.getSymbolTable(); SymbolTable symbolTable = program.getSymbolTable();
@@ -787,7 +788,7 @@ public class MachoProgramBuilder {
if (threadedBindings != null) { if (threadedBindings != null) {
DyldChainedFixups dyldChainedFixups = DyldChainedFixups dyldChainedFixups =
new DyldChainedFixups(program, machoHeader, log, monitor); new DyldChainedFixups(program, machoHeader, libraryPaths, log, monitor);
DyldChainedImports chainedImports = new DyldChainedImports(bindings); DyldChainedImports chainedImports = new DyldChainedImports(bindings);
for (Binding threadedBinding : threadedBindings) { for (Binding threadedBinding : threadedBindings) {
List<Address> fixedAddresses = new ArrayList<>(); List<Address> fixedAddresses = new ArrayList<>();
@@ -819,6 +820,8 @@ public class MachoProgramBuilder {
Address addr = Address addr =
space.getAddress(segments.get(binding.getSegmentIndex()).getVMaddress() + space.getAddress(segments.get(binding.getSegmentIndex()).getVMaddress() +
binding.getSegmentOffset()); binding.getSegmentOffset());
fixupExternalLibrary(binding.getLibraryOrdinal(), symbol, libraryPaths);
boolean success = false; boolean success = false;
try { try {
@@ -838,6 +841,20 @@ public class MachoProgramBuilder {
} }
} }
private void fixupExternalLibrary(int libraryOrdinal, Symbol symbol, List<String> libraryPaths)
throws InvalidInputException {
ExternalManager extManager = program.getExternalManager();
int libraryIndex = libraryOrdinal - 1;
if (libraryIndex >= 0 && libraryIndex < libraryPaths.size()) {
Library library = extManager.getExternalLibrary(libraryPaths.get(libraryIndex));
ExternalLocation loc =
extManager.getUniqueExternalLocation(Library.UNKNOWN, symbol.getName());
if (loc != null) {
loc.setName(library, symbol.getName(), SourceType.IMPORTED);
}
}
}
protected void markupHeaders(MachHeader header, Address headerAddr) throws Exception { protected void markupHeaders(MachHeader header, Address headerAddr) throws Exception {
monitor.setMessage("Processing header markup..."); monitor.setMessage("Processing header markup...");
@@ -1143,15 +1160,16 @@ public class MachoProgramBuilder {
performRelocations(relocationMap); performRelocations(relocationMap);
} }
protected void processLibraries() throws Exception { protected List<String> processLibraries() throws Exception {
monitor.setMessage("Processing libraries..."); monitor.setMessage("Processing libraries...");
Options props = program.getOptions(Program.PROGRAM_INFO); Options props = program.getOptions(Program.PROGRAM_INFO);
int libraryIndex = 0; int libraryIndex = 0;
List<String> libraryPaths = new ArrayList<>();
for (LoadCommand command : machoHeader.getLoadCommands()) { for (LoadCommand command : machoHeader.getLoadCommands()) {
if (monitor.isCancelled()) { if (monitor.isCancelled()) {
return; return libraryPaths;
} }
String libraryPath = null; String libraryPath = null;
@@ -1168,6 +1186,7 @@ public class MachoProgramBuilder {
} }
if (libraryPath != null) { if (libraryPath != null) {
libraryPaths.add(libraryPath);
int index = libraryPath.lastIndexOf("/"); int index = libraryPath.lastIndexOf("/");
String libraryName = index != -1 ? libraryPath.substring(index + 1) : libraryPath; String libraryName = index != -1 ? libraryPath.substring(index + 1) : libraryPath;
if (!libraryName.equals(program.getName())) { if (!libraryName.equals(program.getName())) {
@@ -1182,6 +1201,8 @@ public class MachoProgramBuilder {
if (program.getSymbolTable().getLibrarySymbol(Library.UNKNOWN) == null) { if (program.getSymbolTable().getLibrarySymbol(Library.UNKNOWN) == null) {
program.getSymbolTable().createExternalLibrary(Library.UNKNOWN, SourceType.IMPORTED); program.getSymbolTable().createExternalLibrary(Library.UNKNOWN, SourceType.IMPORTED);
} }
return libraryPaths;
} }
/** /**