From 3f596a4041efc925f418df4cdf52f8e7f8fa8918 Mon Sep 17 00:00:00 2001 From: ttttupup Date: Tue, 6 Aug 2024 21:13:41 +0800 Subject: [PATCH] feat: update script --- script/ghidra_script/FindCallScript.java | 492 ++++++++++++++++++++++- 1 file changed, 476 insertions(+), 16 deletions(-) diff --git a/script/ghidra_script/FindCallScript.java b/script/ghidra_script/FindCallScript.java index 6b547a5..8b83b4f 100644 --- a/script/ghidra_script/FindCallScript.java +++ b/script/ghidra_script/FindCallScript.java @@ -1,53 +1,513 @@ -import java.util.ArrayList; -import java.util.List; +import static org.junit.Assert.assertNotNull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.bidimap.DualHashBidiMap; import docking.widgets.filter.ContainsTextFilterFactory; import docking.widgets.filter.TextFilter; import docking.widgets.filter.TextFilterFactory; +import edu.uci.ics.jung.graph.Graph; import ghidra.app.script.GhidraScript; +import ghidra.feature.fid.db.FidFile; +import ghidra.feature.fid.db.FidFileManager; +import ghidra.graph.GDirectedGraph; +import ghidra.graph.GEdge; +import ghidra.graph.jung.JungDirectedGraph; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressIterator; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.block.BasicBlockModel; +import ghidra.program.model.block.CodeBlock; +import ghidra.program.model.block.CodeBlockIterator; +import ghidra.program.model.block.CodeBlockModel; +import ghidra.program.model.block.CodeBlockReference; +import ghidra.program.model.block.CodeBlockReferenceIterator; +import ghidra.program.model.block.graph.CodeBlockVertex; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionManager; +import ghidra.program.model.listing.Program; +import ghidra.program.model.symbol.FlowType; +import ghidra.program.model.symbol.Reference; +import ghidra.program.model.symbol.ReferenceIterator; +import ghidra.program.model.symbol.ReferenceManager; import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.SymbolIterator; import ghidra.program.model.symbol.SymbolTable; +import ghidra.util.exception.CancelledException; +import ghidra.util.task.TaskMonitor; public class FindCallScript extends GhidraScript { - @Override protected void run() throws Exception { - ContainsTextFilterFactory containsTextFilterFactory = new ContainsTextFilterFactory(false, true); + ContainsTextFilterFactory factory = new ContainsTextFilterFactory(false, true); + + find_send_msg(factory); + findFunction(factory,"SendMessageMgr::sendMsg"); + findFunction(factory,"AppMsgMgr::sendFile"); + findFunction(factory,"SendMessageMgr::sendImageMsg"); + findFunction(factory,"SyncMgr::doAddMsg"); + findFunction(factory,"ChatRoomMgr::doModChatRoomMemberNickName"); - find_send_msg(containsTextFilterFactory); + findFunction2(factory,"New_ChatMsg"); + findFunction2(factory,"Free_ChatMsg"); + findFunction2(factory,"New_ChatRoomInfo"); + findFunction2(factory,"Free_ChatRoomInfo"); + findFunction2(factory,"New_ChatRoom"); + findFunction2(factory,"Free_ChatRoom"); + findFunction2(factory,"New_Contact"); + findFunction2(factory,"Free_Contact"); + findFunction2(factory,"New_WAUpdatableMsgInfo"); + findFunction2(factory,"Free_WAUpdatableMsgInfo"); + findFunction2(factory,"New_AppMsgInfo"); + findFunction2(factory,"Free_AppMsgInfo"); + findFunction2(factory,"New_MMReaderItem"); + findFunction2(factory,"Free_MMReaderItem"); + findFunction2(factory,"New_WCPayInfo"); + findFunction2(factory,"Free_WCPayInfo"); + findFunction2(factory,"New_WebViewPageConfig"); + findFunction2(factory,"Free_WebViewPageConfig"); + + findMgr(factory, "SendMessageMgr::SendMessageMgr", "GetSendMessageMgr"); + findMgr(factory, "AccountServiceMgr::AccountServiceMgr", "GetAccountServiceMgr"); + findMgr(factory, "AppMsgMgr::AppMsgMgr", "GetAppMsgMgr"); + findMgr(factory, "ContactMgr::ContactMgr", "GetContactMgr"); + findMgr(factory, "ChatRoomMgr::ChatRoomMgr", "GetChatRoomMgr"); + findMgr(factory, "SNSDataMgr::SNSDataMgr", "GetSNSDataMgr"); + findMgr(factory, "SNSTimeLineMgr::SNSTimeLineMgr", "GetSNSTimeLineMgr"); + findMgr(factory, "ChatMgr::ChatMgr", "GetChatMgr"); + findMgr(factory, "FavoriteMgr::FavoriteMgr", "GetFavoriteMgr"); + findMgr(factory, "PreDownLoadMgr::PreDownLoadMgr", "GetPreDownLoadMgr"); + findMgr(factory, "CustomSmileyMgr::CustomSmileyMgr", "GetCustomSmileyMgr"); + findMgr(factory, "LockWechatMgr::LockWechatMgr", "GetLockWechatMgr"); + findMgr(factory, "QRCodeLoginMgr::QRCodeLoginMgr", "GetQRCodeLoginMgr"); + findMgr(factory, "VoiceMgr::VoiceMgr", "GetVoiceMgr"); + findMgr(factory, "WebViewMgr::WebViewMgr", "GetWebViewMgr"); + findMgr(factory, "SearchContactMgr::SearchContactMgr", "GetSearchContactMgr"); + findMgr(factory, "PublicMsgMgr::PublicMsgMgr", "GetPublicMsgMgr"); + findMgr(factory, "MultiDBMsgMgr::MultiDBMsgMgr", "GetMultiDBMsgMgr"); + findMgr(factory, "FavoriteStorageMgr::FavoriteStorageMgr", "GetFavoriteStorageMgr"); + findMgr(factory, "HardLinkMgr::HardLinkMgr", "GetHardLinkMgr"); + } - + + private boolean checkFidFile() { + FidFileManager fidFileManager = FidFileManager.getInstance(); + List userFid = fidFileManager.getFidFiles(); + if (userFid.isEmpty()) { + printerr("please import 3.9.11.25.fid fid file."); + return false; + } + return true; + } + void find_send_msg(ContainsTextFilterFactory factory) { SymbolTable symbolTable = currentProgram.getSymbolTable(); - List searchSymbol = searchSymbol(symbolTable,"SendMessageMgr::sendMsg",factory,"SendMessageMgr::sendMsg"); + List searchSymbol = searchSymbol(symbolTable, "SendMessageMgr::sendMsg", factory, + "SendMessageMgr::sendMsg"); for (Symbol symbol : searchSymbol) { - println("found SendMessageMgr::sendMsg" + symbol.getAddress().toString()); - println("=================copy source========================"); - printf("const uint64_t kSendTextMsg = " + symbol.getAddress().toString() + "; \n"); + println("const uint64_t kSendTextMsg = " + symbol.getAddress().toString()); } } - - void find_sendMessageMgr(ContainsTextFilterFactory factory) { + + void findFunction(ContainsTextFilterFactory factory, String functionName) { + assertNotNull(factory); + assertNotNull(functionName); + String name = ""; + String[] split = functionName.split("::"); + if (split.length > 1) { + name = split[1]; + char upperCase = Character.toUpperCase(split[1].charAt(0)); + name = upperCase + split[1].substring(1); + } else { + char upperCase = Character.toUpperCase(functionName.charAt(0)); + name = upperCase + functionName.substring(1); + } SymbolTable symbolTable = currentProgram.getSymbolTable(); - List searchSymbol = searchSymbol(symbolTable,"SendMessageMgr::SendMessageMgr",factory,"SendMessageMgr::SendMessageMgr"); + List searchSymbol = searchSymbol(symbolTable, functionName, factory, functionName); for (Symbol symbol : searchSymbol) { - + println("const uint64_t k" + name + " = " + symbol.getAddress().toString()); } } - List searchSymbol(SymbolTable symbolTable,String text,TextFilterFactory factory,String filterText) { + void findFunction2(ContainsTextFilterFactory factory, String functionName) { + assertNotNull(factory); + assertNotNull(functionName); + String name = ""; + String split = functionName.replace("_", ""); + char upperCase = Character.toUpperCase(split.charAt(0)); + name = upperCase + split.substring(1); + SymbolTable symbolTable = currentProgram.getSymbolTable(); + List searchSymbol = searchSymbol(symbolTable, functionName, factory, functionName); + for (Symbol symbol : searchSymbol) { + println("const uint64_t k" + name + " = " + symbol.getAddress().toString()); + } + } + + void find_Mgr(ContainsTextFilterFactory factory) throws CancelledException { + if (!checkFidFile()) { + return; + } + SymbolTable symbolTable = currentProgram.getSymbolTable(); + FunctionManager functionManager = currentProgram.getFunctionManager(); + ReferenceManager referenceManager = currentProgram.getReferenceManager(); + + List
addresses = new ArrayList<>(); + List searchMgr = searchSymbol(symbolTable, "SendMessageMgr::SendMessageMgr", factory, + "SendMessageMgr::SendMessageMgr"); + for (Symbol symbol : searchMgr) { + Address address = symbol.getAddress(); + ReferenceIterator referencesTo = referenceManager.getReferencesTo(address); + while (referencesTo.hasNext()) { + Reference next = referencesTo.next(); + Address fromAddress = next.getFromAddress(); + println("fromAddress " + fromAddress.toString()); + Function functionAt = functionManager.getFunctionContaining(fromAddress); + if (null != functionAt) { + addresses.add(functionAt.getEntryPoint()); + } + } + } + + List searchSymbol = searchSymbol(symbolTable, "GetSendMessageMgr", factory, "GetSendMessageMgr"); + for (Symbol symbol : searchSymbol) { + Address address = symbol.getAddress(); + if (addresses.contains(address)) { + println("const uint64_t kGetSendMessageMgr = " + address.toString() + ";"); + } + } + + } + + void find_SendMessageMgr(ContainsTextFilterFactory factory) throws CancelledException { + if (!checkFidFile()) { + return; + } + SymbolTable symbolTable = currentProgram.getSymbolTable(); + FunctionManager functionManager = currentProgram.getFunctionManager(); + + List
addresses = new ArrayList<>(); + List searchMgr = searchSymbol(symbolTable, "SendMessageMgr::SendMessageMgr", factory, + "SendMessageMgr::SendMessageMgr"); + for (Symbol symbol : searchMgr) { + Address address = symbol.getAddress(); + addresses.add(address); + } + + List searchSymbol = searchSymbol(symbolTable, "GetSendMessageMgr", factory, "GetSendMessageMgr"); + for (Symbol symbol : searchSymbol) { + Address address = symbol.getAddress(); + Function function = functionManager.getFunctionAt(address); + if (null != function) { + AddressSetView functionBody = function.getBody(); + Address entryPoint = function.getEntryPoint(); + Set references = getReferencesFrom(currentProgram, functionBody, monitor); + for (Reference reference : references) { + monitor.checkCancelled(); + Address toAddress = reference.getToAddress(); + if (toAddress.equals(entryPoint)) { + continue; + } + Function calledFunction = functionManager.getFunctionAt(toAddress); + if (null != calledFunction) { + if (addresses.contains(toAddress)) { + println("const uint64_t kGetSendMessageMgr = " + address.toString() + ";"); + } + } + } + } + + } + + } + + void findMgr(ContainsTextFilterFactory factory, String mgr, String getMgr) throws CancelledException { + if (!checkFidFile()) { + return; + } + SymbolTable symbolTable = currentProgram.getSymbolTable(); + FunctionManager functionManager = currentProgram.getFunctionManager(); + + List
addresses = new ArrayList<>(); + List searchMgr = searchSymbol(symbolTable, mgr, factory, mgr); + for (Symbol symbol : searchMgr) { + Address address = symbol.getAddress(); + addresses.add(address); + } + + List searchSymbol = searchSymbol(symbolTable, getMgr, factory, getMgr); + for (Symbol symbol : searchSymbol) { + Address address = symbol.getAddress(); + Function function = functionManager.getFunctionAt(address); + if (null != function) { + AddressSetView functionBody = function.getBody(); + Address entryPoint = function.getEntryPoint(); + Set references = getReferencesFrom(currentProgram, functionBody, monitor); + for (Reference reference : references) { + monitor.checkCancelled(); + Address toAddress = reference.getToAddress(); + if (toAddress.equals(entryPoint)) { + continue; + } + Function calledFunction = functionManager.getFunctionAt(toAddress); + if (null != calledFunction) { + if (addresses.contains(toAddress)) { + println("const uint64_t k" + getMgr + " = " + address.toString() + " ;"); + } + } + } + } + + } + + } + + protected Set getReferencesFrom(Program program, AddressSetView addresses, TaskMonitor monitor) + throws CancelledException { + Set set = new HashSet<>(); + ReferenceManager referenceManager = program.getReferenceManager(); + AddressIterator addressIterator = addresses.getAddresses(true); + while (addressIterator.hasNext()) { + monitor.checkCancelled(); + Address address = addressIterator.next(); + Reference[] referencesFrom = referenceManager.getReferencesFrom(address); + if (referencesFrom != null) { + for (Reference reference : referencesFrom) { + set.add(reference); + } + } + } + return set; + } + + List searchSymbol(SymbolTable symbolTable, String text, TextFilterFactory factory, String filterText) { List list = new ArrayList<>(); TextFilter textFilter = factory.getTextFilter(filterText); SymbolIterator symbols = symbolTable.getSymbols(text); while (symbols.hasNext()) { Symbol next = symbols.next(); - if(textFilter.matches(next.getName())) { + if (textFilter.matches(next.getName())) { list.add(next); } } 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