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'))
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
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
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