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 run(self, trace=False, show_speed=False): tick = 0 last_time = time.time() last_cycle = self.cycle if trace: disassembler = disasm.Disassembler(self.memory) while True: pc = self.memory[PC] w = self.memory[pc] self.memory[PC] += 1 operands, opcode = divmod(w, 16) b, a = divmod(operands, 64) if trace: disassembler.offset = pc print("(%08X) %s" % (self.cycle, disassembler.next_instruction())) if opcode == 0x00: if a == 0x00: break arg1 = None opcode = (a << 4) + 0x0 else: arg1 = self.get_operand(a) op = self.opcodes[opcode] arg2 = self.get_operand(b, dereference=True) if self.skip: if trace: print("skipping") self.skip = False else: if 0x01 <= opcode <= 0xB: # write to memory oldval = self.memory[arg1] op(arg1, arg2) val = self.memory[arg1] if oldval != val: for p in self.plugins: p.memory_changed(self, arg1, val, oldval) else: op(arg1, arg2) if trace: self.dump_registers() self.dump_stack() tick += 1 if tick >= 100000: if show_speed: print("%dkHz" % (int((self.cycle - last_cycle) / (time.time() - last_time)) / 1000)) last_time = time.time() last_cycle = self.cycle tick = 0 try: for p in self.plugins: p.tick(self) except SystemExit: break
def STORE(self, lvalue, rvalue, curIndent, emptystack): ''' This method handles all STORE_* commands. @param lvalue: destination, where data is stored. @param rvalue: source of data. @param curIndent: current indent in the generated source code. @param emptystack: should be True if no postponed stores are expected. ''' r = '' if isinstance(rvalue, NewFunction): r += ind(curIndent) + 'def ' + lvalue + '(' r += rvalue.getParams() r += '):\n' da = disasm.Disassembler(rvalue.value, optimizeJumps=True) x = Decompiler(da).decompile(startIndent=curIndent + 1) if x in ('', '\n'): x = ind(curIndent + 1) + 'pass\n' r += x + '\n' elif isinstance(rvalue, NewClass): r += 'class ' + lvalue + '(' r += ', '.join(x.value for x in rvalue.baseclasses.value) r += '):\n' # offset=6 to avoid __module__ = __name__ duplication co = self.findCoByName(rvalue.classname.value) da = disasm.Disassembler(co, optimizeJumps=True) dc = Decompiler(da) x = dc.decompile(offset=6, startIndent=curIndent + 1) + '\n' if x in ('', '\n'): x = ind(curIndent + 1) + 'pass\n' r += x + '\n' elif isinstance(rvalue, Import): if rvalue.module.split('.')[0] != lvalue: # TODO: recheck if rvalue can be != self.co.names... here... r += ind(curIndent) + \ 'import %s as %s\n' % (rvalue.module, lvalue) else: r += ind(curIndent) + 'import %s\n' % rvalue.module elif isinstance(rvalue, ImportFrom): rvalue.importobj.addFrom(rvalue.name, lvalue) elif isinstance(rvalue, InplaceOp): storedIn = str(lvalue) + ' ' if storedIn == str(rvalue)[:len(storedIn)]: r += ind(curIndent) + str(rvalue) + '\n' else: r += ind(curIndent) + '# INPLACE_* op used not as INPLACE!!!\n' # TODO: possible error r += ind(curIndent) + str(lvalue) + ' = ' + \ rvalue.children[0] + ' ' + rvalue.value + \ ' ' + rvalue.children[1] + '\n' elif isinstance(rvalue, Iterator): r += ind(curIndent) + 'for ' + str(lvalue) + ' in ' + \ str(rvalue) + ':\n' elif isinstance(rvalue, DummyEx): # quite a hack here... take a look at mergeCompoundNodes # for more info r += '# as ' + str(lvalue) + '\n' else: if not emptystack: self.postponedStores.append((lvalue, rvalue)) else: if len(self.postponedStores) == 0: r += ind(curIndent) + str(lvalue) + ' = ' + \ str(rvalue) + '\n' else: self.postponedStores.append((lvalue, rvalue)) r += ind(curIndent) + '(' + \ ', '.join(str(x[0]) for x in self.postponedStores) + \ ') = (' + \ ', '.join(str(x[1]) for x in self.postponedStores) + \ ')\n' self.postponedStores = [] return r
def __str__(self): od = disasm.Disassembler(self.value, optimizeJumps=True) # cut out 'return ' and '\n' x = decompile.Decompiler(od).decompile()[7:-1] return '(lambda ' + self.getParams() + ': ' + x + ')'
def start(): '''Starts the unpyc application.''' def copyright(option, opt_str, value, parser, *args, **kwargs): print __copyright def license(option, opt_str, value, parser, *args, **kwargs): print __license def version(option, opt_str, value, parser, *args, **kwargs): print __version def help(option, opt_str, value, parser, *args, **kwargs): print '--== Help ==--' parser.print_help() print parser = optparse.OptionParser(usage=__usage, add_help_option=False) decompileGroup = optparse.OptionGroup(parser, 'Decompilation') decompileGroup.add_option('-D', '--decompile', action='store_true', dest='decompile', default=False, help='decompile') decompileGroup.add_option('--debugDraw', action='store_true', dest='debugDraw', default=False, help='draw intermediate CFGs') disasmGroup = optparse.OptionGroup(parser, 'Disassembly') disasmGroup.add_option('-d', '--disassemble', action='store_true', dest='disassemble', default=False, help='disassemble') disasmGroup.add_option('-x', '--xref', action='store_true', dest='xref', default=False, help='show basic blocks and xrefs') disasmGroup.add_option('-v', action='count', dest='verbose', default=0, help='verbose, use twice for more verbosity') commonGroup = optparse.OptionGroup(parser, 'Common') commonGroup.add_option('-q', '--quiet', action='store_true', dest='quiet', default=False, help='don\'t print --== Disasm ==--, #--== Decompile ==--') guiGroup = optparse.OptionGroup(parser, 'Gui') guiGroup.add_option('-g', '--gui', action='store_true', dest='gui', default=False, help='gui (control flow graph)') infoGroup = optparse.OptionGroup(parser, 'Info') infoGroup.add_option('-c', '--copyright', action='callback', callback=copyright, help='copyright') infoGroup.add_option('-l', '--license', action='callback', callback=license, help='license') infoGroup.add_option('-V', '--version', action='callback', callback=version, help='version') infoGroup.add_option('-h', '--help', action='callback', callback=help, help='show this help message') parser.add_option_group(decompileGroup) parser.add_option_group(disasmGroup) parser.add_option_group(commonGroup) parser.add_option_group(guiGroup) parser.add_option_group(infoGroup) (options, args) = parser.parse_args() if options.disassemble or options.decompile or options.gui: if len(args) != 1: parser.error('incorrect number of arguments') else: filename = args[0] try: parser = parse.Parser(filename, verboseDisasm=options.verbose, xrefDisasm=options.xref) disassembler = disasm.Disassembler(parser.co) optimizingDisassembler = disasm.Disassembler(parser.co, optimizeJumps=True) decompiler = decompile.Decompiler(optimizingDisassembler, options.debugDraw) except (parse.ParseErrorException, parse.IOErrorException, parse.BadFirstObjectException), p: print p sys.exit(-1) except:
def start(): '''Starts the unpyc application.''' def copyright(option, opt_str, value, parser, *args, **kwargs): print __copyright def license(option, opt_str, value, parser, *args, **kwargs): print __license def version(option, opt_str, value, parser, *args, **kwargs): print __version def help(option, opt_str, value, parser, *args, **kwargs): print '--== Help ==--' parser.print_help() print parser = optparse.OptionParser(usage=__usage, add_help_option=False) decompileGroup = optparse.OptionGroup(parser, 'Decompilation') decompileGroup.add_option('-D', '--decompile', action='store_true', dest='decompile', default=False, help='decompile') decompileGroup.add_option('--debugDraw', action='store_true', dest='debugDraw', default=False, help='draw intermediate CFGs') decompileGroup.add_option('--test', dest='selfTest', default='-1', metavar='STRICT', help='run diff of the original and generated ' \ 'pyc files after decompilation '\ 'if STRICT is 0 - ignore filename, firstlineno, lnotab; ' \ 'if STRICT is 1 - ignore filename; ' \ 'if STRICT is 2 - pyc files should be identical; ' \ '$? is 0 if diff was ok, 1 if not') disasmGroup = optparse.OptionGroup(parser, 'Disassembly') disasmGroup.add_option('-d', '--disassemble', action='store_true', dest='disassemble', default=False, help='disassemble') disasmGroup.add_option('-x', '--xref', action='store_true', dest='xref', default=False, help='show basic blocks and xrefs') disasmGroup.add_option('-v', action='count', dest='verbose', default=0, help='verbose, use twice for more verbosity') commonGroup = optparse.OptionGroup(parser, 'Common') commonGroup.add_option('--colist', action='store_true', dest='colist', default=False, help='list names of all code-objects') commonGroup.add_option( '--co', dest='coname', default=None, metavar='NAME', help='specify code-object to work with in a dotted manner') commonGroup.add_option( '-q', '--quiet', action='store_true', dest='quiet', default=False, help='don\'t print --== HEADER ==-- and diff output') diffGroup = optparse.OptionGroup(parser, 'Diff') diffGroup.add_option('--diff', dest='diff', default='-1', metavar='STRICT', help='compare two pyc files, STRICT is 0, 1, 2') guiGroup = optparse.OptionGroup(parser, 'Gui') guiGroup.add_option('-g', '--gui', action='store_true', dest='gui', default=False, help='gui (control flow graph)') infoGroup = optparse.OptionGroup(parser, 'Info') infoGroup.add_option('-c', '--copyright', action='callback', callback=copyright, help='copyright') infoGroup.add_option('-l', '--license', action='callback', callback=license, help='license') infoGroup.add_option('-V', '--version', action='callback', callback=version, help='version') infoGroup.add_option('-h', '--help', action='callback', callback=help, help='show this help message') parser.add_option_group(decompileGroup) parser.add_option_group(disasmGroup) parser.add_option_group(commonGroup) parser.add_option_group(diffGroup) parser.add_option_group(guiGroup) parser.add_option_group(infoGroup) (options, args) = parser.parse_args() if options.disassemble or options.decompile or \ options.gui or options.colist: if len(args) != 1: parser.error('incorrect number of arguments') else: filename = args[0] co = None full = True try: parser = parse.Parser(filename, verboseDisasm=options.verbose, xrefDisasm=options.xref) if options.coname is not None: full = False co = parser.findCoByAbsName(options.coname) if co is None: raise parse.CoNotFoundException(options.coname) else: co = parser.co disassembler = disasm.Disassembler(co) optimizingDisassembler = disasm.Disassembler( co, optimizeJumps=True) decompiler = decompile.Decompiler(optimizingDisassembler, options.debugDraw) except (parse.ParseErrorException, parse.IOErrorException, parse.BadFirstObjectException, parse.CoNotFoundException), p: print p sys.exit(-1) except: