mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-2016 addressing code review suggestions
GP-2016_short_wide_character_format_strings
This commit is contained in:
parent
37a8ffb492
commit
c6f174dffb
2 changed files with 52 additions and 49 deletions
|
@ -99,8 +99,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(AddressSetView selection, TaskMonitor monitor)
|
private void run(AddressSetView selection, TaskMonitor monitor) throws CancelledException {
|
||||||
throws CancelledException {
|
|
||||||
|
|
||||||
DefinedDataIterator dataIterator = DefinedDataIterator.definedStrings(currentProgram);
|
DefinedDataIterator dataIterator = DefinedDataIterator.definedStrings(currentProgram);
|
||||||
Map<Address, Data> stringsByAddress = new HashMap<>();
|
Map<Address, Data> stringsByAddress = new HashMap<>();
|
||||||
|
@ -114,7 +113,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
FunctionIterator functionIterator = currentProgram.getListing().getFunctions(true);
|
FunctionIterator functionIterator = currentProgram.getListing().getFunctions(true);
|
||||||
FunctionIterator externalIterator = currentProgram.getListing().getExternalFunctions();
|
FunctionIterator externalIterator = currentProgram.getListing().getExternalFunctions();
|
||||||
Iterator<Function> programFunctionIterator = IteratorUtils.chainedIterator(functionIterator,externalIterator);
|
Iterator<Function> programFunctionIterator =
|
||||||
|
IteratorUtils.chainedIterator(functionIterator, externalIterator);
|
||||||
Map<String, List<DataType>> namesToParameters = new HashMap<>();
|
Map<String, List<DataType>> namesToParameters = new HashMap<>();
|
||||||
|
|
||||||
Map<String, DataType> namesToReturn = new HashMap<>();
|
Map<String, DataType> namesToReturn = new HashMap<>();
|
||||||
|
@ -124,22 +124,21 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
// Find variadic function names and their parameter data types
|
// Find variadic function names and their parameter data types
|
||||||
for (Function function : IteratorUtils.asIterable(programFunctionIterator)) {
|
for (Function function : IteratorUtils.asIterable(programFunctionIterator)) {
|
||||||
String name = function.getName().strip();
|
String name = function.getName().strip();
|
||||||
if (usesVariadicFormatString(function)) {
|
if (usesVariadicFormatString(function)) {
|
||||||
for (String variadicSubstring : VARIADIC_SUBSTRINGS) {
|
for (String variadicSubstring : VARIADIC_SUBSTRINGS) {
|
||||||
if (name.contains(variadicSubstring)) {
|
if (name.contains(variadicSubstring)) {
|
||||||
variadicFunctionNames.add(name);
|
variadicFunctionNames.add(name);
|
||||||
namesToParameters.put(name, getParameters(function));
|
namesToParameters.put(name, getParameters(function));
|
||||||
namesToReturn.put(name, function.getReturnType());
|
namesToReturn.put(name, function.getReturnType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<Function> functionsToSearchIterator = selection != null
|
Iterator<Function> functionsToSearchIterator = selection != null
|
||||||
? currentProgram.getFunctionManager()
|
? currentProgram.getFunctionManager().getFunctionsOverlapping(selection)
|
||||||
.getFunctionsOverlapping(selection)
|
|
||||||
: currentProgram.getFunctionManager().getFunctionsNoStubs(true);
|
: currentProgram.getFunctionManager().getFunctionsNoStubs(true);
|
||||||
|
|
||||||
// Find functions that call variadic functions
|
// Find functions that call variadic functions
|
||||||
|
@ -157,14 +156,11 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
decompile(currentProgram, monitor, stringsByAddress, variadicFunctionNames,
|
decompile(currentProgram, monitor, stringsByAddress, variadicFunctionNames,
|
||||||
namesToParameters,
|
namesToParameters, namesToReturn, toDecompile);
|
||||||
namesToReturn,
|
|
||||||
toDecompile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decompile(Program program, TaskMonitor monitor,
|
private void decompile(Program program, TaskMonitor monitor,
|
||||||
Map<Address, Data> stringsByAddress,
|
Map<Address, Data> stringsByAddress, Set<String> variadicFunctionNames,
|
||||||
Set<String> variadicFunctionNames,
|
|
||||||
Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn,
|
Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn,
|
||||||
Set<Function> toDecompile) {
|
Set<Function> toDecompile) {
|
||||||
|
|
||||||
|
@ -187,11 +183,9 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecompilerCallback<Void> initDecompilerCallback(Program program,
|
private DecompilerCallback<Void> initDecompilerCallback(Program program,
|
||||||
Map<Address, Data> stringsByAddress,
|
Map<Address, Data> stringsByAddress, Set<String> variadicFuncNames,
|
||||||
Set<String> variadicFuncNames, Map<String, List<DataType>> namesToParameters,
|
Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn) {
|
||||||
Map<String, DataType> namesToReturn) {
|
return new DecompilerCallback<>(program, new VariadicSignatureDecompileConfigurer()) {
|
||||||
return new DecompilerCallback<>(program,
|
|
||||||
new VariadicSignatureDecompileConfigurer()) {
|
|
||||||
@Override
|
@Override
|
||||||
public Void process(DecompileResults results, TaskMonitor tMonitor) throws Exception {
|
public Void process(DecompileResults results, TaskMonitor tMonitor) throws Exception {
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
|
@ -211,8 +205,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
pcodeOpASTs.add(pcodeAST);
|
pcodeOpASTs.add(pcodeAST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<FunctionCallData> functionCallDataList = pcodeParser.parseFunctionForCallData(
|
List<FunctionCallData> functionCallDataList = pcodeParser
|
||||||
pcodeOpASTs, stringsByAddress, variadicFuncNames);
|
.parseFunctionForCallData(pcodeOpASTs, stringsByAddress, variadicFuncNames);
|
||||||
if (functionCallDataList != null && functionCallDataList.size() > 0) {
|
if (functionCallDataList != null && functionCallDataList.size() > 0) {
|
||||||
overrideCallList(program, function, functionCallDataList, namesToParameters,
|
overrideCallList(program, function, functionCallDataList, namesToParameters,
|
||||||
namesToReturn);
|
namesToReturn);
|
||||||
|
@ -256,7 +250,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
// DecompInterface allows for control of decompilation processes
|
// DecompInterface allows for control of decompilation processes
|
||||||
@Override
|
@Override
|
||||||
public void configure(DecompInterface decompiler) {
|
public void configure(DecompInterface decompiler) {
|
||||||
decompiler.toggleCCode(true); // Produce C code
|
decompiler.toggleCCode(false); //only need syntax tree
|
||||||
decompiler.toggleSyntaxTree(true); // Produce syntax tree
|
decompiler.toggleSyntaxTree(true); // Produce syntax tree
|
||||||
decompiler.openProgram(currentProgram);
|
decompiler.openProgram(currentProgram);
|
||||||
decompiler.setSimplificationStyle("normalize");
|
decompiler.setSimplificationStyle("normalize");
|
||||||
|
@ -266,8 +260,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParameterDefinition[] parseParameters(Function function,
|
private ParameterDefinition[] parseParameters(Function function, Address address,
|
||||||
Address address,
|
|
||||||
String callFunctionName, String formatString,
|
String callFunctionName, String formatString,
|
||||||
Map<String, List<DataType>> namesToParameters) {
|
Map<String, List<DataType>> namesToParameters) {
|
||||||
|
|
||||||
|
@ -347,8 +340,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
private void overrideFunctionCall(Program program, Function function, Address address,
|
private void overrideFunctionCall(Program program, Function function, Address address,
|
||||||
String callFunctionName, String formatString,
|
String callFunctionName, String formatString,
|
||||||
Map<String, List<DataType>> namesToParameters,
|
Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn) {
|
||||||
Map<String, DataType> namesToReturn) {
|
|
||||||
if (formatString == null) {
|
if (formatString == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -361,14 +353,14 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
|
||||||
try {
|
try {
|
||||||
if (createBookmarksEnabled) {
|
if (createBookmarksEnabled) {
|
||||||
BookmarkManager bookmark = program.getBookmarkManager();
|
BookmarkManager bookmark = program.getBookmarkManager();
|
||||||
bookmark.setBookmark(address, BookmarkType.ANALYSIS,
|
bookmark.setBookmark(address, BookmarkType.ANALYSIS, "Function Signature Override",
|
||||||
"Function Signature Override",
|
|
||||||
"Override for call to function " + callFunctionName);
|
"Override for call to function " + callFunctionName);
|
||||||
}
|
}
|
||||||
HighFunctionDBUtil.writeOverride(function, address, functionSignature);
|
HighFunctionDBUtil.writeOverride(function, address, functionSignature);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
Msg.error(this, "Error: invalid input given to writeOverride()", e);
|
Msg.warn(this,
|
||||||
|
"Error applying override to " + address.toString() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,12 @@ import java.util.*;
|
||||||
|
|
||||||
import ghidra.docking.settings.SettingsImpl;
|
import ghidra.docking.settings.SettingsImpl;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.StringDataInstance;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.StringDataType;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBufferImpl;
|
import ghidra.program.model.mem.MemoryBufferImpl;
|
||||||
import ghidra.program.model.pcode.PcodeOpAST;
|
import ghidra.program.model.pcode.PcodeOpAST;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for parsing functions' Pcode representations and finding variadic
|
* Class for parsing functions' Pcode representations and finding variadic
|
||||||
|
@ -84,7 +84,7 @@ public class PcodeFunctionParser {
|
||||||
boolean hasDefinedFormatString = searchForVariadicCallData(ast,
|
boolean hasDefinedFormatString = searchForVariadicCallData(ast,
|
||||||
addressToCandidateData, functionCallDataList, functionName);
|
addressToCandidateData, functionCallDataList, functionName);
|
||||||
if (!hasDefinedFormatString) {
|
if (!hasDefinedFormatString) {
|
||||||
searchForHiddenFormatStrings(ast, functionCallDataList, functionName);
|
searchForHiddenFormatStrings(ast, functionCallDataList, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,20 +116,28 @@ public class PcodeFunctionParser {
|
||||||
// If addrToCandidateData doesn't have format String data for this call
|
// If addrToCandidateData doesn't have format String data for this call
|
||||||
// and we are calling a variadic function, parse the String to determine
|
// and we are calling a variadic function, parse the String to determine
|
||||||
// whether it's a format String.
|
// whether it's a format String.
|
||||||
private void searchForHiddenFormatStrings(PcodeOpAST ast,
|
private void searchForHiddenFormatStrings(PcodeOpAST callOp,
|
||||||
List<FunctionCallData> functionCallDataList, String functionName) {
|
List<FunctionCallData> functionCallDataList, Function function) {
|
||||||
|
|
||||||
Varnode[] inputs = ast.getInputs();
|
Varnode[] inputs = callOp.getInputs();
|
||||||
// Initialize i = 1 to skip first input
|
// Initialize i = 1 to skip first input, which is the call target
|
||||||
for (int i = 1; i < inputs.length; ++i) {
|
for (int i = 1; i < inputs.length; ++i) {
|
||||||
Varnode v = inputs[i];
|
Varnode v = inputs[i];
|
||||||
String formatStringCandidate = findFormatString(v.getAddress());
|
Parameter param = function.getParameter(i - 1);
|
||||||
|
if (param == null || param.getSource().equals(SourceType.DEFAULT)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DataType type = param.getDataType();
|
||||||
|
if ((type == null) || !(type instanceof Pointer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String formatStringCandidate = findFormatString(v.getAddress(), (Pointer) type);
|
||||||
if (formatStringCandidate == null) {
|
if (formatStringCandidate == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (formatStringCandidate.contains("%")) {
|
if (formatStringCandidate.contains("%")) {
|
||||||
functionCallDataList.add(new FunctionCallData(ast.getSeqnum().getTarget(),
|
functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
|
||||||
functionName, formatStringCandidate));
|
function.getName(), formatStringCandidate));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -145,9 +153,10 @@ public class PcodeFunctionParser {
|
||||||
* Looks at bytes at given address and converts to format String
|
* Looks at bytes at given address and converts to format String
|
||||||
*
|
*
|
||||||
* @param address Address of format String
|
* @param address Address of format String
|
||||||
|
* @param pointer Pointer "type" of string
|
||||||
* @return format String
|
* @return format String
|
||||||
*/
|
*/
|
||||||
private String findFormatString(Address address) {
|
private String findFormatString(Address address, Pointer pointer) {
|
||||||
|
|
||||||
if (!address.getAddressSpace().isConstantSpace()) {
|
if (!address.getAddressSpace().isConstantSpace()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -159,9 +168,11 @@ public class PcodeFunctionParser {
|
||||||
MemoryBufferImpl memoryBuffer =
|
MemoryBufferImpl memoryBuffer =
|
||||||
new MemoryBufferImpl(this.program.getMemory(), ramSpaceAddress);
|
new MemoryBufferImpl(this.program.getMemory(), ramSpaceAddress);
|
||||||
|
|
||||||
StringDataInstance stringDataInstance = StringDataInstance
|
DataType charType = pointer.getDataType();
|
||||||
.getStringDataInstance(new StringDataType(), memoryBuffer, SettingsImpl.NO_SETTINGS,
|
//StringDataInstace.getStringDataInstance checks that charType is appropriate
|
||||||
BUFFER_LENGTH);
|
//and returns StringDataInstace.NULL_INSTANCE if not
|
||||||
|
StringDataInstance stringDataInstance = StringDataInstance.getStringDataInstance(charType,
|
||||||
|
memoryBuffer, SettingsImpl.NO_SETTINGS, BUFFER_LENGTH);
|
||||||
String stringValue = stringDataInstance.getStringValue();
|
String stringValue = stringDataInstance.getStringValue();
|
||||||
if (stringValue == null) {
|
if (stringValue == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue