mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4371 Added check to RecoverClassesFromRTTIScript to not run when there are unhandled relocations.
This commit is contained in:
parent
59a048fdf2
commit
fd8fcebe09
1 changed files with 63 additions and 60 deletions
|
@ -54,18 +54,10 @@
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import classrecovery.DecompilerScriptUtils;
|
import classrecovery.*;
|
||||||
import classrecovery.RTTIClassRecoverer;
|
|
||||||
import classrecovery.RTTIGccClassRecoverer;
|
|
||||||
import classrecovery.RTTIWindowsClassRecoverer;
|
|
||||||
import classrecovery.RecoveredClass;
|
|
||||||
import classrecovery.RecoveredClassHelper;
|
|
||||||
import generic.theme.GThemeDefaults.Colors.Palette;
|
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||||
import ghidra.app.decompiler.DecompInterface;
|
import ghidra.app.decompiler.DecompInterface;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
|
@ -83,30 +75,15 @@ import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.app.util.opinion.PeLoader;
|
import ghidra.app.util.opinion.PeLoader;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.DataTypeComponent;
|
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
|
||||||
import ghidra.program.model.data.Structure;
|
|
||||||
import ghidra.program.model.listing.Function;
|
|
||||||
import ghidra.program.model.listing.Parameter;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
import ghidra.program.model.reloc.Relocation;
|
||||||
|
import ghidra.program.model.reloc.RelocationTable;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.util.GhidraProgramUtilities;
|
import ghidra.program.util.GhidraProgramUtilities;
|
||||||
import ghidra.service.graph.AttributedEdge;
|
import ghidra.service.graph.*;
|
||||||
import ghidra.service.graph.AttributedGraph;
|
|
||||||
import ghidra.service.graph.AttributedVertex;
|
|
||||||
import ghidra.service.graph.GraphDisplay;
|
|
||||||
import ghidra.service.graph.GraphDisplayOptions;
|
|
||||||
import ghidra.service.graph.GraphDisplayOptionsBuilder;
|
|
||||||
import ghidra.service.graph.GraphDisplayProvider;
|
|
||||||
import ghidra.service.graph.GraphType;
|
|
||||||
import ghidra.service.graph.GraphTypeBuilder;
|
|
||||||
import ghidra.service.graph.VertexShape;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.GraphException;
|
import ghidra.util.exception.GraphException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -184,16 +161,16 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
|
||||||
String errorMsg = validate();
|
String errorMsg = validate();
|
||||||
|
|
||||||
if (!errorMsg.isEmpty()) {
|
if (!errorMsg.isEmpty()) {
|
||||||
println(errorMsg);
|
println(errorMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isGcc() && isWindows()) {
|
if (!isGcc() && isWindows()) {
|
||||||
|
|
||||||
if (!isRttiAnalyzed()) {
|
if (!isRttiAnalyzed()) {
|
||||||
println("Running the RTTIAnalyzer...");
|
println("Running the RTTIAnalyzer...");
|
||||||
analysisMode = AnalysisMode.ENABLED;
|
analysisMode = AnalysisMode.ENABLED;
|
||||||
|
@ -218,8 +195,8 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
|
this, BOOKMARK_FOUND_FUNCTIONS, USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS,
|
||||||
nameVfunctions, hasDebugSymbols, monitor);
|
nameVfunctions, hasDebugSymbols, monitor);
|
||||||
}
|
}
|
||||||
else if (isPE() && isGcc()){
|
else if (isPE() && isGcc()) {
|
||||||
|
|
||||||
println("Program is a gcc compiled PE.");
|
println("Program is a gcc compiled PE.");
|
||||||
|
|
||||||
boolean runGcc;
|
boolean runGcc;
|
||||||
|
@ -250,7 +227,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
runGcc = askYesNo("Gcc Class Recovery Still Under Development",
|
runGcc = askYesNo("Gcc Class Recovery Still Under Development",
|
||||||
"I understand that Gcc class recovery is still under development and my results will be incomplete but want to run this anyway.");
|
"I understand that Gcc class recovery is still under development and my results will be incomplete but want to run this anyway.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runGcc) {
|
if (!runGcc) {
|
||||||
|
@ -439,26 +416,54 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
if (defaultPointerSize != 4 && defaultPointerSize != 8) {
|
if (defaultPointerSize != 4 && defaultPointerSize != 8) {
|
||||||
return ("This script only works on 32 or 64 bit programs");
|
return ("This script only works on 32 or 64 bit programs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that gcc loader or mingw analyzer has fixed the relocations correctly
|
// check that gcc loader or mingw analyzer has fixed the relocations correctly
|
||||||
if(isGcc()) {
|
if (isGcc()) {
|
||||||
|
|
||||||
// first check that there is even rtti by searching the special string in memory
|
// first check that there is even rtti by searching the special string in memory
|
||||||
if (!isStringInProgramMemory("class_type_info")) {
|
if (!isStringInProgramMemory("class_type_info")) {
|
||||||
return ("This program does not contain RTTI.");
|
return ("This program does not contain RTTI.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// then check to see if the special typeinfo namespace is in external space
|
// then check to see if the special typeinfo namespace is in external space
|
||||||
// if so then relocations are present and have not been fixed up because when fixed up
|
// if so then relocations are present and have not been fixed up because when fixed up
|
||||||
// the namespace gets moved to inside program space
|
// the namespace gets moved to inside program space
|
||||||
if(isExternalNamespace("__cxxabiv1::__class_type_info")) {
|
if (isExternalNamespace("__cxxabiv1::__class_type_info")) {
|
||||||
return ("This program's relocations were not correctly fixed so the script cannot " +
|
return ("This program's relocations were not correctly fixed so the script cannot " +
|
||||||
"continue. If this program is mingw this is a known issue and " +
|
"continue. If this program is mingw this is a known issue and " +
|
||||||
"will be fixed in a later release. For all other gcc programs please " +
|
"will be fixed in a later release. For all other gcc programs please " +
|
||||||
"contact the Ghidra team so this issue can be fixed.");
|
"contact the Ghidra team so this issue can be fixed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUnhandledRelocations()) {
|
||||||
|
return ("This program has unhandled elf relocations so cannot continue. Please " +
|
||||||
|
"contact the Ghidra team for assistance.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String();
|
return new String();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasUnhandledRelocations() throws CancelledException {
|
||||||
|
|
||||||
|
RelocationTable relocationTable = currentProgram.getRelocationTable();
|
||||||
|
|
||||||
|
Iterator<Relocation> relocations = relocationTable.getRelocations();
|
||||||
|
|
||||||
|
while (relocations.hasNext()) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
Relocation r = relocations.next();
|
||||||
|
|
||||||
|
if (r.getSymbolName().contains("class_type_info") &&
|
||||||
|
(r.getStatus() != Relocation.Status.APPLIED &&
|
||||||
|
r.getStatus() != Relocation.Status.APPLIED_OTHER &&
|
||||||
|
r.getStatus() != Relocation.Status.SKIPPED)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzeProgramChanges(AddressSetView beforeChanges) throws Exception {
|
private void analyzeProgramChanges(AddressSetView beforeChanges) throws Exception {
|
||||||
|
@ -641,18 +646,17 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to check if executable format is PE
|
* Method to check if executable format is PE
|
||||||
*/
|
*/
|
||||||
private boolean isPE() {
|
private boolean isPE() {
|
||||||
|
|
||||||
if (!PeLoader.PE_NAME.equals(currentProgram.getExecutableFormat())) {
|
if (!PeLoader.PE_NAME.equals(currentProgram.getExecutableFormat())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -669,9 +673,9 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
if (isCompilerSpecGcc) {
|
if (isCompilerSpecGcc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String compiler = currentProgram.getCompiler();
|
String compiler = currentProgram.getCompiler();
|
||||||
if(compiler != null && compiler.contains("gcc")) {
|
if (compiler != null && compiler.contains("gcc")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,7 +704,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
return isGcc;
|
return isGcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to set the global variable isWindows
|
* Method to set the global variable isWindows
|
||||||
|
@ -1575,7 +1578,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
return stringBuffer;
|
return stringBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStringInProgramMemory(String string) {
|
private boolean isStringInProgramMemory(String string) {
|
||||||
|
|
||||||
byte[] byteArrray = string.getBytes();
|
byte[] byteArrray = string.getBytes();
|
||||||
|
@ -1587,19 +1590,19 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExternalNamespace(String path) throws CancelledException {
|
private boolean isExternalNamespace(String path) throws CancelledException {
|
||||||
|
|
||||||
List<Symbol> symbols = NamespaceUtils.getSymbols(path, currentProgram, true);
|
List<Symbol> symbols = NamespaceUtils.getSymbols(path, currentProgram, true);
|
||||||
|
|
||||||
for(Symbol symbol : symbols) {
|
for (Symbol symbol : symbols) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
if(symbol.isExternal() && symbol.getSymbolType().isNamespace()) {
|
if (symbol.isExternal() && symbol.getSymbolType().isNamespace()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue