Esempio n. 1
0
 def _convert(self, value):
     if isinstance(value, disasm.Module):
         return self._covert(value.body)
     elif isinstance(value, disasm.CodeObject):
         return Block(*[self._convert(x) for x in value.opcodes])
     elif isinstance(value, disasm.Opcode):
         arg = value.argument
         if isinstance(arg, list): arg = List(*[self._convert(x) for x in arg])
         elif isinstance(arg, tuple): arg = Tuple(*[self._convert(x) for x in arg])
         elif isinstance(arg, set): arg = Call(Ident('set'), Tuple(*[self._convert(x) for x in arg]))
         elif isinstance(arg, frozenset): arg = Call(Ident('frozenset'), Tuple(*[self._convert(x) for x in arg]))
         else: arg = self._convert(arg)
         return Opcode(value.offset, value.size, value.opcode, arg if op.has_argument(value.opcode) else None)
     else:
         return Const(value)
Esempio n. 2
0
    def unmarshal_node(self):
        type = self.read_int8()

        # Global singletons
        if type == _TYPE_NONE: return None
        elif type == _TYPE_TRUE: return True
        elif type == _TYPE_FALSE:
            return False

            # Collections
        elif type == _TYPE_TUPLE:
            return self.unmarshal_collection(tuple)
        elif type == _TYPE_LIST:
            return self.unmarshal_collection(list)
        elif type == _TYPE_SET:
            return self.unmarshal_collection(set)
        elif type == _TYPE_FROZEN_SET:
            return self.unmarshal_collection(frozenset)

            # Numbers
        elif type == _TYPE_INT:
            return self.read_int32()
        elif type == _TYPE_INT64:
            return struct.unpack('=q', self.file.read(8))[0]
        elif type == _TYPE_BINARY_FLOAT:
            return struct.unpack('=d', self.file.read(8))[0]
        elif type == _TYPE_BINARY_COMPLEX:
            return complex(*struct.unpack('=dd', self.file.read(16)))
        elif type == _TYPE_LONG:
            nbits = self.read_int32()
            if not nbits:
                return 0
            n = 0
            for i in range(abs(nbits)):
                digit = self.read_int16()
                n |= digit << (i * 15)
            return n if nbits > 0 else -n

        # Strings
        elif type == _TYPE_STRING:
            return self.read_string_ascii()
        elif type == _TYPE_UNICODE:
            return self.read_string_utf8()
        elif type == _TYPE_INTERNED:
            data = self.read_string_ascii()
            self.string_table.append(data)
            return data
        elif type == _TYPE_STRING_REF:
            index = self.read_int32()
            if index < 0 or index >= len(self.string_table):
                raise DisassemblerException(
                    'String index %d is outside string table' % index)
            return self.string_table[index]

        # Code objects
        elif type == _TYPE_CODE:
            co = CodeObject()
            co.co_argcount = self.read_int32()
            co.co_kwonlyargcount = self.read_int32() if op.has_kwonlyargcount(
                self.magic) else 0
            co.co_nlocals = self.read_int32()
            co.co_stacksize = self.read_int32()
            co.co_flags = self.read_int32()
            type = self.read_int8()
            if type != _TYPE_STRING:
                raise DisassemblerException(
                    'Bytecode was not marshalled as a string (type was 0x%02X instead of 0x%02X)'
                    % (type, _TYPE_STRING))
            co.co_code = self.read_byte_array()
            co.co_consts = self.unmarshal_node()
            co.co_names = self.unmarshal_node()
            co.co_varnames = self.unmarshal_node()
            co.co_freevars = self.unmarshal_node()
            co.co_cellvars = self.unmarshal_node()
            co.co_filename = self.unmarshal_node()
            co.co_name = self.unmarshal_node()
            co.co_firstlineno = self.read_int32()
            co.co_lnotab = self.unmarshal_node()

            # Start disassembly
            argument = 0
            i = 0
            while i < len(co.co_code):
                offset = i
                opcode = op.from_bytecode(co.co_code[i], self.magic)
                if opcode is None:
                    raise DisassemblerException('Unknown bytecode 0x%02X' %
                                                co.co_code[i])
                i += 1

                if op.has_argument(opcode):
                    lo, hi = co.co_code[i:i + 2]
                    argument |= (lo | (hi << 8))
                    i += 2

                # The upper 16 bits of 32-bit arguments are stored in a fake
                # EXTENDED_ARG opcode that precedes the actual opcode
                if opcode == op.EXTENDED_ARG:
                    argument <<= 16
                    continue

                # Decode the opcode argument if present
                arg = None
                if op.has_argument(opcode):
                    if opcode == op.LOAD_CONST:
                        if argument >= len(co.co_consts):
                            raise DisassemblerException(
                                'Invalid argument %d for opcode %s' %
                                (argument, opcode))
                        arg = co.co_consts[argument]
                    elif opcode in [
                            op.LOAD_NAME, op.STORE_NAME, op.DELETE_NAME,
                            op.LOAD_ATTR, op.STORE_ATTR, op.DELETE_ATTR,
                            op.LOAD_GLOBAL, op.STORE_GLOBAL, op.DELETE_GLOBAL,
                            op.IMPORT_NAME, op.IMPORT_FROM
                    ]:
                        if argument >= len(co.co_names):
                            raise DisassemblerException(
                                'Invalid argument %d for opcode %s' %
                                (argument, opcode))
                        arg = co.co_names[argument]
                    elif opcode in [
                            op.LOAD_FAST, op.STORE_FAST, op.DELETE_FAST
                    ]:
                        if argument >= len(co.co_varnames):
                            raise DisassemblerException(
                                'Invalid argument %d for opcode %s' %
                                (argument, opcode))
                        arg = co.co_varnames[argument]
                    else:
                        arg = argument

                # Record disassembled opcode
                co.opcodes.append(Opcode(offset, i - offset, opcode, arg))
                argument = 0

            return co

        else:
            raise DisassemblerException(
                'Cannot unmarshal unknown type 0x%02X' % type)
