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