Skip to content

Commit

Permalink
GP-2075 Updated RecoverClassesFromRTTI script to fixup generic deleti…
Browse files Browse the repository at this point in the history
…ng destructor names into vector and scalar ones for windows programs and split into two functions when necessary.
  • Loading branch information
ghidra007 committed Jun 8, 2022
1 parent eb0a23a commit 02db970
Showing 1 changed file with 176 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
private static final int NONE = -1;
private static final int UNKNOWN = -2;

private static final String DELETING_DESTRUCTOR = "deleting_destructor";
private static final String SCALAR_DELETING_DESCTRUCTOR = "scalar_deleting_destructor";
private static final String VECTOR_DELETING_DESCTRUCTOR = "vector_deleting_destructor";

boolean isPDBLoaded;

public RTTIWindowsClassRecoverer(Program program, ProgramLocation location, PluginTool tool,
Expand Down Expand Up @@ -177,6 +181,10 @@ public List<RecoveredClass> createRecoveredClasses() throws Exception {
// create better vftable labels for multi vftable classes
updateMultiVftableLabels(recoveredClasses);
removeEmptyClassesAndStructures();

// fix up deleting destructors to have vector and scalar names and to split
// non-contiguous ones into two seaparate functions
fixUpDeletingDestructors(recoveredClasses);
}

return recoveredClasses;
Expand Down Expand Up @@ -2660,4 +2668,172 @@ private void updateMultiVftableLabels(List<RecoveredClass> recoveredClasses)
}
}

/**
* Method to fixup previously found deleting destructors's symbols to determine if they are
* scalar or vector ones and name appropriately. In the non-contiguous case, split into two
* functions and name accordingly.
* @param recoveredClasses the list of classes to processes
* @throws CancelledException if cancelled
*/
private void fixUpDeletingDestructors(List<RecoveredClass> recoveredClasses)
throws CancelledException {

List<Function> processedFunctions = new ArrayList<>();

for (RecoveredClass recoveredClass : recoveredClasses) {
monitor.checkCanceled();

List<Function> deletingDestructors = recoveredClass.getDeletingDestructors();

if (deletingDestructors.isEmpty()) {
continue;
}

for (Function function : deletingDestructors) {
monitor.checkCanceled();

if (processedFunctions.contains(function)) {
continue;
}

AddressSetView body = function.getBody();
int numAddressRanges = body.getNumAddressRanges();

// fixup contigous dd function
if (numAddressRanges == 1) {
fixupContiguousDeletingDestructorSymbols(function);
processedFunctions.add(function);
}
else if (numAddressRanges == 2) {
// else fixup split dd function
Function scalarDeletingDestructor = createSplitDeletingDestructorFunction(body);
if (scalarDeletingDestructor == null) {
Msg.debug(this, "Could not fixup split deleting destructor function: " +
function.getEntryPoint());
continue;
}
fixupSplitDeletingDestructorSymbols(function, scalarDeletingDestructor);
processedFunctions.add(function);
}
// else if > 2 do nothing - not sure how to handle or even if they exist
}
}
}

/**
* Method to fixup the given functoin as a contiguous deleting destructor which means it is
* both a scalar and vector deleting destructor and needs both names. Some functions are deleting
* destructors for multiple classes so all of the symbols need to be updated.
* @param function the given function
* @throws CancelledException if cancelled
*/
private void fixupContiguousDeletingDestructorSymbols(Function function)
throws CancelledException {

Symbol[] functionSymbols = symbolTable.getSymbols(function.getEntryPoint());

Address functionAddress = function.getEntryPoint();

api.createBookmark(functionAddress, "Deleting Destructor Fixup",
"Scalar and Vector Deleting Destructor");

try {
for (Symbol functionSymbol : functionSymbols) {
monitor.checkCanceled();

// skip any symbols at function that are not dds ie fid mangled names
if (!functionSymbol.getName().contains(DELETING_DESTRUCTOR)) {
continue;
}

functionSymbol.setName(SCALAR_DELETING_DESCTRUCTOR, functionSymbol.getSource());

Symbol secondaryLabel = symbolTable.createLabel(functionAddress,
VECTOR_DELETING_DESCTRUCTOR, SourceType.ANALYSIS);
secondaryLabel.setNamespace(functionSymbol.getParentNamespace());

}
}
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
Msg.debug(this,
"Could not fixup one or more deleting destructor symbols for function: " +
functionAddress);
}
}

/**
* Method to create a second function in the case where a deleting destructor is of the type
* vector dd function jumps to scalar dd function and fixup the jump to be a call return flow
* override
* @param body the given function body
* @return the newly created jumped to function or null if it cannot be created
*/
private Function createSplitDeletingDestructorFunction(AddressSetView body) {

if (body.getNumAddressRanges() != 2) {
return null;
}
AddressRange firstRange = body.getFirstRange();
Address maxAddressofFirstRange = firstRange.getMaxAddress();
Instruction instructionContaining =
api.getInstructionContaining(maxAddressofFirstRange);
if (!instructionContaining.getFlowType().isJump()) {
return null;
}
AddressRange lastRange = body.getLastRange();
Address minAddressOfLastRange = lastRange.getMinAddress();
Reference reference =
api.getReference(instructionContaining, minAddressOfLastRange);
if (reference == null) {
return null;
}
instructionContaining.setFlowOverride(FlowOverride.CALL_RETURN);
Function newFunction = api.createFunction(minAddressOfLastRange, null);
return newFunction;
}

/**
* Method to fixup the deleting destructor symbols in a split deleting destructor case given
* the two functions split earlier from the original function. Some functions are deleting
* destructors for multiple classes so all of the symbols need to be updated.
* @param vectorDDFunction the vector deleting destructor function
* @param scalarDDFunction the scalar deleting destructor function
* @throws CancelledException if cancelled
*/
private void fixupSplitDeletingDestructorSymbols(Function vectorDDFunction,
Function scalarDDFunction) throws CancelledException {

Symbol[] functionSymbols = symbolTable.getSymbols(vectorDDFunction.getEntryPoint());

try {
for (Symbol functionSymbol : functionSymbols) {
monitor.checkCanceled();

// skip any symbols at function that are not dds ie fid mangled names
if (!functionSymbol.getName().contains(DELETING_DESTRUCTOR)) {
continue;
}

functionSymbol.setName(VECTOR_DELETING_DESCTRUCTOR, functionSymbol.getSource());

Symbol secondaryLabel = symbolTable.createLabel(scalarDDFunction.getEntryPoint(),
SCALAR_DELETING_DESCTRUCTOR, SourceType.ANALYSIS);
secondaryLabel.setNamespace(functionSymbol.getParentNamespace());

}
}
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
Msg.debug(this,
"Could not fixup one or more deleting destructor symbols for split functions: " +
vectorDDFunction.getEntryPoint() + " and " + scalarDDFunction.getEntryPoint());
}

api.createBookmark(scalarDDFunction.getEntryPoint(), "Deleting Destructor Fixup",
"Scalar Deleting Destructor");
api.createBookmark(vectorDDFunction.getEntryPoint(), "Deleting Destructor Fixup",
"Vector Deleting Destructor");

}

}

0 comments on commit 02db970

Please sign in to comment.