Esempio n. 3
0
    def unmarshal_node(self):
        type = self.read_int8()

        # Global singletons
        if type == _TYPE_NONE: return None
        elif type == _TYPE_TRUE: return True
        elif type == _TYPE_FALSE: return False

        # Collections
        elif type == _TYPE_TUPLE: return self.unmarshal_collection(tuple)
        elif type == _TYPE_LIST: return self.unmarshal_collection(list)
        elif type == _TYPE_SET: return self.unmarshal_collection(set)
        elif type == _TYPE_FROZEN_SET: return self.unmarshal_collection(frozenset)

        # Numbers
        elif type == _TYPE_INT: return self.read_int32()
        elif type == _TYPE_INT64: return struct.unpack('=q', self.file.read(8))[0]
        elif type == _TYPE_BINARY_FLOAT: return struct.unpack('=d', self.file.read(8))[0]
        elif type == _TYPE_BINARY_COMPLEX: return complex(*struct.unpack('=dd', self.file.read(16)))
        elif type == _TYPE_LONG:
            nbits = self.read_int32()
            if not nbits:
                return 0
            n = 0
            for i in range(abs(nbits)):
                digit = self.read_int16()
                n |= digit << (i * 15)
            return n if nbits > 0 else -n

        # Strings
        elif type == _TYPE_STRING: return self.read_string_ascii()
        elif type == _TYPE_UNICODE: return self.read_string_utf8()
        elif type == _TYPE_INTERNED:
            data = self.read_string_ascii()
            self.string_table.append(data)
            return data
        elif type == _TYPE_STRING_REF:
            index = self.read_int32()
            if index < 0 or index >= len(self.string_table):
                raise DisassemblerException('String index %d is outside string table' % index)
            return self.string_table[index]

        # Code objects
        elif type == _TYPE_CODE:
            co = CodeObject()
            co.co_argcount = self.read_int32()
            co.co_kwonlyargcount = self.read_int32() if op.has_kwonlyargcount(self.magic) else 0
            co.co_nlocals = self.read_int32()
            co.co_stacksize = self.read_int32()
            co.co_flags = self.read_int32()
            type = self.read_int8()
            if type != _TYPE_STRING:
                raise DisassemblerException('Bytecode was not marshalled as a string (type was 0x%02X instead of 0x%02X)' % (type, _TYPE_STRING))
            co.co_code = self.read_byte_array()
            co.co_consts = self.unmarshal_node()
            co.co_names = self.unmarshal_node()
            co.co_varnames = self.unmarshal_node()
            co.co_freevars = self.unmarshal_node()
            co.co_cellvars = self.unmarshal_node()
            co.co_filename = self.unmarshal_node()
            co.co_name = self.unmarshal_node()
            co.co_firstlineno = self.read_int32()
            co.co_lnotab = self.unmarshal_node()

            # Start disassembly
            argument = 0
            i = 0
            while i < len(co.co_code):
                offset = i
                opcode = op.from_bytecode(co.co_code[i], self.magic)
                if opcode is None:
                    raise DisassemblerException('Unknown bytecode 0x%02X' % co.co_code[i])
                i += 1

                if op.has_argument(opcode):
                    lo, hi = co.co_code[i:i + 2]
                    argument |= (lo | (hi << 8))
                    i += 2

                # The upper 16 bits of 32-bit arguments are stored in a fake
                # EXTENDED_ARG opcode that precedes the actual opcode
                if opcode == op.EXTENDED_ARG:
                    argument <<= 16
                    continue

                # Decode the opcode argument if present
                arg = None
                if op.has_argument(opcode):
                    if opcode == op.LOAD_CONST:
                        if argument >= len(co.co_consts):
                            raise DisassemblerException('Invalid argument %d for opcode %s' % (argument, opcode))
                        arg = co.co_consts[argument]
                    elif opcode in [op.LOAD_NAME, op.STORE_NAME, op.DELETE_NAME,
                                op.LOAD_ATTR, op.STORE_ATTR, op.DELETE_ATTR,
                                op.LOAD_GLOBAL, op.STORE_GLOBAL, op.DELETE_GLOBAL,
                                op.IMPORT_NAME, op.IMPORT_FROM]:
                        if argument >= len(co.co_names):
                            raise DisassemblerException('Invalid argument %d for opcode %s' % (argument, opcode))
                        arg = co.co_names[argument]
                    elif opcode in [op.LOAD_FAST, op.STORE_FAST, op.DELETE_FAST]:
                        if argument >= len(co.co_varnames):
                            raise DisassemblerException('Invalid argument %d for opcode %s' % (argument, opcode))
                        arg = co.co_varnames[argument]
                    else:
                        arg = argument

                # Record disassembled opcode
                co.opcodes.append(Opcode(offset, i - offset, opcode, arg))
                argument = 0

            return co

        else:
            raise DisassemblerException('Cannot unmarshal unknown type 0x%02X' % type)