Пример #1
0
    def single_operand_parser(self, address, op, idx):
        """Parse a PPC operand."""
        def constraint_value(value):
            if value > 2**16:
                return -(2**32 - value)
            return value

        # Operand parsing
        #

        if op.type == OPERAND_TYPE_NO_OPERAND:
            return None

        #print '>>>', hex(address), idx, op.type

        segment = idaapi.getseg(address)
        addressing_mode = segment.bitness

        # Start creating the AST, the root entry is always the width of the
        # operand
        operand = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]

        # Compose the rest of the AST
        #

        if op.type == OPERAND_TYPE_DISPLACEMENT:

            # A displacement operatior might refer to a variable...
            #
            var_name = None

            # Try to get any name that might have been assigned to the
            # variable. It's only done if the register is:
            # sp/esp (4) os bp/ebp (5)
            #
            flags = idc.GetFlags(address)
            if (idx == 0
                    and idc.isStkvar0(flags)) or (idx == 1
                                                  and idc.isStkvar1(flags)):

                var_name = self.get_operand_stack_variable_name(
                    address, op, idx)

            #if has_sib_byte(op) is True:
            # when SIB byte set, process the SIB indexing
            #    phrase = parse_phrase(op)
            #else:
            phrase = [
                self.NODE_TYPE_OPERATOR_PLUS,
                [
                    self.NODE_TYPE_REGISTER,
                    self.REGISTERS[self.as_byte_value(op.reg)], 0
                ]
            ]

            if var_name:
                value = arch.ExpressionNamedValue(long(op.addr), var_name)
            else:
                value = constraint_value(op.addr)

            operand.extend([[
                self.NODE_TYPE_DEREFERENCE,
                phrase + [[self.NODE_TYPE_VALUE, value, 1]]
            ]])

        elif op.type == OPERAND_TYPE_REGISTER:
            operand.extend([[
                self.NODE_TYPE_REGISTER,
                self.REGISTERS[self.as_byte_value(op.reg)], 1
            ]])

        elif op.type == OPERAND_TYPE_MEMORY:

            addr_name = self.get_address_name(op.addr)

            if addr_name:
                value = arch.ExpressionNamedValue(long(op.addr), addr_name)
            else:
                value = op.addr

            operand.extend([[
                self.NODE_TYPE_DEREFERENCE, [self.NODE_TYPE_VALUE, value, 0]
            ]])

        elif op.type == OPERAND_TYPE_IMMEDIATE:

            # Keep the value's size
            #
            if self.as_byte_value(op.dtyp) == 0:
                mask = 0xff
            elif self.as_byte_value(op.dtyp) == 1:
                mask = 0xffff
            else:
                mask = 0xffffffff

            operand.extend([[self.NODE_TYPE_VALUE, op.value & mask, 0]])

        elif op.type in (OPERAND_TYPE_NEAR, OPERAND_TYPE_FAR):

            addr_name = self.get_address_name(op.addr)

            if addr_name:
                value = arch.ExpressionNamedValue(long(op.addr), addr_name)
            else:
                value = op.addr

            operand.extend([[self.NODE_TYPE_VALUE, value, 0]])

        elif op.type == OPERAND_TYPE_PHRASE:
            print '***Dunno how to parse PHRASE'
            operand.extend([[
                self.NODE_TYPE_SYMBOL,
                'UNK_PHRASE(val:%d, reg:%d, type:%d)' %
                (op.value, self.as_byte_value(op.reg), op.type), 0
            ]])

        elif op.type == OPERAND_TYPE_IDPSPEC0:

            # Handle Special Purpose Registers
            #
            register = self.SPR_REGISTERS.get(
                op.value, 'UNKNOWN_REGISTER(val:%x)' % op.value)

            operand.extend([[self.NODE_TYPE_REGISTER, register, 0]])

        elif op.type == OPERAND_TYPE_IDPSPEC1:
            #print '***Dunno how to parse OPERAND_TYPE_IDPSPEC1'
            #operand.extend([[self.NODE_TYPE_SYMBOL,
            #    'UNK_IDPSPEC1(val:%d, reg:%d, type:%d)' % (
            #        op.value, op.reg, op.type), 0]])
            operand.extend([[
                self.NODE_TYPE_REGISTER,
                self.REGISTERS[self.as_byte_value(op.reg)], 1
            ]])
            operand.extend([[
                self.NODE_TYPE_REGISTER,
                self.REGISTERS[self.as_byte_value(op.specflag1)], 2
            ]])

        elif op.type == OPERAND_TYPE_IDPSPEC2:
            # IDSPEC2 is operand type for all rlwinm and rlwnm
            # instructions which are in general op reg, reg, byte, byte, byte
            # or eqivalent. simplified mnemonics sometimes take less than
            # five arguments.
            #
            # Keep the value's size
            #
            if self.as_byte_value(op.dtyp) == 0:
                mask = 0xff
            elif self.as_byte_value(op.dtyp) == 1:
                mask = 0xffff
            else:
                mask = 0xffffffff

            operand_1 = []
            operand_2 = []
            operand_3 = []

            # Get the object representing the instruction's data.
            # It varies between IDA pre-5.7 and 5.7 onwards, the following check
            # will take care of it (for more detail look into the similar
            # construct in arch.py)
            #
            if hasattr(idaapi, 'cmd'):
                idaapi.decode_insn(address)
                ida_instruction = idaapi.cmd
            else:
                idaapi.ua_code(address)
                ida_instruction = idaapi.cvar.cmd

            if (ida_instruction.auxpref & 0x0020):
                #print "SH"
                operand_1 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_1.extend([[
                    self.NODE_TYPE_VALUE,
                    self.as_byte_value(op.reg) & mask, 0
                ]])
            else:
                operand_1 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_1.extend([[
                    self.NODE_TYPE_REGISTER,
                    self.REGISTERS[self.as_byte_value(op.reg)], 0
                ]])
            #print operand_1

            if (ida_instruction.auxpref & 0x0040):
                #print "MB"
                operand_2 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_2.extend([[
                    self.NODE_TYPE_VALUE,
                    self.as_byte_value(op.specflag1) & mask, 0
                ]])
            #print operand_2

            if (ida_instruction.auxpref & 0x0080):
                #print "ME"
                operand_3 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_3.extend([[
                    self.NODE_TYPE_VALUE,
                    self.as_byte_value(op.specflag2) & mask, 0
                ]])
            #print operand_3

            operand = [operand_1]
            #operand = operand_1

            if (ida_instruction.auxpref & 0x0040):
                #print "MB2"
                operand.append(operand_2)
            if (ida_instruction.auxpref & 0x0080):
                #print "ME2"
                operand.append(operand_3)

            #print operand
            # operand = operand_1
            #print operand
            #print '>>>', hex(address), idx, op.type, op.reg
            #operand.extend([[self.NODE_TYPE_OPERATOR_COMMA, [self.NODE_TYPE_VALUE, op.reg&mask, 0], [self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag1)&mask, 1], [self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag2)&mask, 2]]])

        elif op.type == OPERAND_TYPE_IDPSPEC3:
            # CR registers
            #
            operand.extend([[
                self.NODE_TYPE_REGISTER,
                self.CR_REGISTERS[self.as_byte_value(op.reg)], 0
            ]])

        elif op.type == OPERAND_TYPE_IDPSPEC4:
            # The bit in the CR to check for
            #
            operand.extend(
                [[self.NODE_TYPE_REGISTER,
                  self.as_byte_value(op.reg), 0]])

        elif op.type == OPERAND_TYPE_IDPSPEC5:
            # Device Control Register, implementation specific
            operand.extend([[self.NODE_TYPE_REGISTER,
                             'DCR(%x)' % op.value, 0]])

        return operand
    return None
    
