mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 06:59:47 +08:00
Merge remote-tracking branch 'origin/GP-3912_ryanmkurtz_macholibs'
This commit is contained in:
+32
-6
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
+34
-13
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user