From c49eaf9203561fdc3c1049e9e3421705bd9e0eb2 Mon Sep 17 00:00:00 2001 From: ttttupup Date: Thu, 5 Sep 2024 22:15:37 +0800 Subject: [PATCH] feat: find mars script --- script/ghidra_script/FindCallScript.java | 212 ------------- script/ghidra_script/FindMarsScript.java | 386 +++++++++++++++++++++++ 2 files changed, 386 insertions(+), 212 deletions(-) create mode 100644 script/ghidra_script/FindMarsScript.java diff --git a/script/ghidra_script/FindCallScript.java b/script/ghidra_script/FindCallScript.java index 8b83b4f..471df6e 100644 --- a/script/ghidra_script/FindCallScript.java +++ b/script/ghidra_script/FindCallScript.java @@ -298,216 +298,4 @@ public class FindCallScript extends GhidraScript { return list; } -} - -class GraphFunctionFactory { - - public static GDirectedGraph createGraph(Function f, TaskMonitor monitor) - throws CancelledException { - - if (monitor == null) { - monitor = TaskMonitor.DUMMY; - } - - JungDirectedGraph graph = new JungDirectedGraph<>(); - - BidiMap vertices = createVertices(f, monitor); - for (FunctionVertex v : vertices.values()) { - graph.addVertex(v); - } - - Collection edges = createdEdges(vertices, monitor); - for (FunctionEdge e : edges) { - graph.addEdge(e); - } - - // this must be done after the edges are added to the graph - for (FunctionVertex vertex : vertices.values()) { - vertex.setType(getVertexType(graph, vertex)); - } - - return graph; - } - - private static BidiMap createVertices(Function f, TaskMonitor monitor) - throws CancelledException { - - BidiMap vertices = new DualHashBidiMap<>(); - Program p = f.getProgram(); - CodeBlockModel blockModel = new BasicBlockModel(p); - - AddressSetView addresses = f.getBody(); - CodeBlockIterator iterator = blockModel.getCodeBlocksContaining(addresses, monitor); - monitor.initialize(addresses.getNumAddresses()); - - for (; iterator.hasNext();) { - CodeBlock codeBlock = iterator.next(); - - FlowType flowType = codeBlock.getFlowType(); - boolean isEntry = isEntry(codeBlock); - - FunctionVertex vertex = new FunctionVertex(codeBlock, flowType, isEntry); - - vertices.put(codeBlock, vertex); - - long blockAddressCount = codeBlock.getNumAddresses(); - long currentProgress = monitor.getProgress(); - monitor.setProgress(currentProgress + blockAddressCount); - } - - return vertices; - } - - private static Collection createdEdges(BidiMap vertices, - TaskMonitor monitor) throws CancelledException { - - List edges = new ArrayList<>(); - for (FunctionVertex startVertex : vertices.values()) { - Collection vertexEdges = getEdgesForStartVertex(vertices, startVertex, monitor); - - edges.addAll(vertexEdges); - } - - return edges; - } - - private static Collection getEdgesForStartVertex(BidiMap blockToVertexMap, - FunctionVertex startVertex, TaskMonitor monitor) throws CancelledException { - - List edges = new ArrayList<>(); - CodeBlock codeBlock = blockToVertexMap.getKey(startVertex); - CodeBlockReferenceIterator destinations = codeBlock.getDestinations(monitor); - for (; destinations.hasNext();) { - CodeBlockReference reference = destinations.next(); - CodeBlock destinationBlock = reference.getDestinationBlock(); - FunctionVertex destinationVertex = blockToVertexMap.get(destinationBlock); - if (destinationVertex == null) { - continue;// no vertex means the code block is not in our function - } - - edges.add(new FunctionEdge(startVertex, destinationVertex, reference.getFlowType())); - } - return edges; - } - - private static VertexType getVertexType(Graph graph, FunctionVertex v) { - - boolean isEntry = v.isEntry(); - boolean isExit = false; - - FlowType flowType = v.getFlowType(); - if (flowType.isTerminal()) { - isExit = true; - } - - Collection outs = graph.getOutEdges(v); - if (outs == null || outs.isEmpty()) { - isExit = true; - } - - VertexType type = VertexType.BODY; - if (isEntry) { - if (isExit) { - type = VertexType.SINGLETON; - } else { - type = VertexType.ENTRY; - } - } else if (isExit) { - type = VertexType.EXIT; - } - return type; - } - - private static boolean isEntry(CodeBlock codeBlock) { - boolean isSource = true; - try { - CodeBlockReferenceIterator iter = codeBlock.getSources(TaskMonitor.DUMMY); - while (iter.hasNext()) { - isSource = false; - if (iter.next().getFlowType().isCall()) { - // any calls into a code block will make it an 'entry' - return true; - } - } - } catch (CancelledException e) { - // will never happen, because I don't have a monitor - } - return isSource; - } -} - -class FunctionVertex extends CodeBlockVertex { - - private VertexType type = VertexType.BODY; - private FlowType flowType; - private boolean isEntry; - - public FunctionVertex(CodeBlock codeBlock, FlowType flowType, boolean isEntry) { - super(codeBlock); - this.flowType = flowType; - this.isEntry = isEntry; - } - - public boolean isEntry() { - return isEntry; - } - - public FlowType getFlowType() { - return flowType; - } - - public VertexType getType() { - return type; - } - - public void setType(VertexType type) { - this.type = type; - } -} - -class FunctionEdge implements GEdge { - - private FunctionVertex start; - private FunctionVertex end; - private FlowType flowType; - - public FunctionEdge(FunctionVertex start, FunctionVertex end, FlowType flowType) { - this.start = start; - this.end = end; - this.flowType = flowType; - } - - public FlowType getFlowType() { - return flowType; - } - - @Override - public FunctionVertex getStart() { - return start; - } - - @Override - public FunctionVertex getEnd() { - return end; - } -} - -enum VertexType { - - //@formatter:off - BODY, - ENTRY, - EXIT, - GROUP, - SINGLETON; - //@formatter:on - - public boolean isEntry() { - return this == ENTRY || this == SINGLETON; - } - - public boolean isExit() { - return this == EXIT || this == SINGLETON; - } - } \ No newline at end of file diff --git a/script/ghidra_script/FindMarsScript.java b/script/ghidra_script/FindMarsScript.java new file mode 100644 index 0000000..f51fa1b --- /dev/null +++ b/script/ghidra_script/FindMarsScript.java @@ -0,0 +1,386 @@ +// find mars +//@author ttttupup +//@category _NEW_ +//@keybinding +//@menupath +//@toolbar + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import docking.widgets.filter.ContainsTextFilterFactory; +import docking.widgets.filter.TextFilter; +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileOptions; +import ghidra.app.decompiler.DecompileResults; +import ghidra.app.script.GhidraScript; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressFactory; +import ghidra.program.model.address.AddressIterator; +import ghidra.program.model.address.AddressSet; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.block.BasicBlockModel; +import ghidra.program.model.block.CodeBlock; +import ghidra.program.model.listing.CodeUnit; +import ghidra.program.model.listing.Data; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionManager; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.mem.MemoryAccessException; +import ghidra.program.model.pcode.HighFunction; +import ghidra.program.model.pcode.PcodeBlockBasic; +import ghidra.program.model.pcode.PcodeOp; +import ghidra.program.model.pcode.PcodeOpAST; +import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.symbol.Reference; +import ghidra.program.model.symbol.ReferenceIterator; +import ghidra.program.model.symbol.ReferenceManager; +import ghidra.program.model.symbol.SourceType; +import ghidra.program.util.string.FoundString; +import ghidra.sleigh.grammar.SleighParser.stringorident_return; +import ghidra.util.StringUtilities; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.DuplicateNameException; +import ghidra.util.exception.InvalidInputException; + +public class FindMarsScript extends GhidraScript { + DecompInterface decompiler = new DecompInterface(); + BasicBlockModel basicBlockModel; + + @Override + protected void run() throws Exception { + DecompileOptions decompileOptions = new DecompileOptions(); + decompiler.setOptions(decompileOptions); + decompiler.openProgram(currentProgram); + basicBlockModel = new BasicBlockModel(currentProgram); + Address findXScopeTracer = findXScopeTracer(); +// Address findXScopeTracer = currentProgram.getAddressFactory().getAddress("0x183d04d10"); + if (null != findXScopeTracer) { + ReferenceIterator referenceIterator = currentProgram.getReferenceManager() + .getReferencesTo(findXScopeTracer); + while (referenceIterator.hasNext()) { + monitor.checkCancelled(); + Reference next = referenceIterator.next(); + Address fromAddress = next.getFromAddress(); + + Function functionContaining = currentProgram.getFunctionManager().getFunctionContaining(fromAddress); + if (null == functionContaining) { + println("no found function: " + fromAddress.toString()); + continue; + } + DecompileResults res = decompiler.decompileFunction(functionContaining, 20, null); + if (!res.decompileCompleted()) { + println("decompile error: " + res.getErrorMessage()); + continue; + } + HighFunction highFunction = res.getHighFunction(); + Iterator pcodeOps = highFunction.getPcodeOps(); + while (pcodeOps.hasNext()) { + monitor.checkCancelled(); + PcodeOpAST opAST = pcodeOps.next(); + int opcode = opAST.getOpcode(); + if (PcodeOp.CALL == opcode || PcodeOp.CALLIND == opcode || PcodeOp.CALLOTHER == opcode) { + Varnode input0 = opAST.getInput(0); + boolean contains = input0.contains(findXScopeTracer); + + if (contains) { + Varnode input3 = opAST.getInput(3); + Varnode input4 = opAST.getInput(4); + if (input4 == null || input3 == null) { + continue; + } + String namespaceString = ""; + String funcNameString = ""; + if (input3.isUnique()) { + namespaceString = getUniqueValue(input3); + } else if (input3.isConstant()) { + namespaceString = getConstact(input3); + } + if (input4.isUnique()) { + funcNameString = getUniqueValue(input4); + } else if (input4.isConstant()) { + funcNameString = getConstact(input4); + } + if (StringUtilities.isAllBlank(namespaceString) + || StringUtilities.isAllBlank(funcNameString)) { + continue; + } + String name = namespaceString.replace(" ", "") + "::" + funcNameString.replace(" ", ""); + println("find function :" + name); + functionContaining.setName(name, SourceType.USER_DEFINED); + currentProgram.getListing().setComment(functionContaining.getEntryPoint(), + CodeUnit.EOL_COMMENT, "mars scipt auto define: " + name); + } + + } + } + } + + } + + } + + private String getConstact(Varnode input3) { + Address address2 = input3.getAddress(); + Address address3 = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(address2.getOffset()); + Data dataAt2 = getDataAt(address3); + if (null != dataAt2) { + if (dataAt2.hasStringValue()) { + return dataAt2.getValue().toString(); + } + } + return null; + } + + private void easy(Address findXScopeTracer) throws CancelledException { + if (null != findXScopeTracer) { + ReferenceIterator referenceIterator = currentProgram.getReferenceManager() + .getReferencesTo(findXScopeTracer); + while (referenceIterator.hasNext()) { + monitor.checkCancelled(); + Reference next = referenceIterator.next(); + Address fromAddress = next.getFromAddress(); + Instruction instructionAt = currentProgram.getListing().getInstructionAt(fromAddress); + if (null != instructionAt) { + PcodeOp[] pcode = instructionAt.getPcode(); + if (null != pcode) { + for (PcodeOp pcodeOp : pcode) { + if (pcodeOp.getOpcode() == PcodeOp.CALL) { + Varnode namespace = pcodeOp.getInput(3); + Varnode funcName = pcodeOp.getInput(4); + if (null != namespace) { + if (namespace.isConstant()) { + long offset = namespace.getAddress().getOffset(); + Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() + .getAddress(offset); + Data dataAt = currentProgram.getListing().getDataAt(address); + if (null != dataAt) { + if (dataAt.hasStringValue()) { + dataAt.getValue().toString(); + } + } + } + } + if (null != funcName) { + if (funcName.isConstant()) { + long offset = funcName.getAddress().getOffset(); + Address address = currentProgram.getAddressFactory().getDefaultAddressSpace() + .getAddress(offset); + Data dataAt = currentProgram.getListing().getDataAt(address); + if (null != dataAt) { + if (dataAt.hasStringValue()) { + dataAt.getValue().toString(); + } + } + } + } + } + } + } + + println("caller address: " + fromAddress.toString()); + } + } + } + } + + private void find() throws Exception { + Function findXLogger = findXLogger(); + if (null != findXLogger) { + if (findXLogger.isThunk()) { + currentProgram.getFunctionManager().createFunction("XLogger::operator()", findXLogger.getEntryPoint(), + findXLogger.getBody(), findXLogger.getSignatureSource()); + } else { + + findXLogger.setName("XLogger::operator()", SourceType.USER_DEFINED); + currentProgram.getListing().setComment(findXLogger.getEntryPoint(), CodeUnit.EOL_COMMENT, + "rename function: XLogger::operator()"); + + ReferenceIterator referenceIterator = currentProgram.getReferenceManager() + .getReferencesTo(findXLogger.getEntryPoint()); + while (referenceIterator.hasNext()) { + monitor.checkCancelled(); + Reference next = referenceIterator.next(); + Address fromAddress = next.getFromAddress(); + println("caller address: " + fromAddress.toString()); + handle(fromAddress, findXLogger.getEntryPoint()); + } + } + } + } + + private Address findXScopeTracer() throws Exception { + List list = findStrings(null, 5, 1, true, false); + ContainsTextFilterFactory factory = new ContainsTextFilterFactory(false, true); + TextFilter textFilter = factory.getTextFilter("mars::comm::DNS::GetHostByName"); + for (FoundString foundString : list) { + monitor.checkCancelled(); + String string = foundString.getString(currentProgram.getMemory()); + if (textFilter.matches(string)) { + Address address = foundString.getAddress(); + println("=====text addr :" + address.toString()); + + ReferenceIterator referencesTo = currentProgram.getReferenceManager().getReferencesTo(address); + while (referencesTo.hasNext()) { + Reference ref = referencesTo.next(); + Address textAddress = ref.getFromAddress(); + Function func = currentProgram.getFunctionManager().getFunctionContaining(textAddress); + if (null == func) { + continue; + } + CodeBlock[] codeBlocksContaining = basicBlockModel.getCodeBlocksContaining(textAddress, monitor); + for (CodeBlock codeBlock : codeBlocksContaining) { + AddressIterator addressIterator = codeBlock.getAddresses(true); + while (addressIterator.hasNext()) { + Address next = addressIterator.next(); + CodeUnit codeUnitAt = currentProgram.getListing().getCodeUnitAt(next); + if (null != codeUnitAt) { + if (codeUnitAt.getMnemonicString().equals("CALL")) { + Instruction instructionAt = currentProgram.getListing().getInstructionAt(next); + PcodeOp[] pcode = instructionAt.getPcode(); + PcodeOp pcodeOp = pcode[pcode.length - 1]; + Varnode input = pcodeOp.getInput(0); + Address address2 = input.getAddress(); + println("===== XScopeTracer::XScopeTracer addr :" + address2.toString()); + Function functionAt = currentProgram.getFunctionManager().getFunctionAt(address2); + if (null != functionAt) { + functionAt.setName("XScopeTracer::XScopeTracer", SourceType.USER_DEFINED); + currentProgram.getListing().setComment(functionAt.getEntryPoint(), + CodeUnit.EOL_COMMENT, "scipt auto define: XScopeTracer::XScopeTracer"); + } else { + createFunction(address2, "XScopeTracer::XScopeTracer"); + currentProgram.getListing().setComment(address2, CodeUnit.EOL_COMMENT, + "scipt auto create: XScopeTracer::XScopeTracer"); + } + + return address2; + } + } + + } + + } + } + } + } + return null; + + } + + private void handle(Address address, Address calleeAddress) throws CancelledException { + Function functionContaining = currentProgram.getFunctionManager().getFunctionContaining(address); + if (null == functionContaining) { + println("no found function: " + address.toString()); + return; + } + + DecompileResults res = decompiler.decompileFunction(functionContaining, 20, null); + if (!res.decompileCompleted()) { + println("decompile error: " + res.getErrorMessage()); + return; + } + + HighFunction highFunction = res.getHighFunction(); + ArrayList basicBlocks = highFunction.getBasicBlocks(); + + for (PcodeBlockBasic pcodeBlockBasic : basicBlocks) { + monitor.checkCancelled(); + boolean contains = pcodeBlockBasic.contains(address); + if (contains) { + Iterator iterator = pcodeBlockBasic.getIterator(); + for (; iterator.hasNext();) { + monitor.checkCancelled(); + PcodeOp next = iterator.next(); + if (next.getOpcode() == PcodeOp.CALL) { + if (next.getNumInputs() > 4) { + Varnode input3 = next.getInput(3); + if (null != input3) { + if (input3.isUnique()) { + String uniqueValue = getUniqueValue(input3); + if (null != uniqueValue) { + println(uniqueValue); + } + } + } + } + } + } + } + } + + } + + private String getUniqueValue(Varnode input3) { + PcodeOp def = input3.getDef(); + Varnode[] inputs = def.getInputs(); + if (null != inputs && inputs.length > 0) { + if (inputs[0].isConstant()) { + Address address2 = inputs[0].getAddress(); + Address address3 = currentProgram.getAddressFactory().getDefaultAddressSpace() + .getAddress(address2.getOffset()); + Data dataAt2 = currentProgram.getListing().getDataAt(address3); + if (null != dataAt2) { + if (dataAt2.hasStringValue()) { + return dataAt2.getValue().toString(); + } + } + } + } + return null; + } + + private Function findXLogger() throws MemoryAccessException, CancelledException { + + FunctionManager functionManager = currentProgram.getFunctionManager(); + ReferenceManager referenceManager = currentProgram.getReferenceManager(); + AddressFactory factory = currentProgram.getAddressFactory(); + AddressSpace[] addressSpaces = factory.getAddressSpaces(); + AddressSetView initializedMemory = currentProgram.getMemory().getLoadedAndInitializedAddressSet(); + + AddressSet searchSet = initializedMemory.intersect(new AddressSet(initializedMemory)); + List findStrings = new ArrayList<>(); + println("初次查询速度较慢,请耐心等待。"); + for (AddressSpace space : addressSpaces) { + if (monitor.isCancelled()) { + break; + } + AddressSet intersecting = searchSet.intersectRange(space.getMinAddress(), space.getMaxAddress()); + findStrings.addAll(findStrings(null, 10, 1, true, true)); + } + + if (null != findStrings && findStrings.size() > 0) { + ContainsTextFilterFactory containsTextFilterFactory = new ContainsTextFilterFactory(false, true); + TextFilter textFilter = containsTextFilterFactory + .getTextFilter("XLogger& XLogger::operator()(const char* _format, ...)"); + for (FoundString foundString : findStrings) { + if (monitor.isCancelled()) { + break; + } + String string = foundString.getString(currentProgram.getMemory()); + if (textFilter.matches(string)) { + Address address = foundString.getAddress(); + println(address.toString()); + + ReferenceIterator referencesTo = referenceManager.getReferencesTo(address); + while (referencesTo.hasNext()) { + if (monitor.isCancelled()) { + break; + } + Reference ref = referencesTo.next(); + Address xLoggerAddr = ref.getFromAddress(); + Function targetFunction = functionManager.getFunctionContaining(xLoggerAddr); + if (null == targetFunction) { + continue; + } + println("XLogger::operator() :" + targetFunction.getEntryPoint().toString()); + return targetFunction; + } + } + } + } + return null; + } + +}