print 'Start____'
for ref in CodeRefsTo(ScreenEA(), 0):

    # Get the second argument to the function,
    # if none found, continue with the next call
    #
    arg_addr = find_func_arg(ref, -8)
    if arg_addr is None:
        continue

    # Set IDA's to point to the instruction of interest
    #
    idaapi.ua_code(arg_addr)

    # Check if the instruction uses the SIB byte, meaning
    # that this will be an indexed access (for instance, into
    # a table of strings), we don't want to process those
    # in this way
    #
    op = idaapi.get_instruction_operand(idaapi.cvar.cmd, 0)
    if ord(op.specflag1) == 1:
        continue


    r = DataRefsFrom(arg_addr)
    if r:
        r=r[0]
        print '%x: %s' % (r, unrot(r).replace('\n', r'\n'))
Пример #3
0
    def process_instruction_generic(self, addr):
        """Architecture agnostic instruction parsing."""
        
        # Retrieve the instruction mnemonic
        #
        i_mnemonic = self.get_mnemonic(addr)
        if not i_mnemonic:
            return None, None, None, None, None
            
        # Set the current location to the instruction to disassemble
        #
        #idaapi.jumpto(addr)
        #idaapi.ua_ana0(addr)

        # Up to IDA 5.7 it was called ua_code...
        if hasattr(idaapi, 'ua_code'):
            # Gergely told me of using ua_code() and idaapi.cvar.cmd
            # instead of jumpto() and get_current_instruction(). The latter
            # where always making IDA to reposition the cursor and refresh
            # the GUI, which was quite painful
            #
            idaapi.ua_code(addr)
            # Retrieve the current instruction's structure and
            # set its type
            ida_instruction = idaapi.cvar.cmd
        else:
            # now it's called decode_insn()
            idaapi.decode_insn(addr)
            # Retrieve the current instruction's structure and
            # set its type
            ida_instruction = idaapi.cmd


        instruction = Instruction(
            ida_instruction.itype, ida_instruction.size, ida_instruction.ip)
        self.current_instruction_type = instruction.itype
        
        
        # Try to process as many operands as IDA supports
        #
        # Up to IDA 5.7 it was called ua_code... so we use it to check for 5.7
        if hasattr(idaapi, 'ua_code'):
            operands = self.operands_parser( addr, [(
                idaapi.get_instruction_operand(ida_instruction, idx),
                idx ) for idx in range(6)] )
        else:
            operands = self.operands_parser( addr, [(
                ida_instruction.Operands[idx],
                idx ) for idx in range(6)] )
                
        # Retrieve the operand strings
        #
        operand_strings = [
            idc.GetOpnd(addr, idx) for idx in range(len(operands))]
        
        # Get the instruction data
        #
        data = ''.join(
            [chr(idaapi.get_byte(addr+i)) for i in range(idc.ItemSize(addr))])
        
        # Return the mnemonic and the operand AST
        #
        return instruction, i_mnemonic, operands, operand_strings, data
