def structureSingleLoop(self, n): ''' @return: True, if loop was structured, False otherwise. ''' (loope, ALe) = self.findLoopALEdge(n) (loop, AL) = (self.nodes[loope.toNode], self.nodes[ALe.toNode]) if loop.forloop: (forloope, AFe) = self.findForAFEdge(loop) forloop = self.nodes[forloope.toNode] AF = self.nodes[AFe.toNode] if len(forloop.outgoing) == 1 and \ forloop.outgoing[0].toNode == AF.name and \ len(AF.outgoing) == 1 and AF.outgoing[0].toNode == AL.name: forloop.code = indentForText(forloop.code) if AF.code != '': AF.code = 'else:\n' + indentText(AF.code, 1) self.removeEdge(loop, AF) self.removeEdge(n, AL) return True else: (te, fe) = self.findTrueFalseEdge(loop) (tn, fn) = (self.nodes[te.toNode], self.nodes[fe.toNode]) if len(tn.outgoing) == 1 and tn.outgoing[0].toNode == fn.name and \ len(fn.outgoing) == 1 and fn.outgoing[0].toNode == AL.name: loop.code = 'while ' + str(loop.condition) + ':\n' if tn.code == '': tn.code = 'pass\n' tn.code = indentText(tn.code, 1) if fn.code != '': fn.code = 'else:\n' + indentText(fn.code, 1) self.removeEdge(loop, fn) self.removeEdge(n, AL) return True
def mergeCompoundNodes(self, head, x, y, latch): ''' Merges two nodes in if/else construction. @param x: first (higher) node. @param y: second (lower) node. ''' # TODO: add optimization for latch node to avoid simplifyConsecutive if y is None or y.code == '': if x.code == '': x.code = 'pass\n' if isinstance(head.condition, CompareOp) and \ head.condition.value == 'EXC_MATCH': code = head.code + 'except ' + \ str(head.condition.children[1]) + indentExText(x.code) else: code = head.code + 'if ' + \ str(head.condition) + ':\n' + indentText(x.code, 1) #+ '\n' + latch.code n = node(head.name, head.incoming, x.outgoing, conditional=False, code=code, offset=head.offset) else: if x.code == '': x.code = 'pass\n' if y.code == '': y.code = 'pass\n' if isinstance(head.condition, CompareOp) and \ head.condition.value == 'EXC_MATCH': if y.conditional: code = head.code + 'except ' + \ str(head.condition.children[1]) + \ indentExText(x.code) + y.code else: code = head.code + 'except ' + \ str(head.condition.children[1]) + \ indentExText(x.code) + \ 'except:\n' + indentText(y.code, 1) else: code = head.code + 'if ' + str(head.condition) + ':\n' + \ indentText(x.code, 1) + \ 'else:\n' + indentText(y.code, 1)# + '\n' + latch.code n = node(head.name, head.incoming, x.outgoing, conditional=False, code=code, offset=head.offset) self.nodes[head.name] = n self.updateEdges(x.name, head.name) if y is not None: self.updateEdges(y.name, head.name) del self.nodes[x.name] #, self.nodes[latch.name]) if y is not None: del self.nodes[y.name]
def structureSingleLoop(self, n): ''' @return: True, if loop was structured, False otherwise. ''' #THIS ONLY WORKS IF optimizeJumps = True self.extra.append(n) #print "N: ",n (loope, ALe) = self.findLoopALEdge(n) #print "LOOPE: %s"%(loope) #print "ALe: %s"%(ALe) (loop, AL) = (self.nodes[loope.toNode], self.nodes[ALe.toNode]) #print "LOOP: %s"%(loop) #print "AL: %s"%(AL) #Rich mod change test condition to look for t/f edges not loop property if loop.forloop: (forloope, AFe) = self.findForAFEdge(loop) forloop = self.nodes[forloope.toNode] AF = self.nodes[AFe.toNode] #if len(forloop.outgoing) == 1 and \ # forloop.outgoing[0].toNode == AF.name and \ # len(AF.outgoing) == 1 and AF.outgoing[0].toNode == AL.name: if 1: forloop.code = indentForText(forloop.code) if AF.code != '': AF.code = 'else:\n' + indentText(AF.code, 1) self.removeEdge(loop, AF) self.removeEdge(n, AL) return True else: try: (te, fe) = self.findTrueFalseEdge(loop) (tn, fn) = (self.nodes[te.toNode], self.nodes[fe.toNode]) if len(tn.outgoing) == 1 and tn.outgoing[0].toNode == fn.name and \ len(fn.outgoing) == 1 and fn.outgoing[0].toNode == AL.name: loop.code = 'while ' + str(loop.condition) + ':\n' if tn.code == '': tn.code = 'pass\n' tn.code = indentText(tn.code, 1) if fn.code != '': fn.code = 'else:\n' + indentText(fn.code, 1) self.removeEdge(loop, fn) self.removeEdge(n, AL) return True except Exception, err: print "[X] Rich exception caught", err traceback.print_exc() return False
def structureSingleLoop(self, n): ''' @return: True, if loop was structured, False otherwise. ''' (loope, ALe) = self.findLoopALEdge(n) (loop, AL) = (self.nodes[loope.toNode], self.nodes[ALe.toNode]) if loop.forloop: (forloope, AFe) = self.findForAFEdge(loop) forloop = self.nodes[forloope.toNode] AF = self.nodes[AFe.toNode] if len(forloop.outgoing) == 1 and \ forloop.outgoing[0].toNode == AF.name and \ len(AF.outgoing) == 1 and AF.outgoing[0].toNode == AL.name: forloop.code = indentForText(forloop.code) if AF.code != '': AF.code = 'else:\n' + indentText(AF.code, 1) self.removeEdge(loop, AF) self.removeEdge(n, AL) return True elif len(forloop.outgoing) == 1 and \ forloop.outgoing[0].toNode == AF.name and \ AF.name == AL.name: forloop.code = indentForText(forloop.code) self.removeEdge(loop, AF) self.removeEdge(n, AL) return True else: (te, fe) = self.findTrueFalseEdge(loop) (tn, fn) = (self.nodes[te.toNode], self.nodes[fe.toNode]) if len(tn.outgoing) == 1 and tn.outgoing[0].toNode == fn.name and \ len(fn.outgoing) == 1 and fn.outgoing[0].toNode == AL.name: loop.code = 'while ' + str(loop.condition) + ':\n' if tn.code == '': tn.code = 'pass\n' tn.code = indentText(tn.code, 1) if fn.code != '': fn.code = 'else:\n' + indentText(fn.code, 1) self.removeEdge(loop, fn) self.removeEdge(n, AL) return True elif len(tn.outgoing) == 1 and tn.outgoing[0].toNode == fn.name and \ fn.name == AL.name: loop.code = 'while ' + str(loop.condition) + ':\n' if tn.code == '': tn.code = 'pass\n' tn.code = indentText(tn.code, 1) self.removeEdge(loop, fn) self.removeEdge(n, AL) return True
def decompile(self, offset=0, startIndent=0): '''Entry point for the decompilation process.''' try: cb = self.disassembler.getAllCodeBlocks(offset) print "[+] All code blocks got" flowGraph = structure.getGraphFromCodeBlocks(cb, self.debugDraw) print "[+] Flow graph from code blocks got" flowGraph.DFADecompile(self) print "[+] DFA decompiled" flowGraph.simplifyComplexIFs() print "[+] Complex IF's simplified" flowGraph.preprocessWhileLoops() print "[+] WHILE loops preprocessed" flowGraph.simplifyAllCompound() print "[+] All compounds simplified" flowGraph.simplifyConsecutive() print "[+] Consecutives simplified" if len(flowGraph.nodes) == 1: r = flowGraph.nodes[flowGraph.root].code else: print "\n\n" print "!!!INCOMPLETE DISASSEMBLY!!!!" print "%d code block uncoalesced" % len(flowGraph.nodes) #r = '>>> Fatal error: could not structure control flow graph.' r = "" ordered_nodes = flowGraph.nodes.keys() ordered_nodes.sort() for n in ordered_nodes: if len(flowGraph.nodes[n].code) == 0: continue r += "#[NODE: %s]\n%s\n" % (n, flowGraph.nodes[n].code) return indentText(r, startIndent) except: traceback.print_exc()
def str(self, depth=0): dis = disasm.Disassembler(self) ind = indent(depth + 1) r = indent(depth, self.offset) + 'CODE:\n' + \ ind + 'argcount:\n%s\n' % self.argcount.str(depth + 2) + \ ind + 'nlocals:\n%s\n' % self.nlocals.str(depth + 2) + \ ind + 'stacksize:\n%s\n' % self.stacksize.str(depth + 2) + \ ind + 'flags:\n%s\n' % self.flags.str(depth + 2) + \ indent(depth + 2) + '(' + \ ', '.join([opcodes.flags[f] for f in opcodes.flags if f & self.flags.value]) + ')\n' + \ ind + 'code:\n%s\n' % self.code.str(depth + 2) + \ indentText(dis.codeDisasm(verbose=self.verboseDisasm, xref=self.xrefDisasm), depth + 2) + \ ind + 'consts:\n%s\n' % self.consts.str(depth + 2) + \ ind + 'names:\n%s\n' % self.names.str(depth + 2) + \ ind + 'varnames:\n%s\n' % self.varnames.str(depth + 2) + \ ind + 'freevars:\n%s\n' % self.freevars.str(depth + 2) + \ ind + 'cellvars:\n%s\n' % self.cellvars.str(depth + 2) + \ ind + 'filename:\n%s\n' % self.filename.str(depth + 2) + \ ind + 'name:\n%s\n' % self.name.str(depth + 2) + \ ind + 'firslineno:\n%s\n' % self.firstlineno.str(depth + 2) + \ ind + 'lnotab:\n%s\n' % self.lnotab.str(depth + 2) return r
def structureSingleFinally(self, n): ''' @return: True, if finally was structured, False otherwise. ''' changes = False (ASFe, ASF2e, finallye) = self.findASFASF2finallyEdge(n) if ASFe is not None: # it is a try-finally case ASFn = self.nodes[ASFe.toNode] finallyn = self.nodes[finallye.toNode] # check if everything is structured... if len(ASFn.outgoing) == 1 and \ ASFn.outgoing[0].toNode == finallyn.name and \ len(finallyn.outgoing) == 1 and \ finallyn.outgoing[0].type == 'AE': if ASFn.code == '': ASFn.code = 'pass\n' ASFn.code = 'try:\n' + indentText(ASFn.code, 1) if finallyn.code == '': finallyn.code = 'pass\n' finallyn.code = 'finally:\n' + indentText(finallyn.code, 1) self.removeEdge(n, finallyn) latch = self.nodes[finallyn.outgoing[0].toNode] self.removeEdge(finallyn, latch) # remove AE self.addEdge(finallyn, latch) changes = True elif ASF2e is not None: # it is a try-except-(else)-finally case ASFn = self.nodes[ASF2e.toNode] finallyn = self.nodes[finallye.toNode] # check if everything is structured... # TODO: remove copypaste if len(ASFn.outgoing) == 1 and \ ASFn.outgoing[0].toNode == finallyn.name and \ len(finallyn.outgoing) == 1 and \ finallyn.outgoing[0].type == 'AE': if finallyn.code == '': finallyn.code = 'pass\n' finallyn.code = 'finally:\n' + indentText(finallyn.code, 1) self.removeEdge(n, finallyn) latch = self.nodes[finallyn.outgoing[0].toNode] self.removeEdge(finallyn, latch) # remove AE self.addEdge(finallyn, latch) changes = True return changes
def decompile(self, offset=0, startIndent=0, full=True): '''Entry point for the decompilation process.''' if not full: co = self.disassembler.co func = NewFunction(co) r = self.STORE(co.name.value, func, startIndent, True) return indentText(r, startIndent) else: cb = self.disassembler.getAllCodeBlocks(offset) flowGraph = structure.getGraphFromCodeBlocks(cb, self.debugDraw) flowGraph.DFADecompile(self) flowGraph.simplifyComplexIFs() flowGraph.preprocessWhileLoops() flowGraph.simplifyAllCompound() flowGraph.simplifyConsecutive() if len(flowGraph.nodes) == 1: r = flowGraph.nodes[flowGraph.root].code else: raise StructuringErrorException() #r = '>>> Fatal error: could not structure control flow graph.' return indentText(r, startIndent)
def decompile(self, offset=0, startIndent=0): '''Entry point for the decompilation process.''' cb = self.disassembler.getAllCodeBlocks(offset) flowGraph = structure.getGraphFromCodeBlocks(cb, self.debugDraw) flowGraph.DFADecompile(self) flowGraph.simplifyComplexIFs() flowGraph.preprocessWhileLoops() flowGraph.simplifyAllCompound() flowGraph.simplifyConsecutive() if len(flowGraph.nodes) == 1: r = flowGraph.nodes[flowGraph.root].code else: # TODO: throw exception r = '>>> Fatal error: could not structure control flow graph.' return indentText(r, startIndent)
def decompile(self, offset=0, startIndent=0): '''Entry point for the decompilation process.''' try: cb = self.disassembler.getAllCodeBlocks(offset) print "[+] All code blocks got" flowGraph = structure.getGraphFromCodeBlocks(cb, self.debugDraw) print "[+] Flow graph from code blocks got" flowGraph.DFADecompile(self) print "[+] DFA decompiled" flowGraph.simplifyComplexIFs() print "[+] Complex IF's simplified" flowGraph.preprocessWhileLoops() print "[+] WHILE loops preprocessed" flowGraph.simplifyAllCompound() print "[+] All compounds simplified" flowGraph.simplifyConsecutive() print "[+] Consecutives simplified" if len(flowGraph.nodes) == 1: r = flowGraph.nodes[flowGraph.root].code else: print "\n\n" print "!!!INCOMPLETE DISASSEMBLY!!!!" print "%d code block uncoalesced"%len(flowGraph.nodes) #r = '>>> Fatal error: could not structure control flow graph.' r="" ordered_nodes=flowGraph.nodes.keys() ordered_nodes.sort() for n in ordered_nodes: if len(flowGraph.nodes[n].code) == 0: continue r += "#[NODE: %s]\n%s\n"%(n, flowGraph.nodes[n].code) return indentText(r, startIndent) except: traceback.print_exc()
def structureSingleExcept(self, n): ''' @return: True, if except was structured, False otherwise. ''' changes = False # T - try, E - except, F - finally # t - true, f - false # e - edge, n - node # c - child (Te, Ee) = self.findTryExceptEdge(n) (Tn, En) = (self.nodes[Te.toNode], self.nodes[Ee.toNode]) tn = self.nodes[Ee.toNode] fn = self.nodes[Ee.toNode] (te, fe) = self.findTrueFalseEdge(fn) while fe is not None: (tn, fn) = (self.nodes[te.toNode], self.nodes[fe.toNode]) (te, fe) = self.findTrueFalseEdge(fn) if tn.name != fn.name and len(tn.outgoing) == 1 and \ len(fn.outgoing) == 1 and len(fn.incoming) == 1 and \ fn.code == '': pn = self.nodes[fn.incoming[0].fromNode] self.removeEdge(pn, fn) self.addEdge(pn, self.nodes[tn.outgoing[0].toNode], 'f') changes = True if tn.name == fn.name: if not tn.code.startswith('except ') and \ not tn.code.startswith('except:'): if tn.code == '': tn.code = 'pass\n' tn.code = 'except:\n' + indentText(tn.code, 1) changes = True # check if try block is structured TisOK = False if len(Tn.outgoing) == 1: Tnc = self.nodes[Tn.outgoing[0].toNode] for e in Tnc.incoming: if e.type == 'AE': TisOK = True break # find else block elsen = None if TisOK: if len(tn.outgoing) == 1 and \ Tn.outgoing[0].toNode == tn.outgoing[0].toNode: elsen = None else: elsen = self.nodes[Tn.outgoing[0].toNode] # check if else block is structured elseisOK = False if TisOK: if elsen is None: elseisOK = True elif len(elsen.outgoing) == 1 and len(tn.outgoing) == 1 and \ elsen.outgoing[0].toNode == tn.outgoing[0].toNode: elseisOK = True # check if except block is structured EisOK = False if TisOK and elseisOK: # TODO: separate method for index in xrange(len(n.incoming)): if n.incoming[index].type == 'ASF': n.incoming[index].type = 'ASF2' pn = self.nodes[n.incoming[index].fromNode] for index2 in xrange(len(pn.outgoing)): if pn.outgoing[index2].type == 'ASF' and \ pn.outgoing[index2].toNode == n.name: pn.outgoing[index2].type = 'ASF2' changes = True if elsen is not None and len(En.outgoing) == 1 and \ En.outgoing[0].toNode == elsen.outgoing[0].toNode: if Tn.code == '': Tn.code = 'pass\n' Tn.code = 'try:\n' + indentText(Tn.code, 1) if elsen.code == '': elsen.code = 'pass\n' elsen.code = 'else:\n' + indentText(elsen.code, 1) self.removeEdge(n, En) self.removeEdge(En, self.nodes[En.outgoing[0].toNode]) self.removeEdge(Tn, elsen) dummyname = elsen.incoming[0].fromNode self.removeEdge(self.nodes[dummyname], elsen) del self.nodes[dummyname] self.addEdge(Tn, En) self.addEdge(En, elsen) changes = True elif elsen is None and len(En.outgoing) == 1 and \ En.outgoing[0].toNode == Tn.outgoing[0].toNode: latch = self.nodes[En.outgoing[0].toNode] if Tn.code == '': Tn.code = 'pass\n' Tn.code = 'try:\n' + indentText(Tn.code, 1) self.removeEdge(n, En) self.removeEdge(Tn, latch) for index in xrange(len(latch.incoming)): if latch.incoming[index].type == 'AE': dummyname = latch.incoming[index].fromNode self.removeEdge(self.nodes[dummyname], latch) del self.nodes[dummyname] break self.addEdge(Tn, En) changes = True return changes