Beispiel #1
0
 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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
 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 + ')'
Beispiel #5
0
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:
Beispiel #6
0
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: