GP-2384 prevent variadic override analyzer from examining too many args

This commit is contained in:
James
2022-08-12 15:22:23 +00:00
parent aad60ecdd3
commit fbdcf16498

View File

@@ -21,8 +21,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBufferImpl;
import ghidra.program.model.pcode.PcodeOpAST;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.pcode.*;
import ghidra.program.model.symbol.SourceType;
/**
@@ -37,7 +36,6 @@ public class PcodeFunctionParser {
// is too short or contains escape characters that thwart the
// ASCII string analyzer
private static final int NULL_TERMINATOR_PROBE = -1;
private static final String CALL_INSTRUCTION = "CALL";
private Program program;
@@ -62,71 +60,69 @@ public class PcodeFunctionParser {
return null;
}
List<FunctionCallData> functionCallDataList = new ArrayList<>();
for (PcodeOpAST ast : pcodeOps) {
Varnode firstNode = ast.getInput(0);
if (firstNode == null) {
for (PcodeOpAST callOp : pcodeOps) {
if (callOp.getOpcode() != PcodeOp.CALL) {
continue;
}
if (ast.getMnemonic().contentEquals(CALL_INSTRUCTION)) {
FunctionManager functionManager = this.program.getFunctionManager();
Function function = functionManager.getFunctionAt(firstNode.getAddress());
if (function == null) {
return null;
}
String functionName = function.getName();
if (variadicFunctionNames.contains(functionName)) {
Varnode[] inputs = ast.getInputs();
if (inputs.length > 0) {
boolean hasDefinedFormatString = searchForVariadicCallData(ast,
addressToCandidateData, functionCallDataList, functionName);
if (!hasDefinedFormatString) {
searchForHiddenFormatStrings(ast, functionCallDataList, function);
}
}
}
Varnode callTarget = callOp.getInput(0);
if (callTarget == null) {
continue;
}
FunctionManager functionManager = program.getFunctionManager();
Function function = functionManager.getFunctionAt(callTarget.getAddress());
if (function == null) {
continue;
}
String functionName = function.getName();
if (!variadicFunctionNames.contains(functionName)) {
continue;
}
// <= since first input of callOp is call target and
// so not a function argument
if (callOp.getNumInputs() <= function.getParameterCount()) {
continue;
}
boolean hasDefinedFormatString = searchForVariadicCallData(callOp,
addressToCandidateData, functionCallDataList, function);
if (!hasDefinedFormatString) {
searchForHiddenFormatStrings(callOp, functionCallDataList, function);
}
}
return functionCallDataList;
}
private boolean searchForVariadicCallData(PcodeOpAST ast,
private boolean searchForVariadicCallData(PcodeOpAST callOp,
Map<Address, Data> addressToCandidateData, List<FunctionCallData> functionCallDataList,
String functionName) {
boolean hasDefinedFormatString = false;
Varnode[] inputs = ast.getInputs();
for (int i = 1; i < inputs.length; i++) {
Varnode v = inputs[i];
Data data = null;
Address ramSpaceAddress = convertAddressToRamSpace(v.getAddress());
if (addressToCandidateData.containsKey(ramSpaceAddress)) {
data = addressToCandidateData.get(ramSpaceAddress);
functionCallDataList.add(new FunctionCallData(ast.getSeqnum().getTarget(),
functionName, data.getDefaultValueRepresentation()));
hasDefinedFormatString = true;
}
else {
//check for offcut references into a larger defined string
Data containing = program.getListing().getDataContaining(ramSpaceAddress);
if (containing == null) {
continue;
}
if (addressToCandidateData.containsKey(containing.getAddress())) {
StringDataInstance entire =
StringDataInstance.getStringDataInstance(containing);
String subString = entire.getByteOffcut(
Function function) {
//format string should be last parameter of Function ("..." doesn't count as a parameter)
//don't subtract 1 since input 0 is the call target
Varnode v = callOp.getInput(function.getParameterCount());
Data data = null;
Address ramSpaceAddress = convertAddressToRamSpace(v.getAddress());
if (addressToCandidateData.containsKey(ramSpaceAddress)) {
data = addressToCandidateData.get(ramSpaceAddress);
functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
function.getName(), data.getDefaultValueRepresentation()));
return true;
}
//check for offcut references into a larger defined string
Data containing = program.getListing().getDataContaining(ramSpaceAddress);
if (containing == null) {
return false;
}
if (addressToCandidateData.containsKey(containing.getAddress())) {
StringDataInstance entire = StringDataInstance.getStringDataInstance(containing);
String subString = entire
.getByteOffcut(
(int) (ramSpaceAddress.getOffset() - containing.getAddress().getOffset()))
.getStringValue();
if (subString != null) {
functionCallDataList.add(new FunctionCallData(ast.getSeqnum().getTarget(),
functionName, subString));
hasDefinedFormatString = true;
}
}
.getStringValue();
if (subString != null) {
functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
function.getName(), subString));
return true;
}
}
return hasDefinedFormatString;
return false;
}
// If addrToCandidateData doesn't have format String data for this call
@@ -135,27 +131,24 @@ public class PcodeFunctionParser {
private void searchForHiddenFormatStrings(PcodeOpAST callOp,
List<FunctionCallData> functionCallDataList, Function function) {
Varnode[] inputs = callOp.getInputs();
// Initialize i = 1 to skip first input, which is the call target
for (int i = 1; i < inputs.length; ++i) {
Varnode v = inputs[i];
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 = findNullTerminatedString(v.getAddress(), (Pointer) type);
if (formatStringCandidate == null) {
continue;
}
if (formatStringCandidate.contains("%")) {
functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
function.getName(), formatStringCandidate));
}
break;
int formatStringSlot = function.getParameterCount() - 1;
Parameter param = function.getParameter(formatStringSlot);
if (param == null || param.getSource().equals(SourceType.DEFAULT)) {
return;
}
DataType type = param.getDataType();
if ((type == null) || !(type instanceof Pointer)) {
return;
}
//+1 since first input of callOp is call target address
String formatStringCandidate = findNullTerminatedString(
callOp.getInput(formatStringSlot + 1).getAddress(), (Pointer) type);
if (formatStringCandidate == null) {
return;
}
if (formatStringCandidate.contains("%")) {
functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
function.getName(), formatStringCandidate));
}
}