Пример #4
0
    def single_operand_parser(self, address, op, idx):
        """Parse a PPC operand."""
        
        def constraint_value(value):
            if value>2**16:
                return -(2**32-value)
            return value

        
        # Operand parsing
        #
        
        if op.type == OPERAND_TYPE_NO_OPERAND:
            return None
        
        #print '>>>', hex(address), idx, op.type
        
        segment = idaapi.getseg(address)
        addressing_mode = segment.bitness
        
        # Start creating the AST, the root entry is always the width of the
        # operand
        operand = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
        
        
        # Compose the rest of the AST
        #
        
        if op.type == OPERAND_TYPE_DISPLACEMENT:
            
            # A displacement operatior might refer to a variable...
            #
            var_name = None
            
            # Try to get any name that might have been assigned to the
            # variable. It's only done if the register is:
            # sp/esp (4) os bp/ebp (5)
            #
            flags = idc.GetFlags(address)
            if (idx==0 and idc.isStkvar0(flags)) or (
                idx==1 and idc.isStkvar1(flags)):
                
                var_name = self.get_operand_stack_variable_name(address, op, idx)
            
            #if has_sib_byte(op) is True:
                # when SIB byte set, process the SIB indexing
            #    phrase = parse_phrase(op)
            #else:
            phrase = [
                self.NODE_TYPE_OPERATOR_PLUS,
                    [self.NODE_TYPE_REGISTER,
                        self.REGISTERS[self.as_byte_value(op.reg)], 0]]
            
            if var_name:
                value = arch.ExpressionNamedValue(long(op.addr), var_name)
            else:
                value = constraint_value(op.addr)
            
            operand.extend([
                [self.NODE_TYPE_DEREFERENCE,
                    phrase+[ [self.NODE_TYPE_VALUE, value, 1]] ] ])
        
        elif op.type == OPERAND_TYPE_REGISTER:
            operand.extend([
                [self.NODE_TYPE_REGISTER, self.REGISTERS[self.as_byte_value(op.reg)], 1]])
                
        
        elif op.type == OPERAND_TYPE_MEMORY:
            
            addr_name = self.get_address_name(op.addr)
            
            if addr_name:
                value = arch.ExpressionNamedValue(long(op.addr), addr_name)
            else:
                value = op.addr
            
            operand.extend([
                [self.NODE_TYPE_DEREFERENCE,
                    [self.NODE_TYPE_VALUE, value, 0]] ])
             
        
        elif op.type == OPERAND_TYPE_IMMEDIATE:
            
            # Keep the value's size
            #
            if self.as_byte_value(op.dtyp) == 0:
                mask = 0xff
            elif self.as_byte_value(op.dtyp) == 1:
                mask = 0xffff
            else:
                mask = 0xffffffff
            
            operand.extend([[self.NODE_TYPE_VALUE, op.value&mask, 0]])
            
        
        elif op.type in (OPERAND_TYPE_NEAR, OPERAND_TYPE_FAR):
            
            addr_name = self.get_address_name(op.addr)
            
            if addr_name:
                value = arch.ExpressionNamedValue(long(op.addr), addr_name)
            else:
                value = op.addr
            
            operand.extend([[self.NODE_TYPE_VALUE, value, 0]])
            
        
        elif op.type == OPERAND_TYPE_PHRASE:
            print '***Dunno how to parse PHRASE'
            operand.extend([[self.NODE_TYPE_SYMBOL,
                'UNK_PHRASE(val:%d, reg:%d, type:%d)' % (
                    op.value, self.as_byte_value(op.reg), op.type), 0]])
        
        elif op.type == OPERAND_TYPE_IDPSPEC0:
            
            # Handle Special Purpose Registers
            #
            register = self.SPR_REGISTERS.get(
                op.value, 'UNKNOWN_REGISTER(val:%x)' % op.value)
            
            operand.extend([
                [self.NODE_TYPE_REGISTER, register, 0]])
        
        elif op.type == OPERAND_TYPE_IDPSPEC1:
            #print '***Dunno how to parse OPERAND_TYPE_IDPSPEC1'
            #operand.extend([[self.NODE_TYPE_SYMBOL,
            #    'UNK_IDPSPEC1(val:%d, reg:%d, type:%d)' % (
            #        op.value, op.reg, op.type), 0]])
            operand.extend([
                [self.NODE_TYPE_REGISTER, self.REGISTERS[self.as_byte_value(op.reg)], 1]])
            operand.extend([
                [self.NODE_TYPE_REGISTER, self.REGISTERS[self.as_byte_value(op.specflag1)], 2]])
        
        elif op.type == OPERAND_TYPE_IDPSPEC2:
            # IDSPEC2 is operand type for all rlwinm and rlwnm
            # instructions which are in general op reg, reg, byte, byte, byte
            # or eqivalent. simplified mnemonics sometimes take less than
            # five arguments.
            #
            # Keep the value's size
            #
            if self.as_byte_value(op.dtyp) == 0:
                mask = 0xff
            elif self.as_byte_value(op.dtyp) == 1:
                mask = 0xffff
            else:
                mask = 0xffffffff

            operand_1 = []
            operand_2 = []
            operand_3 = []

            # Get the object representing the instruction's data.
            # It varies between IDA pre-5.7 and 5.7 onwards, the following check
            # will take care of it (for more detail look into the similar 
            # construct in arch.py)
            #
            if hasattr(idaapi, 'cmd' ):
                idaapi.decode_insn(address)
                ida_instruction = idaapi.cmd
            else:
                idaapi.ua_code(address)
                ida_instruction = idaapi.cvar.cmd
            
            if (ida_instruction.auxpref & 0x0020):
                #print "SH"		    
                operand_1 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_1.extend([[self.NODE_TYPE_VALUE, self.as_byte_value(op.reg)&mask, 0]])
            else:
                operand_1 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_1.extend([[self.NODE_TYPE_REGISTER, self.REGISTERS[self.as_byte_value(op.reg)], 0]])
            #print operand_1

            if (ida_instruction.auxpref & 0x0040):
                #print "MB"
                operand_2 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_2.extend([[self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag1)&mask, 0]])
            #print operand_2

            if (ida_instruction.auxpref & 0x0080):
                #print "ME"
                operand_3 = [self.OPERAND_WIDTH[self.as_byte_value(op.dtyp)]]
                operand_3.extend([[self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag2)&mask, 0]])
            #print operand_3

            operand = [operand_1]
            #operand = operand_1

            if (ida_instruction.auxpref & 0x0040): 
                #print "MB2"
                operand.append(operand_2)
            if (ida_instruction.auxpref & 0x0080):
                #print "ME2"
                operand.append(operand_3)	    

            #print operand 
            # operand = operand_1
            #print operand
            #print '>>>', hex(address), idx, op.type, op.reg
            #operand.extend([[self.NODE_TYPE_OPERATOR_COMMA, [self.NODE_TYPE_VALUE, op.reg&mask, 0], [self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag1)&mask, 1], [self.NODE_TYPE_VALUE, self.as_byte_value(op.specflag2)&mask, 2]]])

        elif op.type == OPERAND_TYPE_IDPSPEC3:
            # CR registers
            #
            operand.extend([
                [self.NODE_TYPE_REGISTER, self.CR_REGISTERS[self.as_byte_value(op.reg)], 0]])
        
        elif op.type == OPERAND_TYPE_IDPSPEC4:
            # The bit in the CR to check for
            #
            operand.extend([[self.NODE_TYPE_REGISTER, self.as_byte_value(op.reg), 0]])
            
        
        elif op.type == OPERAND_TYPE_IDPSPEC5:
            # Device Control Register, implementation specific
            operand.extend([[self.NODE_TYPE_REGISTER, 'DCR(%x)' % op.value, 0]])
            
        
        return operand
