Exemple #1
0
 def print_disassembly(address: int, inst: CsInsn):
     '''Print a line of disassembly honoring all the various debugging
     settings.'''
     grp = ""
     addr = ""
     rel = ""
     fancy = None
     if DebugOpts.PRINT_GROUPS:
         grp = f"; Groups: {list(map(inst.group_name, inst.groups))}"
         grp = f"{grp:30}"
     if DebugOpts.PRINT_ADDRESSES:
         addr = f"{hex(address):>18}  "
     if DebugOpts.PRINT_RIP:
         for operand in inst.operands:
             disp = OperandTests.is_rip_relative(operand)
             if disp is not None:
                 rel += f"{hex(disp + inst.size + address)} "
         if len(rel) > 0:
             rel = f"; RIP-Refs: {rel:12}"
     if DebugOpts.FANCY_OPERANDS:
         # This is overkill, of course.  It just lets me mess with
         # the operands in case I want to do something special, and
         # (I hope) demonstrates how you can pull apart the operands
         # to an instruction.
         fancy = []
         for operand in inst.operands:
             if operand.type == X86_OP_IMM:
                 fancy.append(f"{hex(operand.value.imm)}")
             elif operand.type == X86_OP_REG:
                 fancy.append(f"{inst.reg_name(operand.value.reg)}")
             elif operand.type == X86_OP_MEM:
                 segment = inst.reg_name(operand.value.mem.segment)
                 base = inst.reg_name(operand.value.mem.base)
                 index = inst.reg_name(operand.value.mem.index)
                 scale = str(operand.value.mem.scale)
                 disp = operand.value.mem.disp
                 value = f"[{base}"
                 if index is not None:
                     value += f" + {index}*{scale}"
                 if disp is not None:
                     if disp > 0:
                         value += f" + {hex(disp)}"
                     elif disp < 0:
                         value += f" - {hex(abs(disp))}"
                 if segment is not None:
                     value = f"{segment}:" + value
                 value += "]"
                 fancy.append(value)
             else:
                 fancy.append("???")
         line = f"{inst.mnemonic:10} {', '.join(fancy)}"
     else:
         line = f"{inst.mnemonic:5} {inst.op_str:30}"
     print(f"  {addr}{line:40}{grp}{rel}")
Exemple #2
0
    def _operand_uses_vector_registers(cls, instruction: CsInsn,
                                       operand: Arm64Op) -> bool:
        if operand.type == ARM64_OP_IMM:
            return False

        if operand.type == ARM64_OP_REG:
            reg_name = instruction.reg_name(operand.value.reg)
        elif operand.type == ARM64_OP_MEM:
            reg_name = instruction.reg_name(operand.mem.base)
        else:
            raise RuntimeError(
                f"unknown operand type {operand.type} in instr at {instruction.address}"
            )
        return ObjcInstruction.is_vector_register(reg_name)
Exemple #3
0
def format_instruction_arg(instruction: CsInsn, arg: Arm64Op) -> str:
    if arg.type == ARM64_OP_REG:
        return StringPalette.REG(instruction.reg_name(arg.value.reg))
    elif arg.type == ARM64_OP_IMM:
        return StringPalette.IMM(hex(arg.value.imm))
    elif arg.type == ARM64_OP_MEM:
        return f"[{StringPalette.REG(instruction.reg_name(arg.mem.base))} #{StringPalette.IMM(hex(arg.mem.disp))}]"
    raise RuntimeError(f"unknown arg type {arg.type}")
