mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-10-24 14:11:11 +00:00
Merge remote-tracking branch 'origin/GP-2504_Arm_common_switchpattern--SQUASHED'
This commit is contained in:
commit
adc3d1b570
|
@ -16,8 +16,7 @@
|
|||
package ghidra.app.analyzers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||
|
@ -29,7 +28,8 @@ import ghidra.app.util.PseudoDisassemblerContext;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -84,19 +84,29 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
protected AddressSet postreqFailedResult = null; // Discovered pattern, but a post req failed (not following a defined thing)
|
||||
protected ArrayList<RegisterValue> contextValueList = null;
|
||||
|
||||
private static ProgramDecisionTree getPatternDecisionTree() {
|
||||
private static ProgramDecisionTree initializePatternDecisionTree() {
|
||||
if (patternDecisitionTree == null) {
|
||||
patternDecisitionTree = Patterns.getPatternDecisionTree();
|
||||
}
|
||||
return patternDecisitionTree;
|
||||
}
|
||||
|
||||
public ProgramDecisionTree getPatternDecisionTree() {
|
||||
return initializePatternDecisionTree();
|
||||
}
|
||||
|
||||
public FunctionStartAnalyzer() {
|
||||
this(NAME, AnalyzerType.BYTE_ANALYZER);
|
||||
}
|
||||
|
||||
public FunctionStartAnalyzer(String name, AnalyzerType analyzerType) {
|
||||
super(name, DESCRIPTION, analyzerType);
|
||||
this(name, DESCRIPTION, analyzerType);
|
||||
|
||||
}
|
||||
|
||||
public FunctionStartAnalyzer(String name, String description, AnalyzerType analyzerType) {
|
||||
super(name, description, analyzerType);
|
||||
|
||||
setPriority(AnalysisPriority.CODE_ANALYSIS.after().after());
|
||||
setDefaultEnablement(true);
|
||||
setSupportsOneTimeAnalysis();
|
||||
|
@ -148,20 +158,14 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
contextValueList = null;
|
||||
}
|
||||
|
||||
private void setDisassemblerContext(Program program, DisassemblerContext pcont) {
|
||||
private void setDisassemblerContext(Program program, PseudoDisassemblerContext pcont, Address addr) {
|
||||
if (contextValueList == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<RegisterValue> iterator = contextValueList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RegisterValue contextValue = iterator.next();
|
||||
|
||||
try {
|
||||
pcont.setRegisterValue(contextValue);
|
||||
}
|
||||
catch (ContextChangeException e) {
|
||||
// context conflicts cause problems, let already layed down context win.
|
||||
}
|
||||
pcont.setValue(contextValue.getRegister(), addr, contextValue.getUnsignedValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,20 +199,29 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
|
||||
public class FunctionStartAction implements MatchAction {
|
||||
|
||||
private static final int MUST_HAVE_VALID_INSTRUCTIONS_NO_MIN = -1; // no minimum
|
||||
private static final int VALID_INSTRUCTIONS_NO_MAX = -1; // no maximum on instructions to check
|
||||
private static final int NO_VALID_INSTRUCTIONS_REQUIRED = 0;
|
||||
|
||||
private String afterName = null;
|
||||
private int validcode = 0; // -1 means in a valid subroutine
|
||||
private int validCodeMin = NO_VALID_INSTRUCTIONS_REQUIRED;
|
||||
private int validCodeMax = VALID_INSTRUCTIONS_NO_MAX;
|
||||
private String label = null;
|
||||
private boolean isThunk = false; // true if this function should be turned into a thunk
|
||||
private boolean noreturn = false; // true to set function non-returning
|
||||
boolean validFunction = false; // must be defined at a function
|
||||
private boolean contiguous = true; // require validcode instructions be contiguous
|
||||
|
||||
@Override
|
||||
public void apply(Program program, Address addr, Match match) {
|
||||
if (!checkPreRequisites(program, addr)) {
|
||||
// didn't match, get rid of contextValueList
|
||||
contextValueList = null;
|
||||
return;
|
||||
}
|
||||
|
||||
applyActionToSet(program, addr, funcResult, match);
|
||||
contextValueList = null;
|
||||
}
|
||||
|
||||
protected boolean checkPreRequisites(Program program, Address addr) {
|
||||
|
@ -233,23 +246,32 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
}
|
||||
|
||||
// do we require some number of valid instructions
|
||||
if (validcode != 0) {
|
||||
if (validCodeMin != 0) {
|
||||
PseudoDisassembler pseudoDisassembler = new PseudoDisassembler(program);
|
||||
PseudoDisassemblerContext pcont =
|
||||
new PseudoDisassemblerContext(program.getProgramContext());
|
||||
setDisassemblerContext(program, pcont);
|
||||
|
||||
setDisassemblerContext(program, pcont, addr);
|
||||
boolean isvalid = false;
|
||||
if (validcode == -1) {
|
||||
isvalid = pseudoDisassembler.checkValidSubroutine(addr, pcont, true, true);
|
||||
if (validCodeMin == -1) {
|
||||
if (validCodeMax > 0) { // check at most N instructions
|
||||
pseudoDisassembler.setMaxInstructions(validCodeMax);
|
||||
}
|
||||
isvalid = pseudoDisassembler.checkValidSubroutine(addr, pcont, true, true, contiguous);
|
||||
}
|
||||
else {
|
||||
pseudoDisassembler.setMaxInstructions(validcode);
|
||||
isvalid = pseudoDisassembler.checkValidSubroutine(addr, pcont, true, false);
|
||||
if (validCodeMax > 0) { // check at most N instructions
|
||||
pseudoDisassembler.setMaxInstructions(validCodeMax);
|
||||
}
|
||||
if (!isvalid) {
|
||||
return false;
|
||||
// disassemble only fallthru, must have validcode number of instructions
|
||||
isvalid = pseudoDisassembler.checkValidSubroutine(addr, pcont, true, false, contiguous);
|
||||
int instrCount = pseudoDisassembler.getLastCheckValidInstructionCount();
|
||||
if (instrCount < validCodeMin) {
|
||||
isvalid = false;
|
||||
}
|
||||
}
|
||||
return isvalid;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -387,6 +409,10 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if (name.startsWith("ptr")) {
|
||||
// if there are only pure data references to the location
|
||||
return pureDataReferencesOnly(program, addr);
|
||||
}
|
||||
else if (name.startsWith("def")) {
|
||||
// make sure there is something at location to check
|
||||
Instruction instr = program.getListing().getInstructionContaining(addrToCheck);
|
||||
|
@ -400,8 +426,38 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
if (data != null) {
|
||||
return true;
|
||||
}
|
||||
// if there are only pure data references to the location
|
||||
return pureDataReferencesOnly(program, addr);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are only pure data references to the location
|
||||
*
|
||||
* @param program program to check
|
||||
* @param addrToCheck location to check
|
||||
* @return true if there are only pure data references (no flow, or r/w)
|
||||
*/
|
||||
private boolean pureDataReferencesOnly(Program program, Address addrToCheck) {
|
||||
ReferenceIterator referencesTo = program.getReferenceManager().getReferencesTo(addrToCheck);
|
||||
if (!referencesTo.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
for (Reference reference : referencesTo) {
|
||||
RefType refType = reference.getReferenceType();
|
||||
if (refType.isFlow()) {
|
||||
return false;
|
||||
}
|
||||
if (refType.isRead() || refType.isWrite()) {
|
||||
return false;
|
||||
}
|
||||
if (refType.isData()) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -494,8 +550,14 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
}
|
||||
|
||||
protected void restoreXmlAttributes(XmlElement el) {
|
||||
if (el.hasAttribute("after")) {
|
||||
afterName = el.getAttribute("after");
|
||||
Map<String, String> attributes = el.getAttributes();
|
||||
Set<String> keySet = attributes.keySet();
|
||||
for (String attrName : keySet) {
|
||||
String attrValue = attributes.get(attrName);
|
||||
attrName = attrName.toLowerCase();
|
||||
switch (attrName) {
|
||||
case "after":
|
||||
afterName = attrValue;
|
||||
if (afterName.startsWith("func")) {
|
||||
hasCodeConstraints = true;
|
||||
}
|
||||
|
@ -505,6 +567,9 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
else if (afterName.startsWith("data")) {
|
||||
hasDataConstraints = true;
|
||||
}
|
||||
else if (afterName.startsWith("ptr")) {
|
||||
hasDataConstraints = true;
|
||||
}
|
||||
else if (afterName.startsWith("def")) {
|
||||
hasCodeConstraints = hasDataConstraints = true;
|
||||
}
|
||||
|
@ -512,34 +577,86 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa
|
|||
Msg.error(this,
|
||||
"funcstart pattern attribute 'after' must be one of 'function', 'instruction', 'data', 'defined'");
|
||||
}
|
||||
}
|
||||
if (el.hasAttribute("validcode")) {
|
||||
validcode = 8;
|
||||
String validcodeStr = el.getAttribute("validcode");
|
||||
break;
|
||||
|
||||
// set check for valid code and the minimum number of instructions required
|
||||
// if no maximum is set, then the instructions MUST be fallthru instructions, don't check branch flows
|
||||
case "validcode":
|
||||
String validcodeStr = attrValue;
|
||||
if (validcodeStr.equals("0") || validcodeStr.equals("false")) {
|
||||
validcode = 0;
|
||||
validCodeMin = NO_VALID_INSTRUCTIONS_REQUIRED;
|
||||
}
|
||||
else if (validcodeStr.equalsIgnoreCase("true") ||
|
||||
validcodeStr.equalsIgnoreCase("subroutine")) { // must be a valid subroutine
|
||||
validcode = -1;
|
||||
validCodeMin = MUST_HAVE_VALID_INSTRUCTIONS_NO_MIN;
|
||||
}
|
||||
else if (validcodeStr.equalsIgnoreCase("function")) { // must be at a defined subroutine
|
||||
else if (validcodeStr.equalsIgnoreCase("function")) { // must be at a defined function
|
||||
validFunction = true;
|
||||
hasFunctionStartConstraints = true;
|
||||
hasFunctionStartConstraints = true; // enable FunctionStartFuncAnalyzer to run
|
||||
validCodeMin = NO_VALID_INSTRUCTIONS_REQUIRED;
|
||||
}
|
||||
else { // must have <N> valid instruction run
|
||||
validcode = Integer.parseInt(validcodeStr);
|
||||
else { // must have <N> valid fallthru instruction to match
|
||||
validCodeMin = Integer.parseInt(validcodeStr);
|
||||
}
|
||||
if (validCodeMax == VALID_INSTRUCTIONS_NO_MAX) {
|
||||
// if no maximum instructions to check, only check the minimum number
|
||||
validCodeMax = validCodeMin;
|
||||
}
|
||||
if (el.hasAttribute("label")) {
|
||||
String name = el.getAttribute("label");
|
||||
break;
|
||||
|
||||
// set the maximum number of instructions to check
|
||||
// if maximum is set, then allow non fallthru instructions while flowing
|
||||
case "validcodemax":
|
||||
String validcodeMaxStr = attrValue;
|
||||
// check up <N> instructions for valid code
|
||||
validCodeMax = Integer.parseInt(validcodeMaxStr);
|
||||
if (validCodeMin == NO_VALID_INSTRUCTIONS_REQUIRED) {
|
||||
// if set a max and no minimum yet, must have some number of instructions
|
||||
// if a validcode minimum is set later, will override this default
|
||||
validCodeMin = MUST_HAVE_VALID_INSTRUCTIONS_NO_MIN;
|
||||
}
|
||||
break;
|
||||
|
||||
// minimum number of instructions for validcode must be contiguous instructions
|
||||
case "contiguous":
|
||||
String fallThruOnlyStr = attrValue;
|
||||
// check up <N> instructions for valid code
|
||||
contiguous = true;
|
||||
if (fallThruOnlyStr.equalsIgnoreCase("false")) {
|
||||
contiguous = false;
|
||||
}
|
||||
else if (fallThruOnlyStr.equalsIgnoreCase("true")) {
|
||||
contiguous = true;
|
||||
} else {
|
||||
Msg.error(this, "Bad contiguous option (true,false): " + attrName + " = " + attrValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case "label":
|
||||
String name = attrValue;
|
||||
label = name;
|
||||
}
|
||||
if (el.hasAttribute("thunk")) {
|
||||
break;
|
||||
|
||||
case "thunk":
|
||||
isThunk = true;
|
||||
}
|
||||
if (el.hasAttribute("noreturn")) {
|
||||
break;
|
||||
|
||||
case "noreturn":
|
||||
noreturn = true;
|
||||
break;
|
||||
|
||||
// TODO: add the ability to make data based on a pattern of bytes
|
||||
// useful after defined instructions/functions to take up filler byte patterns
|
||||
// will allow more finding of code that is after defined data
|
||||
// case "data":
|
||||
// String validcodeDataStr = attrValue;
|
||||
// // create undefined data of the given size
|
||||
// makeData = Integer.parseInt(validcodeDataStr);
|
||||
// break;
|
||||
|
||||
default:
|
||||
Msg.error(this, "Unknown Patten option: " + attrName + " = " + attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.analyzers;
|
||||
|
||||
import ghidra.app.services.AnalysisPriority;
|
||||
import ghidra.app.services.AnalyzerType;
|
||||
import ghidra.util.constraint.ProgramDecisionTree;
|
||||
|
||||
public class FunctionStartPreFuncAnalyzer extends FunctionStartAnalyzer {
|
||||
|
||||
protected static final String FUNCTION_START_PRE_SEARCH = "Function Start Pre Search";
|
||||
|
||||
private static final String DESCRIPTION =
|
||||
"Search for architecture/compiler specific patterns that are better found before any code is disassembled, " +
|
||||
"such as known patterns for ARM functions that handle switch tables and don't return.";
|
||||
|
||||
private static ProgramDecisionTree prePatternDecisitionTree;
|
||||
|
||||
private static ProgramDecisionTree initializePatternDecisionTree() {
|
||||
if (prePatternDecisitionTree == null) {
|
||||
prePatternDecisitionTree = Patterns.getPatternDecisionTree("prepatternconstraints.xml");
|
||||
}
|
||||
return prePatternDecisitionTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramDecisionTree getPatternDecisionTree() {
|
||||
return initializePatternDecisionTree();
|
||||
}
|
||||
|
||||
public FunctionStartPreFuncAnalyzer() {
|
||||
super(FUNCTION_START_PRE_SEARCH, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||
|
||||
setPriority(AnalysisPriority.BLOCK_ANALYSIS.after());
|
||||
setDefaultEnablement(true);
|
||||
setSupportsOneTimeAnalysis();
|
||||
}
|
||||
}
|
|
@ -20,8 +20,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import generic.constraint.DecisionSet;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.Application;
|
||||
|
@ -32,14 +30,20 @@ import ghidra.xml.XmlParseException;
|
|||
|
||||
public class Patterns {
|
||||
|
||||
private static final String PATTERN_FILE_NAME = "patternfile";
|
||||
private static final String DATA_PATTERNS = "data/patterns";
|
||||
public static final String DEFAULT_PATTERNCONSTRAINTS_XML = "patternconstraints.xml";
|
||||
|
||||
private static final String PATTERN_FILE_NAME_XMLTAG = "patternfile";
|
||||
private static final String DATA_PATTERNS_SUBDIR = "data/patterns";
|
||||
|
||||
public static ProgramDecisionTree getPatternDecisionTree() {
|
||||
List<ResourceFile> patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS);
|
||||
List<ResourceFile> patternConstraintFiles = findPatternConstraintFiles(patternDirs);
|
||||
return getPatternDecisionTree(DEFAULT_PATTERNCONSTRAINTS_XML);
|
||||
}
|
||||
|
||||
public static ProgramDecisionTree getPatternDecisionTree(String patternConstraintsFileName) {
|
||||
List<ResourceFile> patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS_SUBDIR);
|
||||
List<ResourceFile> patternConstraintFiles = findPatternConstraintFiles(patternDirs, patternConstraintsFileName);
|
||||
ProgramDecisionTree decisionTree = new ProgramDecisionTree();
|
||||
decisionTree.registerPropertyName(PATTERN_FILE_NAME);
|
||||
decisionTree.registerPropertyName(PATTERN_FILE_NAME_XMLTAG);
|
||||
for (ResourceFile resourceFile : patternConstraintFiles) {
|
||||
try {
|
||||
decisionTree.loadConstraints(resourceFile);
|
||||
|
@ -53,27 +57,27 @@ public class Patterns {
|
|||
}
|
||||
|
||||
public static boolean hasPatternFiles(Program program, ProgramDecisionTree decisionTree) {
|
||||
DecisionSet decisionsSet = decisionTree.getDecisionsSet(program, PATTERN_FILE_NAME);
|
||||
DecisionSet decisionsSet = decisionTree.getDecisionsSet(program, PATTERN_FILE_NAME_XMLTAG);
|
||||
return !decisionsSet.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find any pattern files associated with this program
|
||||
* @param program find pattern files associated with this program
|
||||
* @param decisionTree decision tree parsed from getPatternDecisionTree
|
||||
* @return the array of File objects, one for each file
|
||||
* @throws IOException
|
||||
* @throws FileNotFoundException
|
||||
* @throws SAXException
|
||||
* @throws XmlParseException
|
||||
* @throws IOException pattern file could not be read
|
||||
* @throws FileNotFoundException pattern file not found
|
||||
* @throws XmlParseException pattern file had an XML parse error
|
||||
*/
|
||||
public static ResourceFile[] findPatternFiles(Program program, ProgramDecisionTree decisionTree)
|
||||
throws FileNotFoundException, IOException, XmlParseException {
|
||||
|
||||
DecisionSet decisionsSet = decisionTree.getDecisionsSet(program, PATTERN_FILE_NAME);
|
||||
DecisionSet decisionsSet = decisionTree.getDecisionsSet(program, PATTERN_FILE_NAME_XMLTAG);
|
||||
List<String> values = decisionsSet.getValues();
|
||||
|
||||
List<ResourceFile> patternFileList = new ArrayList<ResourceFile>();
|
||||
List<ResourceFile> patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS);
|
||||
List<ResourceFile> patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS_SUBDIR);
|
||||
|
||||
for (String patternFileName : values) {
|
||||
patternFileList.add(getPatternFile(patternDirs, patternFileName));
|
||||
|
@ -93,12 +97,12 @@ public class Patterns {
|
|||
throw new FileNotFoundException("can't find pattern file: " + patternFileName);
|
||||
}
|
||||
|
||||
private static List<ResourceFile> findPatternConstraintFiles(List<ResourceFile> patternDirs) {
|
||||
private static List<ResourceFile> findPatternConstraintFiles(List<ResourceFile> patternDirs, String constraintsFileName) {
|
||||
|
||||
List<ResourceFile> patternConstraintFiles = new ArrayList<ResourceFile>();
|
||||
|
||||
for (ResourceFile dir : patternDirs) {
|
||||
ResourceFile file = new ResourceFile(dir, "patternconstraints.xml");
|
||||
ResourceFile file = new ResourceFile(dir, constraintsFileName);
|
||||
if (file.exists()) {
|
||||
patternConstraintFiles.add(file);
|
||||
}
|
||||
|
|
|
@ -324,10 +324,11 @@ public class EHDataTypeUtilities {
|
|||
public static boolean createFunctionIfNeeded(Program program, Address functionAddress) {
|
||||
// If there isn't an instruction at the function address yet, then disassemble there.
|
||||
Listing listing = program.getListing();
|
||||
functionAddress =
|
||||
Address normalizedFunctionAddress =
|
||||
PseudoDisassembler.getNormalizedDisassemblyAddress(program, functionAddress);
|
||||
Instruction inst = listing.getInstructionAt(functionAddress);
|
||||
Instruction inst = listing.getInstructionAt(normalizedFunctionAddress);
|
||||
if (inst == null) {
|
||||
functionAddress = PseudoDisassembler.setTargeContextForDisassembly(program, functionAddress);
|
||||
DisassembleCommand cmd = new DisassembleCommand(functionAddress, null, true);
|
||||
if (!cmd.applyTo(program) || cmd.getDisassembledAddressSet().isEmpty()) {
|
||||
Msg.error(EHDataTypeUtilities.class, "Failed to disassemble at " + functionAddress);
|
||||
|
@ -337,12 +338,12 @@ public class EHDataTypeUtilities {
|
|||
|
||||
// If there isn't a function at the function address yet, then try to create one there.
|
||||
FunctionManager functionManager = program.getFunctionManager();
|
||||
Function function = functionManager.getFunctionAt(functionAddress);
|
||||
Function function = functionManager.getFunctionAt(normalizedFunctionAddress);
|
||||
if (function == null) {
|
||||
CreateFunctionCmd cmd = new CreateFunctionCmd(functionAddress);
|
||||
CreateFunctionCmd cmd = new CreateFunctionCmd(normalizedFunctionAddress);
|
||||
if (!cmd.applyTo(program)) {
|
||||
Msg.error(EHDataTypeUtilities.class,
|
||||
"Failed to create function at " + functionAddress);
|
||||
"Failed to create function at " + normalizedFunctionAddress);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ public class PseudoDisassembler {
|
|||
|
||||
private boolean respectExecuteFlag = false;
|
||||
|
||||
private int lastCheckValidDisassemblyCount; // number of last instructions disassembled
|
||||
|
||||
/**
|
||||
* Create a pseudo disassembler for the given program.
|
||||
*/
|
||||
|
@ -95,6 +97,14 @@ public class PseudoDisassembler {
|
|||
maxInstructions = maxNumInstructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last number of disassembled instructions
|
||||
* or the number of initial contiguous instruction if requireContiguous is true
|
||||
*/
|
||||
public int getLastCheckValidInstructionCount() {
|
||||
return lastCheckValidDisassemblyCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag to respect Execute bit on memory if present on any memory
|
||||
*
|
||||
|
@ -583,6 +593,15 @@ public class PseudoDisassembler {
|
|||
|
||||
public boolean checkValidSubroutine(Address entryPoint, PseudoDisassemblerContext procContext,
|
||||
boolean allowExistingInstructions, boolean mustTerminate) {
|
||||
return checkValidSubroutine(entryPoint, procContext, allowExistingInstructions, mustTerminate, false);
|
||||
}
|
||||
|
||||
public boolean checkValidSubroutine(Address entryPoint, PseudoDisassemblerContext procContext,
|
||||
boolean allowExistingInstructions, boolean mustTerminate, boolean requireContiguous) {
|
||||
|
||||
AddressSet contiguousSet = new AddressSet();
|
||||
|
||||
lastCheckValidDisassemblyCount = 0;
|
||||
|
||||
if (!entryPoint.isMemoryAddress()) {
|
||||
return false;
|
||||
|
@ -632,6 +651,7 @@ public class PseudoDisassembler {
|
|||
procContext.flowToAddress(target);
|
||||
}
|
||||
PseudoInstruction instr = disassemble(target, procContext, false);
|
||||
|
||||
if (instr == null) {
|
||||
// if the target is in the external section, which is uninitialized, ignore it!
|
||||
// it is probably a JUMP to an external function.
|
||||
|
@ -646,6 +666,12 @@ public class PseudoDisassembler {
|
|||
continue;
|
||||
}
|
||||
|
||||
// count valid instructions encountered, if checking contiguous only count if instructions merge into the first range
|
||||
if (contiguousSet.isEmpty() || !requireContiguous || contiguousSet.getFirstRange().getMaxAddress().isSuccessor(target)) {
|
||||
contiguousSet.add(instr.getMinAddress(),instr.getMaxAddress());
|
||||
lastCheckValidDisassemblyCount++;
|
||||
}
|
||||
|
||||
// check if we are getting into bad instruction runs
|
||||
if (repeatInstructionByteTracker.exceedsRepeatBytePattern(instr)) {
|
||||
return false;
|
||||
|
@ -789,16 +815,17 @@ public class PseudoDisassembler {
|
|||
target = newTarget;
|
||||
}
|
||||
}
|
||||
catch (
|
||||
|
||||
InsufficientBytesException e) {
|
||||
catch (InsufficientBytesException e) {
|
||||
// can't parse not enough bytes
|
||||
return false;
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
// bad instruction
|
||||
return false;
|
||||
}
|
||||
catch (UnknownContextException e) {
|
||||
|
||||
// something wrong with context
|
||||
return false;
|
||||
}
|
||||
|
||||
// get rid of anything on target list that is in body of instruction
|
||||
|
@ -807,12 +834,17 @@ public class PseudoDisassembler {
|
|||
Address targetAddr = iter.next();
|
||||
if (body.contains(targetAddr)) {
|
||||
iter.remove();
|
||||
}
|
||||
// if this target does not refer to an instruction start.
|
||||
if (!instrStarts.contains(targetAddr)) {
|
||||
return false;
|
||||
}
|
||||
} else if (maxInstructions > 0) {
|
||||
// if there was a maximum, then don't worry about targets that
|
||||
// were never followed
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if target list is empty, and we are at a terminal instruction
|
||||
if (targetList.isEmpty() && (didTerminate || !mustTerminate || didCallValidSubroutine)) {
|
||||
|
|
|
@ -21,22 +21,22 @@
|
|||
|
||||
<pattern> <!-- possible function start -->
|
||||
<data> 111..... .1....11 10...... 0xa9 </data> <!-- stp x, x, [sp, -0x.0]! -->
|
||||
<possiblefuncstart after="defined" isvalid="true"/> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="3" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- possible function start -->
|
||||
<data> 0x........ 111..... .1....11 10...... 0xa9 </data> <!-- stp x, x, [sp, -0x.0]! -->
|
||||
<possiblefuncstart after="defined" isvalid="true" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="3" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- possible function start -->
|
||||
<data> 0xfe .0001111 0x1. 0xf8 </data> <!-- stp x30, [sp, #-0x..0]! -->
|
||||
<possiblefuncstart after="defined" isvalid="true"/> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="3" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- possible function start -->
|
||||
<data> 0x........ 0xfe .0001111 0x1. 0xf8 </data> <!-- stp x30, [sp, #-0x..0]! -->
|
||||
<possiblefuncstart after="defined" isvalid="true"/> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="3" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- solid function start -->
|
||||
|
|
|
@ -40,4 +40,6 @@ data/languages/old/THUMBv2.trans||GHIDRA||||END|
|
|||
data/manuals/ARM.idx||GHIDRA||||END|
|
||||
data/patterns/ARM_BE_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/ARM_LE_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/ARM_switch_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/patternconstraints.xml||GHIDRA||||END|
|
||||
data/patterns/prepatternconstraints.xml||GHIDRA||||END|
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
|
||||
<callfixup name="switch8_r3">
|
||||
<target name="switch8_r3"/>
|
||||
<target name="__ARM_common_switch8"/>
|
||||
<pcode>
|
||||
<body><![CDATA[
|
||||
tmpptr = lr - 1;
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
<constraint loader="Portable Executable (PE)">
|
||||
<constraint compilerSpecID="windows">
|
||||
<constraint primary="448" processor="ARM" endian="little" size="32" variant="v8" />
|
||||
<constraint primary="450" processor="ARM" endian="little" size="32" variant="v8T" /> <!-- THUMB -->
|
||||
<constraint primary="452" processor="ARM" endian="little" size="32" variant="v8T" /> <!-- THUMB -->
|
||||
<constraint primary="450" processor="ARM" endian="little" size="32" variant="v8" /> <!-- ARM and Thumb, spec says only Thumb -->
|
||||
<constraint primary="452" processor="ARM" endian="little" size="32" variant="v8" />
|
||||
</constraint>
|
||||
<constraint compilerSpecID="default">
|
||||
<constraint primary="2560" processor="ARM" endian="big" size="32" variant="v8" />
|
||||
|
@ -20,8 +20,8 @@
|
|||
</constraint>
|
||||
<constraint loader="Debug Symbols (DBG)" compilerSpecID="windows">
|
||||
<constraint primary="448" processor="ARM" endian="little" size="32" variant="v8" />
|
||||
<constraint primary="450" processor="ARM" endian="little" size="32" variant="v8T" /> <!-- THUMB -->
|
||||
<constraint primary="452" processor="ARM" endian="little" size="32" variant="v8T" /> <!-- THUMB -->
|
||||
<constraint primary="450" processor="ARM" endian="little" size="32" variant="v8" /> <!-- ARM and Thumb, spec says only Thumb -->
|
||||
<constraint primary="452" processor="ARM" endian="little" size="32" variant="v8" />
|
||||
</constraint>
|
||||
|
||||
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="default">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<data>0xb0 000..... 0xbd ....0000 </data> <!-- add, pop -->
|
||||
<data> 0x00bf </data> <!-- nop -->
|
||||
<data> 0x8000f3af </data> <!-- nop.w -->
|
||||
<data> 0xe8bd 1....... ........ </data> <!-- pop { rlist, pc } -->
|
||||
<data> 0xe8bd 101..... ........ </data> <!-- pop { rlist, pc !lr !sp } -->
|
||||
<data> 0xf746 </data> <!-- mov pc,lr -->
|
||||
<data> 0xf8 0x5d 0xfb 0....... </data> <!-- ldr.w pc,[sp],#0x.. -->
|
||||
</prepatterns>
|
||||
|
@ -31,20 +31,22 @@
|
|||
<data> 0x46 0x.. 0xb5 ....0000 </data> <!-- push, mov -->
|
||||
<data> 01.01...0x.. 0xb5 ....0000 </data> <!-- push, ldr -->
|
||||
<data> 0x68 0x.. 0xb5 ....0000 </data> <!-- push, ldr -->
|
||||
<data> 0xe92d 010..... ........ </data> <!-- push { rlist, lr } -->
|
||||
<data> 0xe92d 0100.... ........ </data> <!-- push { rlist, lr !sp !pc !r12 } -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart/>
|
||||
<funcstart validcode="3"/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<patternpairs totalbits="32" postbits="16"> <!-- 32 bit ARM -->
|
||||
<prepatterns>
|
||||
<data>0xe12fff1. </data> <!-- bx r? -->
|
||||
<data>0xe12fff1e 0x46c0 </data> <!-- bx lr , filler -->
|
||||
<data>0xe12fff1e 0xe1a00000 </data> <!-- bx lr , filler -->
|
||||
<data>0xe12fff1e 0x00000000 </data> <!-- bx lr , filler -->
|
||||
<data>0xea...... </data> <!-- b xxxx probably a shared call return, careful with this, must be a really strong func start after -->
|
||||
<data>0xe8 10.11101 10.0.... 0x.. </data> <!-- ldmia sp!,{pc,...} -->
|
||||
<data>0xe8 10.11101 10.0.... 0x.. 0xe1a00000 </data> <!-- ldmia sp!,{pc,...}; filler -->
|
||||
<data>0xe8 10.11101 10.0.... 0x.. 0x00000000 </data> <!-- ldmia sp!,{pc,...}; filler -->
|
||||
<data>0xe4 0x9d 0xf0 0x08 </data> <!-- ldr pc,[sp],#0x8 -->
|
||||
<data>0xe1 0xa0 0xf0 0x0e </data> <!-- mov pc,lr -->
|
||||
<data>0xe320f000 0xe1a00000 </data> <!-- nop, cpy r0,r0 -->
|
||||
|
@ -52,76 +54,91 @@
|
|||
</prepatterns>
|
||||
|
||||
<postpatterns>
|
||||
<data> 0xe24dd... 11101001 00101101 .1...... ....0000 </data> <!-- sub sp,sp ; stmdb sp!,{r4+,lr} -->
|
||||
<data> 11101001 00101101 .1...... ....0000 0xe24dd... </data> <!-- stmdb sp!,{r4+,lr}; sub sp,sp -->
|
||||
<data> 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... </data> <!-- stmdb sp!,{r4+,lr}; <instr>; sub sp,sp -->
|
||||
<data> 11101001 00101101 .1...... ....0000 0xe1a0 010.0000 0000000. </data> <!-- stmdb sp!,{r4+,lr}; mov r4,r0 -->
|
||||
<data> 11101001 00101101 .1...... ....0000 </data> <!-- stmdb sp!,{r4+,lr}; if the prepattern is strong -->
|
||||
<data> 0xe24dd... 11101001 00101101 0100.... ........ </data> <!-- sub sp,sp ; stmdb sp!,{r3+,lr !sp !pc !r12} -->
|
||||
<data> 11101001 00101101 0100.... ........ 0xe24dd... </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; sub sp,sp -->
|
||||
<data> 11101001 00101101 0100.... ........ 0x........ 0xe24dd... </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; <instr>; sub sp,sp -->
|
||||
<data> 11101001 00101101 0100.... ........ 0xe1a0 010.0000 0000000. </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; mov r4,r0 -->
|
||||
<data> 11101001 00101101 0100.... ........ </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; if the prepattern is strong -->
|
||||
<data> 0xe24dd... 11100101 00101101 1110.... ........ </data> <!-- sub sp,sp; str lr,[sp,#...]; -->
|
||||
<data> 11101001 00101101 .0...... ........ 11100101 00101101 11100000 ......00 </data> <!-- stmdb sp!,{xxx !lr}; str lr,[sp,#...]; -->
|
||||
<data> 11101001 00101101 0000.... ........ 11100101 00101101 11100000 ......00 </data> <!-- stmdb sp!,{r0+, !lr !sp !pc !r12}; str lr,[sp,#...]; -->
|
||||
<data> 11100101 00101101 1110.... ........ 0xe24dd... </data> <!-- str lr,[sp,#...]; sub sp,sp; -->
|
||||
<data> 11100101 00101101 1110.... ........ 0x........ 0xe24dd... </data> <!-- str lr,[sp,#...]; <instr>; sub sp,sp; -->
|
||||
<data> 0xe5 0x2d 0xe0 0x08 </data> <!-- str lr,[sp,#-0x8] -->
|
||||
<data> 0xe1a0c00d 0xe92d.... </data> <!-- cpy ip,sp; stmdb sp!,{} -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart/>
|
||||
<funcstart validcode="3"/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0xe24dd... 11101001 00101101 .1...... ....0000 </data> <!-- sub sp,sp ; stmdb sp!,{r4+,lr} -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> 0xe24dd... 11101001 00101101 0100.... ........ </data> <!-- sub sp,sp ; stmdb sp!,{r0+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary /> <!-- it is at least code -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 11101001 00101101 .1...... ....0000 </data> <!-- stmdb sp!,{r4+,lr}; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> 0xe5 1001.... 0....... ........ 11101001 00101101 0100.... ....0000 </data> <!-- ldr .., xxx ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="data" isvalid="true"/> <!-- must be something defined right before this, and good code -->
|
||||
<codeboundary /> <!-- it is at least code -->
|
||||
<possiblefuncstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 11101001 00101101 .1...... ....0000 </data> <!-- stmdb sp!,{r4+,lr}; <valid code> -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> 0xe....... 11101001 00101101 0100.... ....0000 </data> <!-- Any instruction ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="defined" isvalid="40"/> <!-- must be something defined right before this, && must be at least 40 valid instructions after it -->
|
||||
<funcstart after="ptr" validcode="10" contiguous="true" /> <!-- must be a data ptr (non r/w) to this and validcode -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0xe....... 0xe....... 11101001 00101101 0100.... ....0000 </data> <!-- Any 2 instructions ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="ptr" validcode="10" contiguous="true" /> <!-- must be a data ptr (non r/w) to this and validcode -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 11101001 00101101 0100.... ........ </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; <valid code> -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this, && must be at least 40 valid instructions after it -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0xe24dd... 11100101 00101101 1110.... ........ </data> <!-- sub sp,sp; str lr,[sp,#...]; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>11100101 00101101 1110.... ........ 0xe24dd... </data> <!-- str lr,[sp,#...]; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="data" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... </data> <!-- stmdb sp!,{r4+,lr}; <instr>; sub sp,sp -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="data" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>11100101 00101101 1110.... ........ 0x........ 0xe24dd... </data> <!-- str lr,[sp,#...]; <instr>; sub sp,sp; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="data" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>0xe1a0c00d 0xe92d.... </data> <!-- cpy ip,sp; stmdb sp!,{} -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary /> <!-- can't say it is a function yet, have seen instructions before -->
|
||||
</pattern>
|
||||
|
@ -130,21 +147,21 @@
|
|||
<data> 0xb5 ....0000 0xb0 100..... </data> <!-- push, sub-->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0xe92d 010..... ........ </data> <!-- push { rlist, lr } -->
|
||||
<data> 0xe92d 0100.... ........ </data> <!-- push { rlist, lr !sp !pc !r12 } -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this, && at least n valid instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0xb5 ....0000 0x1c 00...... </data> <!-- push, mov -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
|
@ -158,28 +175,28 @@
|
|||
<data> 0xb5 ....0000 01.01... 0x.. </data> <!-- push, ldr -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0xb5 ....0000 0x68 0x.. </data> <!-- push, ldr -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0xb5 ....0000 01.01... 0x.. 0xb0 10...... </data> <!-- push, ldr, sub -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<funcstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0xb5 1...0000 0xaf.. </data> <!-- pop pushr7 addr7sp -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<!-- Loosened patterns, but MUST come after a function -->
|
||||
|
@ -194,8 +211,27 @@
|
|||
<data> 0xb5 .......0 </data> <!-- push-->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="function"/>
|
||||
<funcstart after="function" validcode="4" contiguous="true" />
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<pattern> <!-- 32 bit ARM - thunk -->
|
||||
<data> 0xe2 0x8f 1100.... ........
|
||||
0xe2 0x8c 1100.... ........
|
||||
0xe5 0xbc 0xf. 0x.. </data> <!-- adr r12, #; add r12,r12,#; ldr pc, [r21, #] -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="defined" thunk="true"/> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb - thunk -->
|
||||
<data> 0xb4 0x03
|
||||
0x48 0x01
|
||||
0x90 0x01
|
||||
0xbd 0x01 </data> <!-- push {r0,r1} ; ldr r0,[dest] ; str r0, [sp, stack[-4]] ; pop {r0,pc} -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart validcode="function" thunk="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
</patternlist>
|
||||
|
|
|
@ -10,10 +10,11 @@
|
|||
<data>0x7047 </data> <!-- bxlr -->
|
||||
<data>0x7047 0x0000 </data> <!-- bxlr, filler -->
|
||||
<data>0x7047 0xc046 </data> <!-- bxlr, filler -->
|
||||
<data>0x7047 0x00bf </data> <!-- bxlr, filler -->
|
||||
<data>000..... 0xb0 ....0000 0xbd </data> <!-- add, pop -->
|
||||
<data> 0x00bf </data> <!-- nop -->
|
||||
<data> 0xaff30080 </data> <!-- nop.w -->
|
||||
<data> 0xbde8 ........ 1....... </data> <!-- pop { rlist, pc } -->
|
||||
<data> 0xbde8 ........ 1000.... </data> <!-- pop.w { rlist, pc !lr, !sp !r12 } -->
|
||||
<data> 0x46f7 </data> <!-- mov pc,lr -->
|
||||
<data> 0x5d 0xf8 0....... 0xfb </data> <!-- ldr.w pc,[sp],#0x.. -->
|
||||
</prepatterns>
|
||||
|
@ -31,7 +32,7 @@
|
|||
<!-- could match 0xc0 0x46, which is filler <data> 0x.. 0x46 ....0000 0xb5 </data> --> <!-- push, mov -->
|
||||
<data> 0x.. 01.01... ....0000 0xb5 </data> <!-- push, ldr -->
|
||||
<data> 0x.. 0x68 ....0000 0xb5 </data> <!-- push, ldr -->
|
||||
<data> 0x2de9 ........ 010..... </data> <!-- push { rlist, lr } -->
|
||||
<data> 0x2de9 ........ 0100.... </data> <!-- push { rlist, lr !sp !pc !r12 } -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart/>
|
||||
|
@ -41,10 +42,12 @@
|
|||
<patternpairs totalbits="32" postbits="16"> <!-- 32 bit ARM -->
|
||||
<prepatterns>
|
||||
<data>0x1.ff2fe1 </data> <!-- bx r? -->
|
||||
<data>0x1eff2fe1 0xc046 </data> <!-- bx lr , filler -->
|
||||
<data>0x1eff2fe1 0x00000000 </data> <!-- bx lr , filler -->
|
||||
<data>0x1eff2fe1 0x0000a0e1 </data> <!-- bx lr , filler -->
|
||||
<data>0x......ea </data> <!-- b xxxx probably a shared call return, careful with this, must be a really strong func start after -->
|
||||
<data>0x.. 10.0.... 10.11101 0xe8 </data> <!-- ldmia sp!,{pc,...} -->
|
||||
<data>0x.. 10.0.... 10.11101 0xe8 0x00000000 </data> <!-- ldmia sp!,{pc,...}; filler -->
|
||||
<data>0x.. 10.0.... 10.11101 0xe8 0x0000a0e1 </data> <!-- ldmia sp!,{pc,...}; filler -->
|
||||
<data>0x08 0xf0 0x9d 0xe4 </data> <!-- ldr pc,[sp],#0x8 -->
|
||||
<data>0x0e 0xf0 0xa0 0xe1 </data> <!-- mov pc,lr -->
|
||||
<data>0x00f020e3 0x0000a0e1 </data> <!-- nop, cpy r0,r0 -->
|
||||
|
@ -52,50 +55,75 @@
|
|||
</prepatterns>
|
||||
|
||||
<postpatterns>
|
||||
<data> 0x..d.4de2 ....0000 .1...... 00101101 11101001 </data> <!-- sub sp,sp ; stmdb sp!,{r4+,lr} -->
|
||||
<data> ....0000 .1...... 00101101 11101001 0x..d.4de2 </data> <!-- stmdb sp!,{r4+,lr}; sub sp,sp -->
|
||||
<data> ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 </data> <!-- stmdb sp!,{r4+,lr}; <instr>; sub sp,sp -->
|
||||
<data> ....0000 .1...... 00101101 11101001 0000000. 010.0000 0xa0e1 </data> <!-- stmdb sp!,{r4+,lr}; mov r4,r0 -->
|
||||
<data> ....0000 .1...... 00101101 11101001 </data> <!-- stmdb sp!,{r4+,lr}; if the prepattern is strong -->
|
||||
<data> 0x..d.4de2 ........ .10..... 00101101 11101001 </data> <!-- sub sp,sp ; stmdb sp!,{r0+, lr !sp !pc !r12} -->
|
||||
<data> ........ 0100.... 00101101 11101001 0x..d.4de2 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; sub sp,sp -->
|
||||
<data> ........ 0100.... 00101101 11101001 0x........ 0x..d.4de2 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; <instr>; sub sp,sp -->
|
||||
<data> ........ 0100.... 00101101 11101001 0000000. 010.0000 0xa0e1 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; mov r4,r0 -->
|
||||
<data> ........ 0100.... 00101101 11101001 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; if the prepattern is strong -->
|
||||
<data> 0x..d.4de2 ........ 1110.... 00101101 11100101 </data> <!-- sub sp,sp; str lr,[sp,#...]; -->
|
||||
<data> ........ .0...... 00101101 11101001 ......00 11100000 00101101 11100101 </data> <!-- stmdb sp!,{xxx !lr}; str lr,[sp,#...]; -->
|
||||
<data> ........ 0000.... 00101101 11101001 ......00 11100000 00101101 11100101 </data> <!-- stmdb sp!,{r0+, !lr !sp !pc !r12}; str lr,[sp,#...]; -->
|
||||
<data> ........ 1110.... 00101101 11100101 0x..d.4de2 </data> <!-- str lr,[sp,#...]; sub sp,sp; -->
|
||||
<data> ........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 </data> <!-- str lr,[sp,#...]; <instr>; sub sp,sp; -->
|
||||
<data>0x08 0xe0 0x2d 0xe5 </data> <!-- str lr,[sp,#-0x8] -->
|
||||
<data>0x0dc0a0e1 0x....2de9 </data> <!-- cpy ip,sp; stmdb sp!,{} -->
|
||||
<data> ........ .1...... 00101101 11101001 </data> <!-- stmdb sp!,{xxx lr}; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> ........ 0100.... 00101101 11101001 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<possiblefuncstart/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0x..d.4de2 ....0000 .1...... 00101101 11101001 </data> <!-- sub sp,sp ; stmdb sp!,{r4+,lr} -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> 0x..d.4de2 ........ 0100.... 00101101 11101001 </data> <!-- sub sp,sp ; stmdb sp!,{r0+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary /> <!-- it is at least code -->
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<!-- must be something defined right before this, at least 10 contiguous instructions after it, check up to 20 instructions -->
|
||||
<possiblefuncstart after="defined" validcode="10" validcodemax="20" contiguous="true" />
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> ........ 0....... 1001.... 0xe5 0000.... 0100.... 00101101 11101001 </data> <!-- ldr .., xxx ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary /> <!-- it is at least code -->
|
||||
<!-- must be something defined right before this, at least 10 contiguous instructions after it -->
|
||||
<possiblefuncstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0x......e. 0000.... 0100.... 00101101 11101001 </data> <!-- Any instruction ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="ptr" validcode="10" contiguous="true"/> <!-- must be a data ptr (non r/w) to this and validcode -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0x......e. 0x......e. 0000.... 0100.... 00101101 11101001 </data> <!-- Any 2 instructions ; stmdb sp!,{r4+, lr !sp !pc !r12} -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="ptr" validcode="10" contiguous="true"/> <!-- must be a data ptr (non r/w) to this and validcode -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<!-- NOTE: pattern also match Thumb 'b' instruction followed by a 'push' instruction (where push is start uf Thumb function) -->
|
||||
<data> ....0000 .1...... 00101101 11101001 </data> <!-- stmdb sp!,{r4+,lr}; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> ........ 0100.... 00101101 11101001 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<possiblefuncstart after="data" isvalid="true"/> <!-- must be something defined right before this, and good code -->
|
||||
<possiblefuncstart after="defined" validcode="10" contiguous="true" /> <!-- must be something defined right before this, and good code -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> ........ .1...... 00101101 11101001 </data> <!-- stmdb sp!,{r4+,lr}; <valid code> -->
|
||||
<align mark="0" bits="3"/>
|
||||
<data> ........ 0100.... 00101101 11101001 </data> <!-- stmdb sp!,{r0+, lr !sp !pc !r12}; <valid code> -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart after="defined" isvalid="40"/> <!-- must be something defined right before this, && must be at least 40 valid instructions after it -->
|
||||
<!-- must be something defined right before this, at least 10 contiguous instructions after it, check up to (2*validcode) instructions -->
|
||||
<funcstart after="defined" validcode="10" contiguous="true" />
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> 0x..d.4de2 ........ 1110.... 00101101 11100101 </data> <!-- sub sp,sp; str lr,[sp,#...]; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary />
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
|
@ -103,7 +131,7 @@
|
|||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>........ 1110.... 00101101 11100101 0x..d.4de2 </data> <!-- str lr,[sp,#...]; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary />
|
||||
<possiblefuncstart after="data" /> <!-- must be data defined right before this -->
|
||||
|
@ -111,7 +139,7 @@
|
|||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data> ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 </data> <!-- stmdb sp!,{r4+,lr}; <instr>; sub sp,sp -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary />
|
||||
<possiblefuncstart after="data" /> <!-- must be data defined right before this -->
|
||||
|
@ -119,14 +147,14 @@
|
|||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 </data> <!-- str lr,[sp,#...]; <instr>; sub sp,sp; -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<possiblefuncstart after="data" /> <!-- must be data defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 32 bit ARM -->
|
||||
<data>0x0dc0a0e1 0x....2de9 </data> <!-- cpy ip,sp; stmdb sp!,{} -->
|
||||
<align mark="0" bits="3"/>
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<codeboundary /> <!-- can't say it is a function yet, have seen instructions before -->
|
||||
</pattern>
|
||||
|
@ -135,56 +163,56 @@
|
|||
<data> ....0000 0xb5 1....... 0xb0 </data> <!-- push, sub-->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 0x2de9 ........ 010..... </data> <!-- push { rlist, lr } -->
|
||||
<data> 0x2de9 ........ 010..... </data> <!-- push { rlist, lr !pc !sp } -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> ....0000 0xb5 00...... 0x1c </data> <!-- push, mov -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> ....0000 0xb5 0x.. 0x46 </data> <!-- push, mov -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> ....0000 0xb5 0x.. 01.01... </data> <!-- push, ldr -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> ....0000 0xb5 0x.. 0x68 </data> <!-- push, ldr -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> ....0000 0xb5 0x.. 01.01... 10...... 0xb0 </data> <!-- push, ldr, sub -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- 16 bit Thumb -->
|
||||
<data> 1...0000 0xb5 0x..af </data> <!-- pop pushr7 addr7sp -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<possiblefuncstart after="defined" /> <!-- must be something defined right before this -->
|
||||
<possiblefuncstart after="defined" validcode="4" contiguous="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
<!-- Loosened patterns, but MUST come after a function -->
|
||||
|
@ -200,123 +228,27 @@
|
|||
<data> .......0 0xb5 </data> <!-- push-->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart after="function"/>
|
||||
<funcstart after="function" validcode="4" contiguous="true"/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<!-- Special functions with side-effects -->
|
||||
<!-- -->
|
||||
|
||||
<pattern> <!-- Thumb Switch32_r0 -->
|
||||
<data> 0x03b4 0x7146 0x0231 0x8908 0x8000 0x8900 0x0858 0x4018 0x8646 0x03bc 0xf746 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
add r1,#0x2
|
||||
lsr r1,r1,#0x2
|
||||
lsl r0,r0,#0x2
|
||||
lsl r1,r1,#0x2
|
||||
ldr r0,[r1,r0]
|
||||
add r0,r0,r1
|
||||
mov lr,r0
|
||||
pop { r0 r1 }
|
||||
mov pc,lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_si"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch8_r0 -->
|
||||
<data> 0x02b4 0x7146 0x4908 0x4900 0x095c 0x4900 0x8e44 0x02bc 0x7047 </data>
|
||||
<!-- push { r1 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r1,r1,#0x1
|
||||
ldrb r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_uqi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb SwitchS8_r0 -->
|
||||
<data> 0x02b4 0x7146 0x4908 0x4900 0x0956 0x4900 0x8e44 0x02bc 0x7047 </data>
|
||||
<!-- push { r1 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r1,r1,#0x1
|
||||
ldrsb r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_sqi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch_S16_r0 -->
|
||||
<data> 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095e 0x4900 0x8e44 0x03bc 0x7047 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r0,r0,#0x1
|
||||
ldrsh r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_shi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch_16_r0 -->
|
||||
<data> 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095a 0x4900 0x8e44 0x03bc 0x7047 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r0,r0,#0x1
|
||||
ldrh r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_uhi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- ARM Switch8_r3 -->
|
||||
<data> 0x01c05ee5 0x0c0053e1 0x0330de37 0x0c30de27 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 </data>
|
||||
<!-- ldrb ip,[lr,#-0x1]
|
||||
cmp r3,ip
|
||||
ldrbcc r3,[lr,r3]
|
||||
ldrbcs r3,[lr,ip]
|
||||
add ip,lr,r3, lsl #0x1 | add lr,lr,r3, lsl #0x1
|
||||
bx ip | bx lr
|
||||
-->
|
||||
<align mark="0" bits="3"/>
|
||||
<pattern> <!-- 32 bit ARM - thunk -->
|
||||
<data> ........ 1100.... 0x8f 0xe2
|
||||
........ 1100.... 0x8c 0xe2
|
||||
0x.. 0xf. 0xbc 0xe5 </data> <!-- adr r12, #; add r12,r12,#; ldr pc, [r21, #] -->
|
||||
<align mark="0" bits="2"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart label="switch8_r3"/>
|
||||
<funcstart after="defined" thunk="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
|
||||
<pattern> <!-- ARM Switch8_r3 -->
|
||||
<data> 0x01c05ee5 0x0c0053e1 0x0c30de27 0x0330de37 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 </data>
|
||||
<!-- ldrb ip,[lr,#-0x1]
|
||||
cmp r3,ip
|
||||
ldrbcs r3,[lr,ip]
|
||||
ldrbcc r3,[lr,r3]
|
||||
add ip,lr,r3, lsl #0x1 | add lr,lr,r3, lsl #0x1
|
||||
bx ip | bx lr
|
||||
-->
|
||||
<align mark="0" bits="3"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart label="switch8_r3"/>
|
||||
<pattern> <!-- Thumb - thunk -->
|
||||
<data> 0x03 0xb4
|
||||
0x01 0x48
|
||||
0x01 0x90
|
||||
0x01 0xbd </data> <!-- push {r0,r1} ; ldr r0,[dest] ; str r0, [sp, stack[-4]] ; pop {r0,pc} -->
|
||||
<align mark="0" bits="1"/>
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart validcode="function" thunk="true" /> <!-- must be something defined right before this -->
|
||||
</pattern>
|
||||
|
||||
|
||||
</patternlist>
|
||||
|
|
137
Ghidra/Processors/ARM/data/patterns/ARM_switch_patterns.xml
Normal file
137
Ghidra/Processors/ARM/data/patterns/ARM_switch_patterns.xml
Normal file
|
@ -0,0 +1,137 @@
|
|||
<patternlist>
|
||||
|
||||
<!-- Special functions with side-effects -->
|
||||
<!-- -->
|
||||
|
||||
<pattern> <!-- Thumb Switch32_r0 -->
|
||||
<data> 0x03b4 0x7146 0x0231 0x8908 0x8000 0x8900 0x0858 0x4018 0x8646 0x03bc 0xf746 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
add r1,#0x2
|
||||
lsr r1,r1,#0x2
|
||||
lsl r0,r0,#0x2
|
||||
lsl r1,r1,#0x2
|
||||
ldr r0,[r1,r0]
|
||||
add r0,r0,r1
|
||||
mov lr,r0
|
||||
pop { r0 r1 }
|
||||
mov pc,lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_si"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch8_r0 -->
|
||||
<data> 0x02b4 0x7146 0x4908 0x4900 0x095c 0x4900 0x8e44 0x02bc 0x7047 </data>
|
||||
<!-- push { r1 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r1,r1,#0x1
|
||||
ldrb r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_uqi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb SwitchS8_r0 -->
|
||||
<data> 0x02b4 0x7146 0x4908 0x4900 0x0956 0x4900 0x8e44 0x02bc 0x7047 </data>
|
||||
<!-- push { r1 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r1,r1,#0x1
|
||||
ldrsb r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_sqi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch_S16_r0 -->
|
||||
<data> 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095e 0x4900 0x8e44 0x03bc 0x7047 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r0,r0,#0x1
|
||||
ldrsh r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_shi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb Switch_16_r0 -->
|
||||
<data> 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095a 0x4900 0x8e44 0x03bc 0x7047 </data>
|
||||
<!-- push { r1 r0 }
|
||||
mov r1,lr
|
||||
lsr r1,r1,#0x1
|
||||
lsl r0,r0,#0x1
|
||||
ldrh r1,[r1,r0]
|
||||
lsl r1,r1,#0x1
|
||||
add lr,r1
|
||||
pop { r1 }
|
||||
bx lr
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__gnu_thumb1_case_uhi"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- ARM Switch8_r3 -->
|
||||
<data> 0x01c05ee5 0x0c0053e1 0x0330de37 0x0c30de27 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 </data>
|
||||
<!-- ldrb ip,[lr,#-0x1]
|
||||
cmp r3,ip
|
||||
ldrbcc r3,[lr,r3]
|
||||
ldrbcs r3,[lr,ip]
|
||||
add ip,lr,r3, lsl #0x1 | add lr,lr,r3, lsl #0x1
|
||||
bx ip | bx lr
|
||||
-->
|
||||
<align mark="0" bits="3"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart label="switch8_r3"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- ARM Switch8_r3 -->
|
||||
<data> 0x01c05ee5 0x0c0053e1 0x0c30de27 0x0330de37 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 </data>
|
||||
<!-- ldrb ip,[lr,#-0x1]
|
||||
cmp r3,ip
|
||||
ldrbcs r3,[lr,ip]
|
||||
ldrbcc r3,[lr,r3]
|
||||
add ip,lr,r3, lsl #0x1 | add lr,lr,r3, lsl #0x1
|
||||
bx ip | bx lr
|
||||
-->
|
||||
<align mark="0" bits="3"/>
|
||||
<setcontext name="TMode" value="0"/>
|
||||
<funcstart label="switch8_r3"/>
|
||||
</pattern>
|
||||
|
||||
<pattern> <!-- Thumb common switch8 - same effect as switch8_r3 -->
|
||||
<data> 0x30b4 0x7446 0x641e 0x2578 0x641c 0xab42 0x00d2 0x1d46 0x635d 0x5b00 0xe318 0x30bc 0x1847</data>
|
||||
<!-- push {r4,r5}
|
||||
mov r4,lr
|
||||
subs r4,r4,#0x1
|
||||
ldrb r,[r4,#0x0]
|
||||
adds r4,r4,#0x1
|
||||
cmp r3,r5
|
||||
bcs <lab>
|
||||
mov r5,r3
|
||||
lab:
|
||||
ldrb r3,[r4,r5]
|
||||
lsls r3,r3,#0x1
|
||||
adds r3,r4,r3
|
||||
pop {r4,r5}
|
||||
bx r3
|
||||
-->
|
||||
<setcontext name="TMode" value="1"/>
|
||||
<funcstart label="__ARM_common_switch8"/>
|
||||
</pattern>
|
||||
|
||||
</patternlist>
|
|
@ -10,4 +10,5 @@
|
|||
<language id="ARM:LEBE:32:*">
|
||||
<patternfile>ARM_LE_patterns.xml</patternfile>
|
||||
</language>
|
||||
|
||||
</patternconstraints>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<patternconstraints>
|
||||
<language id="ARM:*:32:*">
|
||||
<patternfile>ARM_switch_patterns.xml</patternfile>
|
||||
</language>
|
||||
</patternconstraints>
|
|
@ -1,110 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.analysis;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a temporary analyzer, until we can get the pattern search framework up and going.
|
||||
* This searches for patterns that are functions that have side-effects.
|
||||
*/
|
||||
|
||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||
import ghidra.app.plugin.core.searchmem.RegExSearchData;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Processor;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.datastruct.ListAccumulator;
|
||||
import ghidra.util.search.memory.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class ARMPreAnalyzer extends AbstractAnalyzer {
|
||||
private static String DESCRIPTION =
|
||||
"Analyze ARM binaries for switch8_r3 functions. This will be replaced by a general hashing algorithm next release.";
|
||||
|
||||
public ARMPreAnalyzer() {
|
||||
super("ARM Pre-Pattern Analyzer", DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||
setPriority(AnalysisPriority.BLOCK_ANALYSIS.after());
|
||||
setDefaultEnablement(true);
|
||||
setSupportsOneTimeAnalysis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
Processor processor = program.getLanguage().getProcessor();
|
||||
return (processor.equals(Processor.findOrPossiblyCreateProcessor("ARM")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) {
|
||||
|
||||
String switch_fn = "\\x01\\xc0\\x5e\\xe5" + // ldrb ip,[lr,#-0x1]
|
||||
"\\x0c\\x00\\x53\\xe1" + // cmp r3,ip
|
||||
"(" + "\\x03\\x30\\xde\\x37" + // ldrbcc r3,[lr,r3]
|
||||
"\\x0c\\x30\\xde\\x27" + // ldrbcs r3,[lr,ip]
|
||||
"|" + // OR
|
||||
"\\x0c\\x30\\xde\\x27" + // ldrbcs r3,[lr,ip]
|
||||
"\\x03\\x30\\xde\\x37" + // ldrbcc r3,[lr,r3]
|
||||
")" + "(" + "\\x83\\xc0\\x8e\\xe0" + // add ip,lr,r3, lsl #0x1
|
||||
"\\x1c\\xff\\x2f\\xe1" + // bx ip
|
||||
"|" + // OR
|
||||
"\\x83\\xe0\\x8e\\xe0" + // add lr,lr,r3, lsl #0x1
|
||||
"\\x1e\\xff\\x2f\\xe1" + // bx lr
|
||||
")";
|
||||
|
||||
RegExSearchData searchData = RegExSearchData.createRegExSearchData(switch_fn);
|
||||
|
||||
SearchInfo searchInfo = new SearchInfo(searchData, 30, false, true, 4, false, null);
|
||||
|
||||
AddressSet intersection =
|
||||
program.getMemory().getLoadedAndInitializedAddressSet().intersect(set);
|
||||
RegExMemSearcherAlgorithm searcher =
|
||||
new RegExMemSearcherAlgorithm(searchInfo, intersection, program, true);
|
||||
|
||||
ListAccumulator<MemSearchResult> accumulator = new ListAccumulator<>();
|
||||
searcher.search(accumulator, monitor);
|
||||
List<MemSearchResult> results = accumulator.asList();
|
||||
|
||||
// create a function here with the correct call fixup
|
||||
for (MemSearchResult result : results) {
|
||||
|
||||
Address addr = result.getAddress();
|
||||
|
||||
// disassemble ARM
|
||||
DisassembleCommand disassembleCommand = new DisassembleCommand(addr, null, true);
|
||||
disassembleCommand.applyTo(program);
|
||||
|
||||
// create function
|
||||
CreateFunctionCmd createFunctionCmd = new CreateFunctionCmd(addr, false);
|
||||
createFunctionCmd.applyTo(program);
|
||||
|
||||
// set call fixup
|
||||
Function func = program.getFunctionManager().getFunctionAt(addr);
|
||||
if (func != null) {
|
||||
func.setCallFixup("switch8_r3");
|
||||
}
|
||||
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
bookmarkManager.setBookmark(addr, BookmarkType.ANALYSIS, getName(),
|
||||
"Found Switch8_r3 Function");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -47,9 +47,11 @@ data/languages/x86gcc.cspec||GHIDRA||||END|
|
|||
data/languages/x86win.cspec||GHIDRA||||END|
|
||||
data/manuals/x86.idx||GHIDRA||||END|
|
||||
data/patterns/patternconstraints.xml||GHIDRA||||END|
|
||||
data/patterns/prepatternconstraints.xml||GHIDRA||||END|
|
||||
data/patterns/x86-16_default_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86-64gcc_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86-64win_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86delphi_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86gcc_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86win_patterns.xml||GHIDRA||||END|
|
||||
data/patterns/x86win_prepatterns.xml||GHIDRA||||END|
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<patternconstraints>
|
||||
|
||||
<language id="x86:LE:32:default">
|
||||
<compiler id="windows">
|
||||
<patternfile>x86win_prepatterns.xml</patternfile>
|
||||
</compiler>
|
||||
<compiler id="borlandcpp">
|
||||
<patternfile>x86win_prepatterns.xml</patternfile>
|
||||
</compiler>
|
||||
</language>
|
||||
|
||||
</patternconstraints>
|
|
@ -11,11 +11,8 @@
|
|||
<data>0xeb..90</data> <!-- JMP small , NOP -->
|
||||
<data>0x5d 0xc3</data> <!-- POP RBP, RET -->
|
||||
<data>0x5b 0xc3</data> <!-- POP RBX, RET -->
|
||||
<data>0x415f 0xc3</data> <!-- POP R15, RET -->
|
||||
<data>0x415c 0xc3</data> <!-- POP R12, RET -->
|
||||
<data>0x41 010111.. 0xc3</data> <!-- POP R12-15, RET -->
|
||||
<data>0x31c0 0xc3</data> <!-- XOR(EAX,EAX), RET -->
|
||||
<data>0x415d 0xc3</data> <!-- POP R13, RET -->
|
||||
<data>0x415e 0xc3</data> <!-- POP R14, RET -->
|
||||
<data>0x4883c4 ....1000 0xc3</data> <!-- ADD RSP, C; RET -->
|
||||
<data>0x666690</data> <!-- three-byte NOP -->
|
||||
<data>0x0f1f00</data> <!-- three-byte NOP -->
|
||||
|
@ -36,37 +33,114 @@
|
|||
<data>0x534889fb</data> <!-- PUSH RBX; MOV(RBX,RDI) (shared objects) -->
|
||||
<data>0x554889fd</data> <!-- PUSH (RBP); MOV(RBP, RDI) (kernel objects) -->
|
||||
<data>0x534889fb</data> <!-- PUSH RBX; MOV(RBX,RDI)-->
|
||||
<data>0x53 0x48 0x83 0xec 0....000 </data> <!-- PUSH RBX; SUB RSP, C -->
|
||||
<data>0x53 0x48 0x81 0xec .....000 00...... 0x00 </data> <!-- PUSH RBX; SUB RSP, C -->
|
||||
<!-- three-instruction sequences -->
|
||||
<data>0x55 0x48 0x89 0xe5 0x48 0x83 0xec 0...0000</data> <!-- PUSH RBP; MOV RBP, RSP; SUB RSP, C -->
|
||||
<data>0x55 0x48 0x89 0xe5 0x48 100000.1 0xec .....000</data> <!-- PUSH RBP; MOV RBP, RSP; SUB RSP, C -->
|
||||
<data>0x554889e553</data> <!-- PUSH RBP; MOV RBP, RSP; PUSH RBX -->
|
||||
<data>0x554889fd53</data> <!-- PUSH RBP; MOV RBP, RDI; PUSH RBX -->
|
||||
<data>0x554889e548897df8</data> <!-- PUSH RBP; MOV RBP, RSP; MOV [RBP -0x8], RDI -->
|
||||
<data>0x53 0x48 0x89 0xfb 0xe8 ........ ........ 0xff 0xff</data> <!-- PUSH RBX; MOV RBX,RDI; CALL -->
|
||||
<data>0x4154 0x55 0100100. 0x89 11......</data> <!-- PUSH R12; PUSH RBP; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<data>0x4154 0x55 0x53 0100100. 0x89 11......</data> <!-- PUSH R12; PUSH RBP; PUSH RBX; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<!-- save registers start sequences -->
|
||||
<data>0x415741564155</data> <!-- PUSH R15; PUSH R14; PUSH R13-->
|
||||
<data>0x41544989fc55</data> <!-- PUSH R12; MOV(R12,RDI); PUSH(RBP)-->
|
||||
<data>0x41564155</data> <!-- PUSH R14; PUSH R13-->
|
||||
<data>0x41554154</data> <!-- PUSH R13; PUSH R12-->
|
||||
<data>0x41 010101.. 0100100. 0x89 11...... 0x55</data> <!-- PUSH R12/3/4/5; MOV(R12/3/4/5/xX,RxX); PUSH(RBP)-->
|
||||
<data>0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... </data> <!-- PUSH R12/3/4/5; PUSH R12/3/4/5; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart/>
|
||||
</postpatterns>
|
||||
</patternpairs>
|
||||
|
||||
<pattern>
|
||||
<data>0x5589e5</data> <!-- PUSH RBP; MOV(EBP, ESP) (shared objects) -->
|
||||
<funcstart after="data" /> <!-- must be something defined right before this, or no memory -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x55 0x53 0100100. 0x89 11......</data> <!-- PUSH RBP; PUSH RBX; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x4154 0x55 0100100. 0x89 11......</data> <!-- PUSH R12; PUSH RBP; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x4154 0x55 0x53 0100100. 0x89 11......</data> <!-- PUSH R12; PUSH RBP; PUSH RBX; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x53 0x48 0x83 0xec 0....000 </data> <!-- PUSH RBX; SUB RSP, C -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x48 0x83 0xec .....000 </data> <!-- SUB RSP, C -->
|
||||
<funcstart after="defined" validcode="10" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x48 0x81 0xec .....000 00...... 0x00 </data> <!-- SUB RSP, big C -->
|
||||
<funcstart after="defined" validcode="10" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x55 0x53 0x48 0x83 100000.1 0xec .....000 </data> <!-- PUSH RBP; PUSH RBX; SUB RSP, big/C -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x554889e5</data> <!-- PUSH RBP; MOV(RBP, RSP) (shared objects) -->
|
||||
<funcstart after="data" /> <!-- must be something defined right before this, or no memory -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x55 0x48 0x89 0xe5 0x48 0x83 0xec 0...0000</data> <!-- PUSH RBP; MOV RBP, RSP; SUB RSP, C --> <!-- PUSH RBP; MOV(RBP, RSP) (shared objects) -->
|
||||
<funcstart after="data" /> <!-- must be something defined right before this, or no memory -->
|
||||
<data>0x55 0x48 0x89 0xe5 0x48 100000.1 0xec .....000</data> <!-- PUSH RBP; MOV RBP, RSP; SUB RSP, big/C --> <!-- PUSH RBP; MOV(RBP, RSP) (shared objects) -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x554889e553</data> <!-- PUSH RBP; MOV RBP, RSP; PUSH RBX --> <!-- PUSH RBP; MOV(RBP, RSP) (shared objects) -->
|
||||
<funcstart after="data" /> <!-- must be something defined right before this, or no memory -->
|
||||
<funcstart after="defined" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x4157 0x4156 0x4155</data> <!-- PUSH R15; PUSH R14; PUSH R13-->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x4157 0x4156</data> <!-- PUSH R15; PUSH R14-->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x4156 0x4155</data> <!-- PUSH R14; PUSH R13-->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x41554154</data> <!-- PUSH R13; PUSH R12-->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x41 010101.. 0100100. 0x89 11...... 0x55</data> <!-- PUSH R12/3/4/5; MOV(R12/3/4/5/xX,RxX); PUSH(RBP)-->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... </data> <!-- PUSH R12/3/4/5; PUSH R12/3/4/5; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... </data> <!-- PUSH R12/3/4/5; PUSH R12/3/4/5; MOV(R12/3/4/5/xX,RxX); -->
|
||||
<funcstart after="defined" validcode="5" /> <!-- must be something defined right before this, or no memory, at least 5 FT instructions -->
|
||||
</pattern>
|
||||
|
||||
</patternlist>
|
||||
|
|
|
@ -30,6 +30,40 @@
|
|||
<possiblefuncstart/>
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x83 0xec 0.....00 100010.1 01...100 ..100100 0.....00 </data> <!-- SUB ESP, C, MOV [ESP + value], reg OR MOV reg, [ESP + value] -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x81 0xec ......00 0000.... 0x00 0x00 100010.1 01...100 ..100100 0.....00 </data> <!-- SUB ESP, big C, MOV [ESP + value], reg OR MOV reg, [ESP + value] -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x5. 0x83 0xec 0.....00 100010.1 01...100 ..100100 0.....00 </data> <!-- PUSH reg, SUB ESP, C, MOV [ESP + value], reg OR MOV reg, [ESP + value] -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x5. 0x81 0xec ......00 0000.... 0x00 0x00 </data> <!-- PUSH reg, SUB ESP, big C, -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x5. 0x5. 100000.1 0xec ......00 </data> <!-- PUSH reg; push reg; SUB ESP, C/big C -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x5. 0x5. 0x5. 100000.1 0xec ......00 </data> <!-- PUSH reg; PUSH reg; PUSH reg; push reg; SUB ESP, C/big C -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data> 0x5. 0x5. 0x5. 0x5. 100000.1 0xec ......00 </data> <!-- PUSH reg; PUSH reg; push reg; SUB ESP, C/big C -->
|
||||
<funcstart after="defined" validcode="6" /> <!-- must be something defined right before this, or no memory -->
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>0x8b 0x04 0x24 0xc3 </data> <!-- MOV EAX,[ESP] / RET -->
|
||||
|
|
|
@ -104,40 +104,6 @@
|
|||
<funcstart label="__alloca_probe_8"/>
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>
|
||||
0x8bff
|
||||
0x55
|
||||
0x8bec
|
||||
0x83ec20
|
||||
0x8b4508
|
||||
0x56
|
||||
0x57
|
||||
0x6a08
|
||||
0x59
|
||||
0xbe........
|
||||
0x8d7de0
|
||||
0xf3a5
|
||||
0x8945f8
|
||||
0x8b450c
|
||||
0x5f
|
||||
0x8945fc
|
||||
0x5e
|
||||
0x85c0
|
||||
0x740c
|
||||
0xf60008
|
||||
0x7407
|
||||
0xc745f4........
|
||||
0x8d45f4
|
||||
0x50
|
||||
0xff75f0
|
||||
0xff75e4
|
||||
0xff75e0
|
||||
0xff15........
|
||||
0xc9
|
||||
0xc20800 </data> <!-- __CxxThrowException@8 -->
|
||||
<funcstart label="__CxxThrowException@8" noreturn="true"/>
|
||||
</pattern>
|
||||
|
||||
<pattern>
|
||||
<data>
|
||||
|
|
38
Ghidra/Processors/x86/data/patterns/x86win_prepatterns.xml
Normal file
38
Ghidra/Processors/x86/data/patterns/x86win_prepatterns.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<patternlist>
|
||||
|
||||
<pattern>
|
||||
<data>
|
||||
0x8bff
|
||||
0x55
|
||||
0x8bec
|
||||
0x83ec20
|
||||
0x8b4508
|
||||
0x56
|
||||
0x57
|
||||
0x6a08
|
||||
0x59
|
||||
0xbe........
|
||||
0x8d7de0
|
||||
0xf3a5
|
||||
0x8945f8
|
||||
0x8b450c
|
||||
0x5f
|
||||
0x8945fc
|
||||
0x5e
|
||||
0x85c0
|
||||
0x740c
|
||||
0xf60008
|
||||
0x7407
|
||||
0xc745f4........
|
||||
0x8d45f4
|
||||
0x50
|
||||
0xff75f0
|
||||
0xff75e4
|
||||
0xff75e0
|
||||
0xff15........
|
||||
0xc9
|
||||
0xc20800 </data> <!-- __CxxThrowException@8 -->
|
||||
<funcstart label="__CxxThrowException@8" noreturn="true"/>
|
||||
</pattern>
|
||||
|
||||
</patternlist>
|
Loading…
Reference in New Issue
Block a user