diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java index 5c15328922..8505ea169c 100644 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java +++ b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java @@ -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 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 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 + 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,22 +246,31 @@ 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 (!isvalid) { - return false; + if (validCodeMax > 0) { // check at most N instructions + pseudoDisassembler.setMaxInstructions(validCodeMax); + } + // 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,52 +550,113 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa } protected void restoreXmlAttributes(XmlElement el) { - if (el.hasAttribute("after")) { - afterName = el.getAttribute("after"); - if (afterName.startsWith("func")) { - hasCodeConstraints = true; + Map attributes = el.getAttributes(); + Set 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; + } + else if (afterName.startsWith("inst")) { + hasCodeConstraints = true; + } + else if (afterName.startsWith("data")) { + hasDataConstraints = true; + } + else if (afterName.startsWith("ptr")) { + hasDataConstraints = true; + } + else if (afterName.startsWith("def")) { + hasCodeConstraints = hasDataConstraints = true; + } + else { + Msg.error(this, + "funcstart pattern attribute 'after' must be one of 'function', 'instruction', 'data', 'defined'"); + } + 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")) { + validCodeMin = NO_VALID_INSTRUCTIONS_REQUIRED; + } + else if (validcodeStr.equalsIgnoreCase("true") || + validcodeStr.equalsIgnoreCase("subroutine")) { // must be a valid subroutine + validCodeMin = MUST_HAVE_VALID_INSTRUCTIONS_NO_MIN; + } + else if (validcodeStr.equalsIgnoreCase("function")) { // must be at a defined function + validFunction = true; + hasFunctionStartConstraints = true; // enable FunctionStartFuncAnalyzer to run + validCodeMin = NO_VALID_INSTRUCTIONS_REQUIRED; + } + else { // must have 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; + } + 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 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 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; + break; + + case "thunk": + isThunk = true; + 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); } - else if (afterName.startsWith("inst")) { - hasCodeConstraints = true; - } - else if (afterName.startsWith("data")) { - hasDataConstraints = true; - } - else if (afterName.startsWith("def")) { - hasCodeConstraints = hasDataConstraints = true; - } - else { - 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"); - if (validcodeStr.equals("0") || validcodeStr.equals("false")) { - validcode = 0; - } - else if (validcodeStr.equalsIgnoreCase("true") || - validcodeStr.equalsIgnoreCase("subroutine")) { // must be a valid subroutine - validcode = -1; - } - else if (validcodeStr.equalsIgnoreCase("function")) { // must be at a defined subroutine - validFunction = true; - hasFunctionStartConstraints = true; - } - else { // must have valid instruction run - validcode = Integer.parseInt(validcodeStr); - } - } - if (el.hasAttribute("label")) { - String name = el.getAttribute("label"); - label = name; - } - if (el.hasAttribute("thunk")) { - isThunk = true; - } - if (el.hasAttribute("noreturn")) { - noreturn = true; } } diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartPreFuncAnalyzer.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartPreFuncAnalyzer.java new file mode 100644 index 0000000000..2c40ab2bab --- /dev/null +++ b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartPreFuncAnalyzer.java @@ -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(); + } +} diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/Patterns.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/Patterns.java index e8810a3783..d252369b40 100644 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/Patterns.java +++ b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/Patterns.java @@ -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 patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS); - List patternConstraintFiles = findPatternConstraintFiles(patternDirs); + return getPatternDecisionTree(DEFAULT_PATTERNCONSTRAINTS_XML); + } + + public static ProgramDecisionTree getPatternDecisionTree(String patternConstraintsFileName) { + List patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS_SUBDIR); + List 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 values = decisionsSet.getValues(); List patternFileList = new ArrayList(); - List patternDirs = Application.findModuleSubDirectories(DATA_PATTERNS); + List 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 findPatternConstraintFiles(List patternDirs) { + private static List findPatternConstraintFiles(List patternDirs, String constraintsFileName) { List patternConstraintFiles = new ArrayList(); for (ResourceFile dir : patternDirs) { - ResourceFile file = new ResourceFile(dir, "patternconstraints.xml"); + ResourceFile file = new ResourceFile(dir, constraintsFileName); if (file.exists()) { patternConstraintFiles.add(file); } diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java index a50c366637..8cd322ddd0 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java @@ -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; } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java index 7d9d751931..6b06504d80 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java @@ -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. */ @@ -94,6 +96,14 @@ public class PseudoDisassembler { public void setMaxInstructions(int maxNumInstructions) { 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 @@ -580,10 +590,19 @@ public class PseudoDisassembler { return checkValidSubroutine(entryPoint, procContext, allowExistingInstructions, mustTerminate); } - + 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. @@ -645,7 +665,13 @@ public class PseudoDisassembler { repeatInstructionByteTracker.reset(); 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,13 +834,18 @@ 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; + // 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)) { // check that the body of the function doesn't break any rules. diff --git a/Ghidra/Processors/AARCH64/data/patterns/AARCH64_LE_patterns.xml b/Ghidra/Processors/AARCH64/data/patterns/AARCH64_LE_patterns.xml index bae3968d95..fe705a6ce9 100644 --- a/Ghidra/Processors/AARCH64/data/patterns/AARCH64_LE_patterns.xml +++ b/Ghidra/Processors/AARCH64/data/patterns/AARCH64_LE_patterns.xml @@ -21,22 +21,22 @@ 111..... .1....11 10...... 0xa9 - + 0x........ 111..... .1....11 10...... 0xa9 - + 0xfe .0001111 0x1. 0xf8 - + 0x........ 0xfe .0001111 0x1. 0xf8 - + diff --git a/Ghidra/Processors/ARM/certification.manifest b/Ghidra/Processors/ARM/certification.manifest index 40ae34598a..af7c971381 100644 --- a/Ghidra/Processors/ARM/certification.manifest +++ b/Ghidra/Processors/ARM/certification.manifest @@ -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| diff --git a/Ghidra/Processors/ARM/data/languages/ARM.cspec b/Ghidra/Processors/ARM/data/languages/ARM.cspec index 4137ca1d69..7d5e703e2d 100644 --- a/Ghidra/Processors/ARM/data/languages/ARM.cspec +++ b/Ghidra/Processors/ARM/data/languages/ARM.cspec @@ -120,6 +120,7 @@ + - - + + @@ -20,8 +20,8 @@ - - + + diff --git a/Ghidra/Processors/ARM/data/patterns/ARM_BE_patterns.xml b/Ghidra/Processors/ARM/data/patterns/ARM_BE_patterns.xml index c74608db5e..ec97996dca 100644 --- a/Ghidra/Processors/ARM/data/patterns/ARM_BE_patterns.xml +++ b/Ghidra/Processors/ARM/data/patterns/ARM_BE_patterns.xml @@ -13,7 +13,7 @@ 0xb0 000..... 0xbd ....0000 0x00bf 0x8000f3af - 0xe8bd 1....... ........ + 0xe8bd 101..... ........ 0xf746 0xf8 0x5d 0xfb 0....... @@ -31,20 +31,22 @@ 0x46 0x.. 0xb5 ....0000 01.01...0x.. 0xb5 ....0000 0x68 0x.. 0xb5 ....0000 - 0xe92d 010..... ........ + 0xe92d 0100.... ........ - + 0xe12fff1. - 0xe12fff1e 0x46c0 0xe12fff1e 0xe1a00000 + 0xe12fff1e 0x00000000 0xea...... 0xe8 10.11101 10.0.... 0x.. + 0xe8 10.11101 10.0.... 0x.. 0xe1a00000 + 0xe8 10.11101 10.0.... 0x.. 0x00000000 0xe4 0x9d 0xf0 0x08 0xe1 0xa0 0xf0 0x0e 0xe320f000 0xe1a00000 @@ -52,76 +54,91 @@ - 0xe24dd... 11101001 00101101 .1...... ....0000 - 11101001 00101101 .1...... ....0000 0xe24dd... - 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... - 11101001 00101101 .1...... ....0000 0xe1a0 010.0000 0000000. - 11101001 00101101 .1...... ....0000 + 0xe24dd... 11101001 00101101 0100.... ........ + 11101001 00101101 0100.... ........ 0xe24dd... + 11101001 00101101 0100.... ........ 0x........ 0xe24dd... + 11101001 00101101 0100.... ........ 0xe1a0 010.0000 0000000. + 11101001 00101101 0100.... ........ 0xe24dd... 11100101 00101101 1110.... ........ - 11101001 00101101 .0...... ........ 11100101 00101101 11100000 ......00 + 11101001 00101101 0000.... ........ 11100101 00101101 11100000 ......00 11100101 00101101 1110.... ........ 0xe24dd... 11100101 00101101 1110.... ........ 0x........ 0xe24dd... 0xe5 0x2d 0xe0 0x08 - 0xe1a0c00d 0xe92d.... - + 0xe1a0c00d 0xe92d.... + - + - 0xe24dd... 11101001 00101101 .1...... ....0000 - + 0xe24dd... 11101001 00101101 0100.... ........ + - + - 11101001 00101101 .1...... ....0000 - + 0xe5 1001.... 0....... ........ 11101001 00101101 0100.... ....0000 + - + + - 11101001 00101101 .1...... ....0000 - + 0xe....... 11101001 00101101 0100.... ....0000 + - + + + + + 0xe....... 0xe....... 11101001 00101101 0100.... ....0000 + + + + + + + 11101001 00101101 0100.... ........ + + + 0xe24dd... 11100101 00101101 1110.... ........ - + 11100101 00101101 1110.... ........ 0xe24dd... - + 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... - + 11100101 00101101 1110.... ........ 0x........ 0xe24dd... - + 0xe1a0c00d 0xe92d.... - + @@ -130,21 +147,21 @@ 0xb5 ....0000 0xb0 100..... - + - 0xe92d 010..... ........ + 0xe92d 0100.... ........ - + 0xb5 ....0000 0x1c 00...... - + @@ -158,28 +175,28 @@ 0xb5 ....0000 01.01... 0x.. - + 0xb5 ....0000 0x68 0x.. - + 0xb5 ....0000 01.01... 0x.. 0xb0 10...... - + 0xb5 1...0000 0xaf.. - + @@ -194,8 +211,27 @@ 0xb5 .......0 - + - + + + 0xe2 0x8f 1100.... ........ + 0xe2 0x8c 1100.... ........ + 0xe5 0xbc 0xf. 0x.. + + + + + + + 0xb4 0x03 + 0x48 0x01 + 0x90 0x01 + 0xbd 0x01 + + + + + diff --git a/Ghidra/Processors/ARM/data/patterns/ARM_LE_patterns.xml b/Ghidra/Processors/ARM/data/patterns/ARM_LE_patterns.xml index 7e18bea070..b242723347 100644 --- a/Ghidra/Processors/ARM/data/patterns/ARM_LE_patterns.xml +++ b/Ghidra/Processors/ARM/data/patterns/ARM_LE_patterns.xml @@ -10,10 +10,11 @@ 0x7047 0x7047 0x0000 0x7047 0xc046 + 0x7047 0x00bf 000..... 0xb0 ....0000 0xbd 0x00bf 0xaff30080 - 0xbde8 ........ 1....... + 0xbde8 ........ 1000.... 0x46f7 0x5d 0xf8 0....... 0xfb @@ -31,7 +32,7 @@ 0x.. 01.01... ....0000 0xb5 0x.. 0x68 ....0000 0xb5 - 0x2de9 ........ 010..... + 0x2de9 ........ 0100.... @@ -41,10 +42,12 @@ 0x1.ff2fe1 - 0x1eff2fe1 0xc046 + 0x1eff2fe1 0x00000000 0x1eff2fe1 0x0000a0e1 0x......ea 0x.. 10.0.... 10.11101 0xe8 + 0x.. 10.0.... 10.11101 0xe8 0x00000000 + 0x.. 10.0.... 10.11101 0xe8 0x0000a0e1 0x08 0xf0 0x9d 0xe4 0x0e 0xf0 0xa0 0xe1 0x00f020e3 0x0000a0e1 @@ -52,50 +55,75 @@ - 0x..d.4de2 ....0000 .1...... 00101101 11101001 - ....0000 .1...... 00101101 11101001 0x..d.4de2 - ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 - ....0000 .1...... 00101101 11101001 0000000. 010.0000 0xa0e1 - ....0000 .1...... 00101101 11101001 + 0x..d.4de2 ........ .10..... 00101101 11101001 + ........ 0100.... 00101101 11101001 0x..d.4de2 + ........ 0100.... 00101101 11101001 0x........ 0x..d.4de2 + ........ 0100.... 00101101 11101001 0000000. 010.0000 0xa0e1 + ........ 0100.... 00101101 11101001 0x..d.4de2 ........ 1110.... 00101101 11100101 - ........ .0...... 00101101 11101001 ......00 11100000 00101101 11100101 + ........ 0000.... 00101101 11101001 ......00 11100000 00101101 11100101 ........ 1110.... 00101101 11100101 0x..d.4de2 ........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 0x08 0xe0 0x2d 0xe5 0x0dc0a0e1 0x....2de9 - ........ .1...... 00101101 11101001 - + ........ 0100.... 00101101 11101001 + - 0x..d.4de2 ....0000 .1...... 00101101 11101001 - + 0x..d.4de2 ........ 0100.... 00101101 11101001 + - + + + + + + ........ 0....... 1001.... 0xe5 0000.... 0100.... 00101101 11101001 + + + + + + + + + 0x......e. 0000.... 0100.... 00101101 11101001 + + + + + 0x......e. 0x......e. 0000.... 0100.... 00101101 11101001 + + + + + - ....0000 .1...... 00101101 11101001 - + ........ 0100.... 00101101 11101001 + - + - ........ .1...... 00101101 11101001 - + ........ 0100.... 00101101 11101001 + - + + 0x..d.4de2 ........ 1110.... 00101101 11100101 - + @@ -103,7 +131,7 @@ ........ 1110.... 00101101 11100101 0x..d.4de2 - + @@ -111,7 +139,7 @@ ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 - + @@ -119,14 +147,14 @@ ........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 - + 0x0dc0a0e1 0x....2de9 - + @@ -135,56 +163,56 @@ ....0000 0xb5 1....... 0xb0 - + - 0x2de9 ........ 010..... + 0x2de9 ........ 010..... - + ....0000 0xb5 00...... 0x1c - + ....0000 0xb5 0x.. 0x46 - + ....0000 0xb5 0x.. 01.01... - + ....0000 0xb5 0x.. 0x68 - + ....0000 0xb5 0x.. 01.01... 10...... 0xb0 - + 1...0000 0xb5 0x..af - + @@ -200,123 +228,27 @@ .......0 0xb5 - + - - - - - 0x03b4 0x7146 0x0231 0x8908 0x8000 0x8900 0x0858 0x4018 0x8646 0x03bc 0xf746 - - - - - - - 0x02b4 0x7146 0x4908 0x4900 0x095c 0x4900 0x8e44 0x02bc 0x7047 - - - - - - - 0x02b4 0x7146 0x4908 0x4900 0x0956 0x4900 0x8e44 0x02bc 0x7047 - - - - - - - 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095e 0x4900 0x8e44 0x03bc 0x7047 - - - - - - - 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095a 0x4900 0x8e44 0x03bc 0x7047 - - - - - - - 0x01c05ee5 0x0c0053e1 0x0330de37 0x0c30de27 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 - - + + ........ 1100.... 0x8f 0xe2 + ........ 1100.... 0x8c 0xe2 + 0x.. 0xf. 0xbc 0xe5 + - + - - - 0x01c05ee5 0x0c0053e1 0x0c30de27 0x0330de37 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 - - - - + + 0x03 0xb4 + 0x01 0x48 + 0x01 0x90 + 0x01 0xbd + + + - diff --git a/Ghidra/Processors/ARM/data/patterns/ARM_switch_patterns.xml b/Ghidra/Processors/ARM/data/patterns/ARM_switch_patterns.xml new file mode 100644 index 0000000000..f622f10fce --- /dev/null +++ b/Ghidra/Processors/ARM/data/patterns/ARM_switch_patterns.xml @@ -0,0 +1,137 @@ + + + + + + + 0x03b4 0x7146 0x0231 0x8908 0x8000 0x8900 0x0858 0x4018 0x8646 0x03bc 0xf746 + + + + + + + 0x02b4 0x7146 0x4908 0x4900 0x095c 0x4900 0x8e44 0x02bc 0x7047 + + + + + + + 0x02b4 0x7146 0x4908 0x4900 0x0956 0x4900 0x8e44 0x02bc 0x7047 + + + + + + + 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095e 0x4900 0x8e44 0x03bc 0x7047 + + + + + + + 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095a 0x4900 0x8e44 0x03bc 0x7047 + + + + + + + 0x01c05ee5 0x0c0053e1 0x0330de37 0x0c30de27 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 + + + + + + + + 0x01c05ee5 0x0c0053e1 0x0c30de27 0x0330de37 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 + + + + + + + + 0x30b4 0x7446 0x641e 0x2578 0x641c 0xab42 0x00d2 0x1d46 0x635d 0x5b00 0xe318 0x30bc 0x1847 + + + + + + \ No newline at end of file diff --git a/Ghidra/Processors/ARM/data/patterns/patternconstraints.xml b/Ghidra/Processors/ARM/data/patterns/patternconstraints.xml index 29ca71a319..3db7419e56 100644 --- a/Ghidra/Processors/ARM/data/patterns/patternconstraints.xml +++ b/Ghidra/Processors/ARM/data/patterns/patternconstraints.xml @@ -9,5 +9,6 @@ ARM_LE_patterns.xml - + + diff --git a/Ghidra/Processors/ARM/data/patterns/prepatternconstraints.xml b/Ghidra/Processors/ARM/data/patterns/prepatternconstraints.xml new file mode 100644 index 0000000000..c4d8abb655 --- /dev/null +++ b/Ghidra/Processors/ARM/data/patterns/prepatternconstraints.xml @@ -0,0 +1,5 @@ + + + ARM_switch_patterns.xml + + \ No newline at end of file diff --git a/Ghidra/Processors/ARM/src/main/java/ghidra/app/plugin/core/analysis/ARMPreAnalyzer.java b/Ghidra/Processors/ARM/src/main/java/ghidra/app/plugin/core/analysis/ARMPreAnalyzer.java deleted file mode 100644 index 0c9c6bc91b..0000000000 --- a/Ghidra/Processors/ARM/src/main/java/ghidra/app/plugin/core/analysis/ARMPreAnalyzer.java +++ /dev/null @@ -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 accumulator = new ListAccumulator<>(); - searcher.search(accumulator, monitor); - List 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; - } -} diff --git a/Ghidra/Processors/x86/certification.manifest b/Ghidra/Processors/x86/certification.manifest index 7d95a8f6a4..c1f458b1e6 100644 --- a/Ghidra/Processors/x86/certification.manifest +++ b/Ghidra/Processors/x86/certification.manifest @@ -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| diff --git a/Ghidra/Processors/x86/data/patterns/prepatternconstraints.xml b/Ghidra/Processors/x86/data/patterns/prepatternconstraints.xml new file mode 100644 index 0000000000..ea92c2ab1c --- /dev/null +++ b/Ghidra/Processors/x86/data/patterns/prepatternconstraints.xml @@ -0,0 +1,12 @@ + + + + + x86win_prepatterns.xml + + + x86win_prepatterns.xml + + + + diff --git a/Ghidra/Processors/x86/data/patterns/x86-64gcc_patterns.xml b/Ghidra/Processors/x86/data/patterns/x86-64gcc_patterns.xml index 98ff3ad6c7..2daa852e44 100644 --- a/Ghidra/Processors/x86/data/patterns/x86-64gcc_patterns.xml +++ b/Ghidra/Processors/x86/data/patterns/x86-64gcc_patterns.xml @@ -11,11 +11,8 @@ 0xeb..90 0x5d 0xc3 0x5b 0xc3 - 0x415f 0xc3 - 0x415c 0xc3 + 0x41 010111.. 0xc3 0x31c0 0xc3 - 0x415d 0xc3 - 0x415e 0xc3 0x4883c4 ....1000 0xc3 0x666690 0x0f1f00 @@ -36,37 +33,114 @@ 0x534889fb 0x554889fd 0x534889fb + 0x53 0x48 0x83 0xec 0....000 + 0x53 0x48 0x81 0xec .....000 00...... 0x00 - 0x55 0x48 0x89 0xe5 0x48 0x83 0xec 0...0000 + 0x55 0x48 0x89 0xe5 0x48 100000.1 0xec .....000 0x554889e553 0x554889fd53 0x554889e548897df8 0x53 0x48 0x89 0xfb 0xe8 ........ ........ 0xff 0xff + 0x4154 0x55 0100100. 0x89 11...... + 0x4154 0x55 0x53 0100100. 0x89 11...... + 0x415741564155 - 0x41544989fc55 + 0x41564155 + 0x41554154 + 0x41 010101.. 0100100. 0x89 11...... 0x55 + 0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... 0x5589e5 - + + + + + 0x55 0x53 0100100. 0x89 11...... + + + + + 0x4154 0x55 0100100. 0x89 11...... + + + + + 0x4154 0x55 0x53 0100100. 0x89 11...... + + + + + 0x53 0x48 0x83 0xec 0....000 + + + + + 0x48 0x83 0xec .....000 + + + + + 0x48 0x81 0xec .....000 00...... 0x00 + + + + + 0x55 0x53 0x48 0x83 100000.1 0xec .....000 + 0x554889e5 - + - 0x55 0x48 0x89 0xe5 0x48 0x83 0xec 0...0000 - + 0x55 0x48 0x89 0xe5 0x48 100000.1 0xec .....000 + 0x554889e553 - + - + + 0x4157 0x4156 0x4155 + + + + + 0x4157 0x4156 + + + + + 0x4156 0x4155 + + + + + 0x41554154 + + + + + 0x41 010101.. 0100100. 0x89 11...... 0x55 + + + + + 0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... + + + + + 0x41 010101.. 0x41 010101.. 0100100. 0x89 11...... + + + diff --git a/Ghidra/Processors/x86/data/patterns/x86gcc_patterns.xml b/Ghidra/Processors/x86/data/patterns/x86gcc_patterns.xml index a8f1e0340b..89885e5aea 100644 --- a/Ghidra/Processors/x86/data/patterns/x86gcc_patterns.xml +++ b/Ghidra/Processors/x86/data/patterns/x86gcc_patterns.xml @@ -30,7 +30,41 @@ + + 0x83 0xec 0.....00 100010.1 01...100 ..100100 0.....00 + + + + 0x81 0xec ......00 0000.... 0x00 0x00 100010.1 01...100 ..100100 0.....00 + + + + + 0x5. 0x83 0xec 0.....00 100010.1 01...100 ..100100 0.....00 + + + + + 0x5. 0x81 0xec ......00 0000.... 0x00 0x00 + + + + + 0x5. 0x5. 100000.1 0xec ......00 + + + + + 0x5. 0x5. 0x5. 100000.1 0xec ......00 + + + + + 0x5. 0x5. 0x5. 0x5. 100000.1 0xec ......00 + + + 0x8b 0x04 0x24 0xc3 diff --git a/Ghidra/Processors/x86/data/patterns/x86win_patterns.xml b/Ghidra/Processors/x86/data/patterns/x86win_patterns.xml index dbb07c069d..4c4b59e73c 100644 --- a/Ghidra/Processors/x86/data/patterns/x86win_patterns.xml +++ b/Ghidra/Processors/x86/data/patterns/x86win_patterns.xml @@ -103,41 +103,7 @@ 0x518d4c24082bc883e10703c11bc90bc159e9........ - - - - 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 - - + diff --git a/Ghidra/Processors/x86/data/patterns/x86win_prepatterns.xml b/Ghidra/Processors/x86/data/patterns/x86win_prepatterns.xml new file mode 100644 index 0000000000..7e3ecbaf6d --- /dev/null +++ b/Ghidra/Processors/x86/data/patterns/x86win_prepatterns.xml @@ -0,0 +1,38 @@ + + + + + 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 + + + +