Exemple #4
0
def annotate_instruction(function_analyzer: ObjcFunctionAnalyzer,
                         sel_args: List[str], instr: CsInsn) -> str:
    annotation = "\t\t"
    # Parse as an ObjcInstruction
    wrapped_instr = ObjcInstruction.parse_instruction(
        function_analyzer,
        function_analyzer.get_instruction_at_address(instr.address))

    if isinstance(wrapped_instr, ObjcBranchInstruction):
        wrapped_branch_instr: ObjcBranchInstruction = wrapped_instr

        annotation += "#\t"
        if function_analyzer.is_local_branch(wrapped_branch_instr):
            annotation += StringPalette.ANNOTATION(
                f"jump loc_{hex(wrapped_branch_instr.destination_address)}")

        elif wrapped_instr.symbol:
            annotation += StringPalette.ANNOTATION(wrapped_instr.symbol)

            if not wrapped_branch_instr.selector:
                annotation += StringPalette.ANNOTATION("();")
            else:
                annotation += StringPalette.ANNOTATION_ARGS(
                    f"(id, @selector({wrapped_branch_instr.selector.name})")

                # Figure out argument count passed to selector
                arg_count = wrapped_branch_instr.selector.name.count(":")
                for i in range(arg_count):
                    # x0 is self, x1 is the SEL, real args start at x2
                    register = f"x{i + 2}"
                    method_arg = function_analyzer.get_register_contents_at_instruction(
                        register, wrapped_branch_instr)

                    method_arg_string = ", "
                    if method_arg.type == RegisterContentsType.IMMEDIATE:
                        method_arg_string += hex(method_arg.value)
                    else:
                        method_arg_string += "<?>"

                    annotation += StringPalette.STRING(method_arg_string)
                annotation += ");"

        else:
            annotation += StringPalette.ANNOTATION(f"({hex(instr.address)})(")
            arg_count = 4
            for i in range(arg_count):
                # x0 is self, x1 is the SEL, real args start at x2
                register = f"x{i}"
                method_arg = function_analyzer.get_register_contents_at_instruction(
                    register, wrapped_instr)

                method_arg_string = f"{register}: "
                if method_arg.type == RegisterContentsType.IMMEDIATE:
                    method_arg_string += hex(method_arg.value)
                else:
                    method_arg_string += "<?>"

                annotation += StringPalette.ANNOTATION_ARGS(method_arg_string)
                annotation += ", "
            annotation += ");"
    else:
        # Try to annotate string loads
        # This code taken from Ethan's potential passwords check
        if instr.mnemonic in ["ldr", "adr", "adrp", "add"]:
            # Only care about general purpose registers that are being written into
            if not ObjcInstruction.instruction_uses_vector_registers(instr):
                _, instr_mutated_regs = instr.regs_access()
                if len(instr_mutated_regs):
                    # Get the contents of the register (an address)
                    register = instr.reg_name(instr_mutated_regs[0])
                    wrapped_instr = ObjcInstruction.parse_instruction(
                        function_analyzer, instr)
                    register_contents = function_analyzer.get_register_contents_at_instruction(
                        register, wrapped_instr)
                    if register_contents.type == RegisterContentsType.IMMEDIATE:
                        # Try reading a string
                        binary_str = function_analyzer.binary.read_string_at_address(
                            VirtualMemoryPointer(register_contents.value))
                        if binary_str:
                            annotation += StringPalette.STRING(
                                f'#\t"{binary_str}"')

    return annotation
Exemple #5
0
 def is_interrupt(insn: CsInsn) -> bool:
     '''Determine if an instruction is an interrupt.'''
     return insn.group(X86_GRP_INT)
Exemple #6
0
 def is_privileged(insn: CsInsn) -> bool:
     '''Determine if an instruciton is privileged.'''
     return insn.group(X86_GRP_PRIVILEGE)
Exemple #7
0
 def is_interrupt_return(insn: CsInsn) -> bool:
     '''Determine if an instruction is a return from interrupt.'''
     return insn.group(X86_GRP_IRET)
Exemple #8
0
 def is_branch(insn: CsInsn) -> bool:
     '''Determine if an instruction is a conditional branch.'''
     return insn.group(X86_GRP_BRANCH_RELATIVE)
Exemple #9
0
 def is_ret(insn: CsInsn) -> bool:
     '''Determine if an instruction is a return.'''
     return insn.group(X86_GRP_RET)
Exemple #10
0
 def is_call(insn: CsInsn) -> bool:
     '''Determine if an instruction is a call.'''
     return insn.group(X86_GRP_CALL)
Exemple #11
0
 def is_jump(insn: CsInsn) -> bool:
     '''Determine if an instruction is an unconditional jump.'''
     return insn.group(X86_GRP_JUMP)