Пример #5
0
    def process_instruction_generic(self, addr):
        """Architecture agnostic instruction parsing."""

        # Retrieve the instruction mnemonic
        #
        i_mnemonic = self.get_mnemonic(addr)
        if not i_mnemonic:
            return None, None, None, None, None

        # Set the current location to the instruction to disassemble
        #
        #idaapi.jumpto(addr)
        #idaapi.ua_ana0(addr)

        # Up to IDA 5.7 it was called ua_code...
        if hasattr(idaapi, 'ua_code'):
            # Gergely told me of using ua_code() and idaapi.cvar.cmd
            # instead of jumpto() and get_current_instruction(). The latter
            # where always making IDA to reposition the cursor and refresh
            # the GUI, which was quite painful
            #
            idaapi.ua_code(addr)
            # Retrieve the current instruction's structure and
            # set its type
            ida_instruction = idaapi.cvar.cmd
        else:
            # now it's called decode_insn()
            idaapi.decode_insn(addr)
            # Retrieve the current instruction's structure and
            # set its type
            ida_instruction = idaapi.cmd

        instruction = Instruction(ida_instruction.itype, ida_instruction.size,
                                  ida_instruction.ip)
        self.current_instruction_type = instruction.itype

        # Try to process as many operands as IDA supports
        #
        # Up to IDA 5.7 it was called ua_code... so we use it to check for 5.7
        if hasattr(idaapi, 'ua_code'):
            operands = self.operands_parser(
                addr,
                [(idaapi.get_instruction_operand(ida_instruction, idx), idx)
                 for idx in range(6)])
        else:
            operands = self.operands_parser(
                addr,
                [(ida_instruction.Operands[idx], idx) for idx in range(6)])

        # Retrieve the operand strings
        #
        operand_strings = [
            idc.GetOpnd(addr, idx) for idx in range(len(operands))
        ]

        # Get the instruction data
        #
        data = ''.join([
            chr(idaapi.get_byte(addr + i)) for i in range(idc.ItemSize(addr))
        ])

        # Return the mnemonic and the operand AST
        #
        return instruction, i_mnemonic, operands, operand_strings, data