def Test(ctx): assert isinstance(ctx, IClientContext) input_path = r"D:\tmp\2\project\about_dex_diff\code\jsq\jsq.dex" class_sign = "Lcom/BestCalculatorCN/MyCalculator;" method_sign = "Lcom/BestCalculatorCN/MyCalculator;->b(Lcom/BestCalculatorCN/MyCalculator;Ljava/lang/String;)V" unit = ctx.open(input_path) assert isinstance(unit, IUnit) prj = ctx.getMainProject() assert isinstance(prj, IRuntimeProject) dexUnit = prj.findUnit(IDexUnit) assert isinstance(dexUnit, IDexUnit) clz = dexUnit.getClass(class_sign) assert isinstance(clz, IDexClass) method = dexUnit.getMethod(method_sign) assert isinstance(method, IDexMethod) # 1 查询某method交叉引用列表 # 使用(unit,操作,地址,itemid)来创建一个context对象,提供给JEB引擎,用于后续执行 print "------------------------------------------------" actionXrefsData = ActionXrefsData() actionContext = ActionContext(dexUnit, Actions.QUERY_XREFS, method.getItemId(), None) if unit.prepareExecution(actionContext, actionXrefsData): for xref_addr in actionXrefsData.getAddresses(): print xref_addr # 2 查询整个class的交叉引用列表 print "------------------------------------------------" actionXrefsData = ActionXrefsData() actionContext = ActionContext(dexUnit, Actions.QUERY_XREFS, clz.getItemId(), None) if unit.prepareExecution(actionContext, actionXrefsData): for idx, xref_addr in enumerate(actionXrefsData.getAddresses()): print idx, xref_addr
def getMethodXrefs(self, unit, itemId): data = ActionXrefsData() # careful, with query-type actions, the data is returned after the action prep' if unit.prepareExecution( ActionContext(unit, Actions.QUERY_XREFS, itemId, None), data): # clean up the DEX address, extrac the method name return data.getAddresses()
def append_cls_name(self, cls, append_str): p = re.compile("^.*\/([\w$-]+);$") # cls_name has package path cls_name = cls.getSignature(True) if cls_name.find(append_str) == -1: s = re.search(p, cls_name) if not s: return False simple_new_name = s.group(1) + '_' + append_str actCntx = ActionContext(self.dex, Actions.RENAME, cls.getItemId(), cls.getAddress()) actData = ActionRenameData() actData.setNewName(simple_new_name) if self.dex.prepareExecution(actCntx, actData): try: bRlt = self.dex.executeAction(actCntx, actData) if (not bRlt): print(u'executeAction fail!') return False else: return True except Exception, e: return self.jeb.renameClass(cls_name, simple_new_name) else: return False
def xrefs_for(unit, item): data = ActionXrefsData() if unit.prepareExecution( ActionContext(unit, Actions.QUERY_XREFS, item.itemId, item.address), data): return data.addresses return []
def setOrStoreDecryptedStr(self, unit, itemId, comment, key): data = ActionXrefsData() if unit.prepareExecution(ActionContext(unit, Actions.QUERY_XREFS, itemId, None), data): if data.getAddresses().size() > 1: # If the variable is called by other class(main target class) self.dic[key] = comment # Store the key value pair into the dictionary else: self.addComments(self.codeUnit, itemId, comment) # If the variable is not called by other class(main target class), add the decrypted string as comment directly return "NULL"
def get_xrefs_by_item(dunit, itemid, addr): data = ActionXrefsData() result = [] if dunit.prepareExecution(ActionContext(dunit, Actions.QUERY_XREFS, itemid, addr), data): # item.getSignature() for xref_addr in data.getAddresses(): # print(xref_addr) result.append(xref_addr) return result
def findClassXRef(self, units, itemId, itemAddress): refs = [] for unit in units: data = ActionXrefsData() if unit.prepareExecution( ActionContext(unit, Actions.QUERY_XREFS, itemId, itemAddress), data): if len(data.getAddresses()) > 0: refs.append((unit, data.getAddresses())) return refs
def addComments(self, unit, itemId, comment): data = ActionCommentData() # Create a new instance of ActionCommentData data.setNewComment(comment) # Add the decrypted string as comment to data address = unit.getAddressOfItem(itemId) # Set the comment ctx = ActionContext(unit, Actions.COMMENT, itemId, address) if unit.prepareExecution(ctx, data): r = unit.executeAction(ctx, data) if not r: print('Cannot set comment at address %s' % address)
def searchOveride(self,dId, dAddr): actCntx = ActionContext(self.targetUnit, Actions.QUERY_OVERRIDES, dId, dAddr) actData = ActionOverridesData() if(self.targetUnit.prepareExecution(actCntx, actData)): try: bRlt = self.targetUnit.executeAction(actCntx, actData) if(not bRlt): print('executeAction fail!') except Exception, e: print Exception, ":", e return []
def findMethodXRef(self, units, itemId, itemAddress, refs): preNode = refs.getCurrentNode() refs.setCurrentNodeById(itemId) sub_address = [] total = 0 for unit in units: data = ActionXrefsData() if unit.prepareExecution( ActionContext(unit, Actions.QUERY_XREFS, itemId, itemAddress), data): if len(data.getAddresses()) > 0: sub_address.append((unit, data.getAddresses())) total += len(data.getAddresses()) else: row_m = unit.getMethod(itemAddress) impl_class = row_m.getClassType().getImplementingClass() if re.search(r'(\$\d+?)+;$', impl_class.getAddress()) != None: # sub_address.append((unit, impl_class.getAddress())) clxXref = self.findClassXRef(units, impl_class.getItemId(), impl_class.getAddress()) sub_address.extend(clxXref) for (unit, addresses) in clxXref: total += len(addresses) refs.getCurrentNode().setXrefCount(total) for (unit, addresses) in sub_address: for xref_addr in addresses: indexObj = re.search(r'\+[0-9A-F]+?h$', xref_addr) if indexObj != None: index = indexObj.group() last_index = 0 - len(index) method = unit.getMethod(xref_addr[0:last_index]) node = refs.buildNode(method.getItemId(), method.getAddress()) if node == None: refs.setCurrentNodeById(preNode.itemId) return else: self.findMethodXRef(units, method.getItemId(), method.getAddress(), refs) else: method = unit.getMethod(xref_addr) node = refs.buildNode(method.getItemId(), method.getAddress()) if node == None: refs.setCurrentNodeById(preNode.itemId) return else: self.findMethodXRef(units, method.getItemId(), method.getAddress(), refs) refs.setCurrentNodeById(preNode.itemId) return
def getMethodRefs(self, unit, itemId): r = [] data = ActionXrefsData() # careful, with query-type actions, the data is returned after the action prep' if unit.prepareExecution(ActionContext(unit, Actions.QUERY_XREFS, itemId, None), data): # clean up the DEX address, extrac the method name for a in data.getAddresses(): i = a.find('->') + 2 j = a.find('(', i) r.append(a[i:j]) return r
def comment_class(self, unit, originClazz, commentStr): actCtx = ActionContext(unit, Actions.COMMENT, originClazz.getItemId(), originClazz.getAddress()) actData = ActionCommentData() actData.setNewComment(commentStr) if unit.prepareExecution(actCtx, actData): try: result = unit.executeAction(actCtx, actData) except Exception, e: print(Exception, e)
def commentClass(self, unit, clz, adr): ctx = ActionContext(unit, Actions.COMMENT, clz.getItemId(), clz.getAddress()) data = ActionCommentData() data.setNewComment(adr.replace('/', ".")[1:-1]) if not unit.prepareExecution(ctx, data): return False try: return unit.executeAction(ctx, data) except Exception as e: print(Exception, e) return False
def renameClass(self, unit, clz, sname): ctx = ActionContext(unit, Actions.RENAME, clz.getItemId(), clz.getAddress()) data = ActionRenameData() data.setNewName(sname) if not unit.prepareExecution(ctx, data): return False try: return unit.executeAction(ctx, data) except Exception as e: print(Exception, e) return False
def getItemOriginalName(self, item): actCntx = ActionContext(self.focusUnit, Actions.RENAME, item.getItemId(), item.getSignature()) actData = ActionRenameData() originalName = "" if self.focusUnit.prepareExecution(actCntx, actData): try: originalName = actData.getOriginalName() assert (item.getName() == actData.getCurrentName()) except Exception as e: print(e) return originalName
def getItemOriginalName(self, viewName, itemId, viewAddress): actCntx = ActionContext(self.focusUnit, Actions.RENAME, itemId, viewAddress) actData = ActionRenameData() originalName = "" if self.focusUnit.prepareExecution(actCntx, actData): try: originalName = actData.getOriginalName() assert (viewName == actData.getCurrentName()) except Exception as e: print(e) return originalName
def rename_class(self, unit, originClazz, sourceName, isBackup): actCtx = ActionContext(unit, Actions.RENAME, originClazz.getItemId(), originClazz.getAddress()) actData = ActionRenameData() actData.setNewName(sourceName) if unit.prepareExecution(actCtx, actData): try: result = unit.executeAction(actCtx, actData) if not result: print('rename to %s failed!' % sourceName) except Exception, e: print(Exception, e)
def run(self, ctx): unit = ctx.getActiveView().getUnit() print(unit.getFormatType()) current_addr = ctx.getActiveView().getActiveFragment( ).getActiveAddress() print(current_addr) current_item = ctx.getActiveView().getActiveFragment().getActiveItem() print(current_item) data = ActionXrefsData() if unit.prepareExecution( ActionContext(unit, Actions.QUERY_XREFS, current_item.getItemId(), current_addr), data): for xref_addr in data.getAddresses(): print(xref_addr)
def rename(self, obj, new_name): actCntx = ActionContext(self.unit, Actions.RENAME, obj.getItemId(), obj.getAddress()) actData = ActionRenameData() actData.setNewName(new_name) if self.unit.prepareExecution(actCntx, actData): try: res = self.unit.executeAction(actCntx, actData) if not res: print(u'rename failed [new_name %s]' % new_name) return False else: return True except Exception,e: print(e) return False
def commenceRename(self, originName, newName, isClass): if isClass == 0: clz = self.targetUnit.getClass(originName) elif isClass == 1: clz = self.targetUnit.getField(originName) else: clz = self.targetUnit.getMethod(originName) actCntx = ActionContext(self.targetUnit, Actions.RENAME, clz.getItemId(), clz.getAddress()) actData = ActionRenameData() actData.setNewName(newName) if (self.targetUnit.prepareExecution(actCntx, actData)): # 执行重命名动作 try: bRlt = self.targetUnit.executeAction(actCntx, actData) if (not bRlt): print(u'executeAction fail!') except Exception, e: print Exception, ":", e
def rename(self, unit, origin, source, flag): actCtx = ActionContext(unit, Actions.RENAME, origin.getItemId(), origin.getAddress()) actData = ActionRenameData() if flag == 'field': newName = 'm%s_%d' % (source, self.count) self.count += 1 else: newName = '%s___%s' % (source, origin.getName(True)) actData.setNewName(newName) if unit.prepareExecution(actCtx, actData): try: result = unit.executeAction(actCtx, actData) if result: print('rename to %s success!' % newName) else: print('rename to %s failed!' % newName) except Exception, e: print(Exception, e)
def run(self, ctx): unit = ctx.getFocusedUnit() assert unit, 'Need a focused unit fragment' print(unit.getFormatType()) current_addr = ctx.getFocusedAddress() print(current_addr) current_item = ctx.getFocusedItem() print(current_item) data = ActionXrefsData() if unit.prepareExecution( ActionContext( unit, Actions.QUERY_XREFS, 0 if not current_item else current_item.getItemId(), current_addr), data): for xref_addr in data.getAddresses(): print(xref_addr)
def commenceRename(self, codeUnit, ClassName, newName): clz = codeUnit.getClass(ClassName) #clz = codeUnit.getMethod(ClassName) print("[+] Change class name from [ %s ] to [ %s ] " % (ClassName, newName)) #print(clz) actCntx = ActionContext(codeUnit, Actions.RENAME, clz.getItemId(), clz.getAddress()) actData = ActionRenameData() actData.setNewName(newName) if (codeUnit.prepareExecution(actCntx, actData)): try: bRlt = codeUnit.executeAction(actCntx, actData) if (not bRlt): print(u'executeAction fail!') except Exception, e: print Exception, ":", e
def rename_class(self, unit, originClazz, sourceName): actCtx = ActionContext(unit, Actions.RENAME, originClazz.getItemId(), originClazz.getAddress()) actData = ActionRenameData() actData.setNewName(sourceName) if unit.prepareExecution(actCtx, actData): try: originalName = actData.getOriginalName() if len( originalName ) > 10: # Skip for general cases: already have meaningful class name return sourceName result = unit.executeAction(actCtx, actData) if result: print('rename %s to %s success!' % (originalName, originClazz.getAddress())) else: print('rename to %s failed!' % sourceName) except Exception, e: print(Exception, e)
def renameItembySig(self, codeType, signature, newName): x = None for cu in self.codeUnits: if codeType == "Field": x = cu.getField(signature) elif codeType == "Method": x = cu.getMethod(signature) elif codeType == "Class": x = cu.getClass(signature) else: raise Exception("execute renameItembySig with unknown codeType!") if x: break if not x: return itemId = x.getItemId() itemAddress = x.getAddress() itemSig = x.getSignature() actCntx = ActionContext(cu, Actions.RENAME, itemId, itemAddress) actData = ActionRenameData() if cu.prepareExecution(actCntx, actData): try: originalName = actData.getOriginalName() getCurrentName = actData.getCurrentName() if newName == getCurrentName: return newName actData.setNewName(newName) bRlt = cu.executeAction(actCntx, actData) if not bRlt: print(u'Failure Action %s' % itemAddress) else: pass except Exception as e: print(e) return newName
def RenameItem(self, unit, itemId, itemAddress, prefix=""): actCntx = ActionContext(unit, Actions.RENAME, itemId, itemAddress) actData = ActionRenameData() if unit.prepareExecution(actCntx, actData): try: getCurrentName = actData.getCurrentName() if "_" in getCurrentName: return getCurrentName originalName = actData.getOriginalName() if prefix: prefix += "_" newName = prefix + self.methodNameTransform(originalName) if not newName or newName == getCurrentName: return getCurrentName actData.setNewName(newName) bRlt = unit.executeAction(actCntx, actData) except Exception as e: print(e)
def clusterUnit(self, codeUnit, basePackage=''): #print(codeUnit) typeToInternalMethods = {} typeToExternalMethods = {} # method -> list of called methods methodToMethods = {} # reverse map: method -> list of methods callers xmethodToMethods = {} methodToType = {} for classObject in codeUnit.getClasses(): if (classObject.getGenericFlags() & ICodeItem.FLAG_INNER) != 0: #print('Inner class, skipping: %s' % classObject) continue pname = classObject.getPackage().getSignature(True) pname = pname[1:-1].replace('/', '.') + '.' if not pname.startswith(basePackage): #print('Class not in target package, skipping: %s' % classObject) continue typeIndex = classObject.getClassType().getIndex() typeToInternalMethods[typeIndex] = [] methodObjects = classObject.getMethods() if not methodObjects: continue print('Processing: %s (type: %d)' % (classObject, typeIndex)) for methodObject in methodObjects: methodIndex = methodObject.getIndex() typeToInternalMethods[typeIndex].append(methodIndex) methodToType[methodIndex] = typeIndex #print(methodObject) instructions = methodObject.getInstructions() if not instructions: continue print(' %s' % methodObject) for insn in instructions: s = insn.format(None) refMethodIndex = self.extractMethodIndex(s) if refMethodIndex >= 0: print(' %d -> %d' % (methodIndex, refMethodIndex)) if methodIndex not in methodToMethods: methodToMethods[methodIndex] = [] methodToMethods[methodIndex].append(refMethodIndex) #if refMethodIndex not in xmethodToMethods: # xmethodToMethods[refMethodIndex] = [] #xmethodToMethods[refMethodIndex].append(methodIndex) # derive type-to-type connections # map: edge(couple=src,dst) TO weight(int) edgemap = {} vertices = set() for methodIndex in methodToMethods: typeIndex = methodToType[methodIndex] for targetMethodIndex in methodToMethods[methodIndex]: targetTypeIndex = methodToType.get(targetMethodIndex, -1) if targetTypeIndex >= 0 and targetTypeIndex != typeIndex: #print ('%d -> %d' % (typeIndex, targetTypeIndex)) edge = (typeIndex, targetTypeIndex) vertices.add(typeIndex) vertices.add(targetTypeIndex) if edge not in edgemap: edgemap[edge] = 0 edgemap[edge] += 1 types = codeUnit.getTypes() # graph definition (graphviz) gd = 'digraph {\n' for typeIndex in vertices: gd += ' %d [label="%s"]\n' % (typeIndex, self.getTypeLabel(types[typeIndex])) gd += '\n' for edge, weight in edgemap.items(): gd += ' %d -> %d [weight=%d]\n' % (edge[0], edge[1], weight) gd += '}' with open(os.path.join(self.outputDir, 'graph.dot'), 'w') as f: f.write(gd) # graph definition (custom, for igraph) gd = '# vertices (%d)\n' % len(vertices) for typeIndex in vertices: gd += 'v,%d\n' % typeIndex gd += '# edges (%d)\n' % len(edgemap) for edge, weight in edgemap.items(): gd += 'e,%d,%d,%d\n' % (edge[0], edge[1], weight) fileGraph = os.path.join(self.outputDir, 'graph.txt') with open(fileGraph, 'w') as f: f.write(gd) # clustering (external) fileClusteringScript = os.path.join(self.outputDir, 'cluster.py') fileClusters = os.path.join(self.outputDir, 'graph-clusters.txt') task = ClusterTask(fileClusteringScript, fileGraph, fileClusters) if isinstance(self.ctx, IGraphicalClientContext): self.ctx.executeAsync('Clustering...', task) else: task.run() # reading clusters clusters = self.readClusters(fileClusters) print('Clusters(types): %s' % clusters) # refactoring for i, cluster in enumerate(clusters): pname = basePackage + 'cluster%03d' % i # create a package clusterX data = ActionCreatePackageData() data.setFqname(pname) codeUnit.executeAction( ActionContext(codeUnit, Actions.CREATE_PACKAGE, 0, None), data) # move related classes to the virtual package for typeIndex in cluster: t = types[typeIndex] c = t.getImplementingClass() itemId = c.getItemId() data = ActionMoveToPackageData() data.setDstPackageFqname(pname) codeUnit.executeAction( ActionContext(codeUnit, Actions.MOVE_TO_PACKAGE, itemId, None), data)