Beispiel #1
0
    def _fn(instr, dat, addr):
        txt, code, length = instr
        immdata = dat[len(code):]

        info = InstructionInfo()
        info.length = length

        dst, src = txt.split()[1].split(',')

        p_dst_w = set_op(dst, immdata, addr)
        p_dst_r = load_op(dst, immdata, addr)
        p_src_r = load_op(src, immdata, addr)

        fn = None
        if p_dst_r[1] is not None and p_src_r[1] is not None and p_dst_w[1] is not None:
            fn = [lambda il: il.append(p_dst_w[1](il, getattr(il, il_op)(p_dst_r[2], 
                p_dst_r[1](il),
                p_src_r[1](il),
                flags = flags if flags else None
            )))]

        return (
            [tT(op), tS(' '), *p_dst_w[0], tS(', '), *p_src_r[0]],
            info,
            fn
        )
Beispiel #2
0
def dec(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    info = InstructionInfo()
    info.length = length

    dst = txt.split()[1]

    p_dst_w = set_op(dst, immdata, addr)
    p_dst_r = load_op(dst, immdata, addr)

    fn = None
    if p_dst_r[1] is not None and p_dst_w[1] is not None:
        fn = [lambda il: il.append(p_dst_w[1](il, il.sub(p_dst_r[2], 
            p_dst_r[1](il),
            il.const(p_dst_r[2], 1),
            flags="z",
        )))]

    return (
        [tT('DEC'), tS(' '), *p_dst_w[0]],
        info,
        fn
    )
Beispiel #3
0
def ex(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    info = InstructionInfo()
    info.length = length

    dst, src = txt.split()[1].split(',')

    p_dst_w = set_op(dst, immdata, addr)
    p_dst_r = load_op(dst, immdata, addr)
    p_src_w = set_op(src, immdata, addr)
    p_src_r = load_op(src, immdata, addr)

    fn = None
    if p_dst_r[1] is not None and p_src_r[1] is not None and p_dst_w[1] is not None and p_src_w[1] is not None:
        fn = [
            lambda il: il.append(p_dst_w[1](il, p_src_r[1](il))),
            lambda il: il.append(p_src_w[1](il, p_dst_r[1](il)))
        ]

    return (
        [tT('EX'), tS(' '), *p_dst_w[0], tS(', '), *p_src_r[0]],
        info,
        fn
    )
Beispiel #4
0
    def get_instruction_info(self, data, addr):
        (instruction_text, instruction_len) = dis.lazy_disasm(data)
        if instruction_len == 0:
            return None

        result = InstructionInfo()
        result.length = instruction_len

        if len(instruction_text) == 0:
            return result

        if instruction_text[0].lower() == 'b':
            tokens = instruction_text.split()
            token = tokens[1]
            # Unconditional Branch
            if all(char in string.hexdigits for char in token):
                # --HACK: base address offset
                dest = int('0x' + token, 16) - 0x400000
                result.add_branch(BranchType.UnconditionalBranch, dest)
                return result
            # Conditional Branch
            if op.is_conditional_branch(instruction_text):
                tokens = instruction_text.split()
                for token in tokens:
                    csv = token.split(",")
                    check = csv[-1]
                    if all(char in string.hexdigits for char in check):
                        # --HACK: base address offset
                        dest = int('0x' + check, 16) - 0x400000
                        result.add_branch(BranchType.TrueBranch, dest)
                        result.add_branch(BranchType.FalseBranch, addr + instruction_len)
                        return result
        return result
Beispiel #5
0
def rete(instr, dat, addr):
    txt, code, length = instr

    info = InstructionInfo()
    info.length = length
    info.add_branch(BranchType.FunctionReturn)

    return (
        [tT('RETE')],
        info,
        [lambda il: il.append(il.ret(il.pop(2)))]
    )
Beispiel #6
0
    def perform_get_instruction_info(self, data, addr):
        if len(data) < 2:
            print "perform_get_instruction_info(%s, 0x%04x), not enough data!" % (
                tohex(data), addr)
            return None
        if addr % 2 != 0:
            print "perform_get_instruction_info(%s, 0x%04x), address not aligned!" % (
                tohex(data), addr)
            return None
        #print "perform_get_instruction_info(%s, 0x%04x)" % (tohex(data), addr)
        info = InstructionInfo()
        info.length = self.max_instr_length

        # workaround for a Binary Ninja bug, data is not guaranteed to be max_instr_length bytes
        data = data[:self.max_instr_length]

        instruction = unpack('<H', data)[0]
        bincode = instruction >> 8
        if bincode >= 0x80:
            opcode_key = bincode & 0xc0
            is_bit = False
        elif bincode >= 0x40:
            opcode_key = bincode & 0xf8
            is_bit = True
        else:
            opcode_key = bincode
            is_bit = False
        try:
            mask, opspace, jump_action, opcode, caption = opcode_dict[
                opcode_key]
        except KeyError:
            return None  # TODO is it possible to get more information?

        operand = instruction & mask
        branches = {
            NONXT:
            lambda: [(BranchType.FunctionReturn, 0)],
            NEXTI:
            lambda: [],
            BRNCH:
            lambda: [(BranchType.TrueBranch, addr + 4),
                     (BranchType.FalseBranch, addr + 2)],
            JUMPI:
            lambda: [(BranchType.UnconditionalBranch, operand * 2)
                     ],  # ROM addresses are 16 bits of data per address
            CALLI:
            lambda: [(BranchType.CallDestination, operand * 2)
                     ]  # ROM addresses are 16 bits of data per address
        }[jump_action]()

        for type, address in branches:
            info.add_branch(type, address)
        return info
Beispiel #7
0
def mlt(instr, dat, addr):
    txt, code, length = instr

    info = InstructionInfo()
    info.length = length

    return (
        [tT('MLT')],
        info,
        [lambda il: il.append(il.set_reg(2, 'HL', il.mult(2,
            il.zero_extend(2, il.reg(1, 'A')),
            il.zero_extend(2, il.reg(1, 'L')),
        )))]
    )
Beispiel #8
0
    def get_instruction_info(self, data, addr):
        tmp = self.qualifies(data, addr)
        if not tmp:
            return super(X86DeobfuscateHook,
                         self).get_instruction_info(data, addr)

        (push_addr, length) = tmp
        print(
            '%08X: push+ret found, informing binja of unconditional branch to 0x%X'
            % (addr, push_addr))

        result = InstructionInfo()
        result.length = length
        result.add_branch(BranchType.UnconditionalBranch, push_addr)
        return result
Beispiel #9
0
def push(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    op = txt.split()[1]
    p_op = load_op(op, immdata, addr)

    info = InstructionInfo()
    info.length = length

    return (
        [tT('PUSH'), tS(' '), *p_op[0]],
        info,
        [lambda il: il.append(il.push(p_op[2], p_op[1](il)))]
    )
Beispiel #10
0
def decode(dat, addr):
    
    if len(dat) < 1:
        return None

    b0 = dat[0]
    instr = instructions[b0]

    if instr is not None and len(instr) != 3:
        # multi-byte encoding
        if len(dat) < 2:
            return None

        b1 = dat[1]
        instr = instr[b1]

    if instr is None or len(dat) < instr[2]:
        return None

    txt, code, length = instr

    info = InstructionInfo()
    info.length = length

    op = txt.split()[0]

    if op == 'LD': return load(instr, dat, addr)
    elif op == 'JRL': return jrl(instr, dat, addr)
    elif op == 'JRS': return jrs(instr, dat, addr)
    elif op == 'CARL': return carl(instr, dat, addr)
    elif op == 'RET': return ret(instr, dat, addr)
    elif op == 'RETE': return rete(instr, dat, addr)
    elif op == 'PUSH': return push(instr, dat, addr)
    elif op == 'POP': return pop(instr, dat, addr)
    elif op == 'MLT': return mlt(instr, dat, addr)
    elif op == 'ADD': return add(instr, dat, addr)
    elif op == 'SUB': return sub(instr, dat, addr)
    elif op == 'AND': return f_and(instr, dat, addr)
    elif op == 'OR': return f_or(instr, dat, addr)
    elif op == 'XOR': return f_xor(instr, dat, addr)
    elif op == 'INC': return inc(instr, dat, addr)
    elif op == 'DEC': return dec(instr, dat, addr)
    elif op == 'CP': return cp(instr, dat, addr)
    elif op == 'EX': return ex(instr, dat, addr)
    elif op == 'INT': return f_int(instr, dat, addr)
    elif op == 'DJR': return djr(instr, dat, addr)

    return ([tT(txt)], info, None)
Beispiel #11
0
def djr(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    rel = immdata[0]
    if rel & 0x80:
        rel -= 0x100
    
    target = (addr + rel + length - 1) & 0xffff

    info = InstructionInfo()
    info.length = length
    info.add_branch(BranchType.TrueBranch, target)
    info.add_branch(BranchType.FalseBranch, addr + length)

    return (
        [tT('DJR'), tS(' '), tA(hex(target), target)],
        info,
        [
            lambda il: il_branch(
                il,
                il.compare_not_equal(1, il.reg(1, 'B'), il.const(1, 0)),
                il.const_pointer(2, target),
                il.const_pointer(2, addr + length))
        ]
    )
Beispiel #12
0
def carl(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    if txt.split()[1] != '{3}':
        return None

    rel = immdata[0] + (immdata[1] << 8)
    target = (addr + rel + length - 1) & 0xffff

    info = InstructionInfo()
    info.length = length
    info.add_branch(BranchType.CallDestination, target)

    return (
        [tT('CARL'), tS(' '), tA(hex(target), target)],
        info,
        [lambda il: il_jump(il, il.const_pointer(2, target), is_call=True)]
    )
Beispiel #13
0
def f_int(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    op = txt.split()[1]

    if op != '[{0}h]':
        return None

    rel = immdata[0]
    target = rel & 0xff

    info = InstructionInfo()
    info.length = length
    info.add_branch(BranchType.CallDestination, target)

    return (
        [tT('INT'), tS(' '), tA(hex(target), target)],
        info,
        [lambda il: il.append(il.jump(il.const_pointer(2, target)))]
    )
Beispiel #14
0
def pop(instr, dat, addr):
    txt, code, length = instr
    immdata = dat[len(code):]

    op = txt.split()[1]

    info = InstructionInfo()
    info.length = length

    sz = 0
    if op in REGS_1:
        sz = 1
    elif op in REGS_2:
        sz = 2
    else:
        return None

    return (
        [tT('POP'), tS(' '), tR(op)],
        info,
        [lambda il: il.append(il.set_reg(sz, op, il.pop(sz)))]
    )
Beispiel #15
0
 def perform_get_instruction_info(self, data, addr):
     if not len(data):
         return  # edge case during linear sweep
     nfo = InstructionInfo()
     # ana
     size, branch = self.lut.branches[ord(data[0])]
     nfo.length = size
     # emu
     if branch:
         branch_type, target = branch
         if callable(target):
             target = target(data, addr, size) if size <= len(data) else 0
         if branch_type == BranchType.CallDestination:
             # TODO: keep track of return-effect functions, tweak target +=dx
             pass
             # TODO: arch is probably global; need to store this in bv somehow :|
         nfo.add_branch(branch_type, target=target)
         if branch_type == BranchType.TrueBranch:
             nfo.add_branch(BranchType.FalseBranch, addr + size)
     return nfo
    def get_instruction_info(self, data, addr):

        # instruction lookup
        instruction = self.instructions[ord(data[0])]
        if instruction is None:
            return None

        (opcode, length) = instruction[0]

        result = InstructionInfo()
        result.length = length

        # add branches
        if opcode in ['RET', 'RETI', 'RETR']:
            result.add_branch(BranchType.FunctionReturn)
        elif opcode in ['JMP']:
            # TODO: memory bank selection
            result.add_branch(BranchType.UnconditionalBranch, CODE_ADDR((ord(data[0]) & 0xe0) << 3, ord(data[1])))
        elif opcode in ['JMPP']:
            result.add_branch(BranchType.UnresolvedBranch)
        elif opcode == 'DJNZ' or opcode[0] == 'J':
            # conditional branches
            result.add_branch(BranchType.TrueBranch, CODE_ADDR(addr, ord(data[1])))
            result.add_branch(BranchType.FalseBranch, addr + length)
        elif opcode == 'CALL':
            # TODO: memory bank selection
            result.add_branch(BranchType.CallDestination, CODE_ADDR((ord(data[0]) & 0xe0) << 3, ord(data[1])))
        elif opcode == 'SEL':
            # FIXME: fake branches to support bank switching
            if instruction[1][0] == 'RB0':
                result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, 0, self.mb)])
            elif instruction[1][0] == 'RB1':
                result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, 1, self.mb)])
            elif instruction[1][0] == 'MB0':
                result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, self.rb, 0)])
            elif instruction[1][0] == 'MB1':
                result.add_branch(BranchType.UnconditionalBranch, addr + length, Architecture['{}_rb{}mb{}'.format(self.device, self.rb, 1)])

        return result
Beispiel #17
0
    def get_instruction_info(self, data, addr):
        global active_vtil_file
        result = InstructionInfo()
        result.length = 1

        next_vip, _, _, _, code = find_instruction(addr, active_vtil_file)

        if code != None and code.startswith("js"):
            _, _, true, false = code.split(" ")
            true = find_block_address(int(true, 16), active_vtil_file)
            false = find_block_address(int(false, 16), active_vtil_file)
            result.add_branch(BranchType.TrueBranch, true)
            result.add_branch(BranchType.FalseBranch, false)
        elif code != None and code.startswith("vxcall"):
            addr = find_block_address(next_vip[0], active_vtil_file)
            result.add_branch(BranchType.UnconditionalBranch, addr)
        elif code != None and code.startswith("jmp"):
            if len(next_vip) == 1:
                addr = find_block_address(next_vip[0], active_vtil_file)
                result.add_branch(BranchType.UnconditionalBranch, addr)
            else:
                result.add_branch(BranchType.IndirectBranch)
                for vip in next_vip:
                    result.add_branch(BranchType.UnconditionalBranch, find_block_address(vip, active_vtil_file))
        elif code != None and code.startswith("vexit"):
            result.add_branch(BranchType.FunctionReturn)

        return result
Beispiel #18
0
	def get_instruction_info(self, data, addr):
		(instrTxt, instrLen) = skwrapper.disasm(data, addr)
		if instrLen == 0:
			return None
		result = InstructionInfo()
		result.length = instrLen

		rccs = r'(?:C|NC|Z|NZ|M|P|PE|PO)'
		regexes = [ \
			r'^(?:JP|JR) '+rccs+r',\$(.*)$',	# 0: conditional jump			eg: JP PE,#DEAD
			r'^(?:JP|JR) \$(.*)$',				# 1: unconditional jump		eg: JP #DEAD
			r'^(?:JP|JR) \((?:HL|IX|IY)\)$',	# 2: unconditional indirect	eg: JP (IX)
			r'^DJNZ \$(.*)$',					# 3: dec, jump if not zero		eg: DJNZ #DEAD
			r'^CALL '+rccs+r',\$(.*)$',			# 4: conditional call			eg: CALL PE,#DEAD
			r'^CALL \$(.*)$',					# 5: unconditional call		eg: CALL #DEAD
			r'^RET '+rccs+'$',					# 6: conditional return
			r'^(?:RET|RETN|RETI)$',				# 7: return, return (nmi), return (interrupt)
		]

		m = None
		for (i,regex) in enumerate(regexes):
			m = re.match(regex, instrTxt)
			if not m:
				continue

			if i==0 or i==3:
				dest = int(m.group(1), 16)
				result.add_branch(BranchType.TrueBranch, dest)
				result.add_branch(BranchType.FalseBranch, addr + instrLen)
				pass
			elif i==1:
				dest = int(m.group(1), 16)
				result.add_branch(BranchType.UnconditionalBranch, dest)
				pass
			elif i==2:
				result.add_branch(BranchType.IndirectBranch)
				pass
			elif i==4 or i==5:
				dest = int(m.group(1), 16)
				result.add_branch(BranchType.CallDestination, dest)
				pass
			elif i==6:
				pass # conditional returns don't end block
			elif i==7:
				result.add_branch(BranchType.FunctionReturn)

			break

		return result 
Beispiel #19
0
 def get_instruction_info(self, data, addr):
     """ Establishes instruction length and branch info """
     if len(data) > 2:
         data = data[:2]
     result = InstructionInfo()
     result.length = 2
     vars = self.dis._vars(data)
     baddr = vars['addr']
     binfo = self.dis.get_branch_info(data)
     if binfo == BranchType.UnconditionalBranch or binfo == BranchType.CallDestination:
         result.add_branch(binfo, baddr)
     elif binfo == BranchType.FunctionReturn or binfo == BranchType.IndirectBranch:
         result.add_branch(binfo)
     elif binfo == BranchType.TrueBranch:
         result.add_branch(BranchType.TrueBranch, addr + 4)
         result.add_branch(BranchType.FalseBranch, addr + 2)
     elif binfo == BranchType.FalseBranch:
         result.add_branch(BranchType.TrueBranch, addr + 4)
         result.add_branch(BranchType.FalseBranch, addr + 2)
     return result
Beispiel #20
0
    def get_instruction_info(self, data, addr):
        if len(data) < 2 or len(data) > 3: return None
        obj = decode(data, addr)
        if obj.name == "UNKNOWN": return None
        result = InstructionInfo()
        result.length = obj.len

        if obj.name in ["RET", "RET.N"]:
            # RETURN
            result.add_branch(BranchType.FunctionReturn)

        if obj.name in [
                "BALL", "BNALL", "BANY", "BNONE", "BBC", "BBCI", "BBS", "BBSI",
                "BEQ", "BEQI", "BEQZ", "BNE", "BNEI", "BNEZ", "BGE", "BGEI",
                "BGEU", "BGEUI", "BGEZ", "BLT", "BLTI", "BLTU", "BLTUI", "BLTZ"
        ]:
            # CONDITIONAL BRANCH
            for l in obj.prop["format"]:
                if l[0] == "TYPE_LABEL":
                    result.add_branch(BranchType.TrueBranch, l[1])
            result.add_branch(BranchType.FalseBranch, addr + obj.len)

        if obj.name in ["J"]:
            # UNCONDITIONAL JUMP
            for l in obj.prop["format"]:
                if l[0] == "TYPE_LABEL":
                    result.add_branch(BranchType.UnconditionalBranch, l[1])

        if obj.name in ["CALL0", "CALL4", "CALL8", "CALL12"]:
            # DIRECT CALL
            for l in obj.prop["format"]:
                if l[0] == "TYPE_LABEL":
                    result.add_branch(BranchType.CallDestination, l[1])

        if obj.name in ["JX"]:
            # UNCONDITIONAL JUMP TO REGISTER
            result.add_branch(BranchType.IndirectBranch)

        #if obj.name in ["CALLX0", "CALLX4", "CALLX8", "CALLX12"]:
        # CALL TO REGISTER
        #    result.add_branch(BranchType.IndirectBranch)

        return result
Beispiel #21
0
    def get_instruction_info(self, data, addr):
        (instruction_text, instruction_len) = dis.lazy_disasm(addr)
        if instruction_len == 0:
            return None

        result = InstructionInfo()
        result.length = instruction_len

        if len(instruction_text) == 0:
            return result

        tokens = instruction_text.split()
        arch = tokens[0]
        instruction = tokens[1].lower()
        raw_offset = tokens[-1]

        if 'ret' in instruction:
            result.add_branch(BranchType.FunctionReturn)
            return result

        if op.instruction_is_call(instruction):
            call_offset = addr + int(raw_offset, 16)
            result.add_branch(BranchType.CallDestination, call_offset)
            return result

        if not op.instruction_is_branch(instruction):
            return result

        if arch == "MIPS":
            # b	0x10184
            # bgtz	$zero, -0x6c90
            # bgez	$zero, 0x14ca0
            # bne	$v0, $s2, 0x12508
            # bnez	$t8, 0x14d94
            # bltzall	$v0, 0x13cd8
            # bltzal	$t3, -0x7018
            # bltz	$t0, 0x1371c
            # bltz	$zero, -0x69e0
            # bltz	$at, 0x1502c
            if op.is_conditional_branch(instruction_text):
                branch_offset = addr + int(raw_offset, 16)
                result.add_branch(BranchType.TrueBranch, branch_offset)
                result.add_branch(BranchType.FalseBranch,
                                  addr + instruction_len)
            else:  # UNCONDITIONAL BRANCH
                branch_offset = int(raw_offset, 16)
                result.add_branch(BranchType.UnconditionalBranch,
                                  branch_offset)
        elif arch == "ARM":
            # bicsvs	r8, sl, #0x8000000
            # bicsls	r2, r0, r0, lsl r0
            # bicsls	r2, r0, r0, lsl r0
            # bicsls	r2, r0, r0, lsl r0
            # blgt	#0x814c9c
            # bge	#0xfffd0b78
            # bhi	#0x200b08
            # bhi	#0x419078
            # bvs	#0x11e10
            # bvs	#0x1225c
            is_overflow_set = 'bvs' in instruction_text
            if op.is_conditional_branch(instruction_text) or is_overflow_set:
                branch_offset = int(raw_offset.replace("#", ""),
                                    16) - BASE_ADDR
                result.add_branch(BranchType.TrueBranch, branch_offset)
                result.add_branch(BranchType.FalseBranch,
                                  addr + instruction_len)
        elif arch == "RISCV":
            # blez	s8, 0x20
            # bge	t0, a2, 0x24
            # bge	sp, t2, 0x164
            # bge	t2, sp, 0x15c
            # bge	t0, sp, 0x1c
            # bge	t2, s0, 0x34
            # bge	s1, t0, 0x1c
            # j	-0x24
            # j	-0x130
            # j	-0x140
            # j	-0x1b4
            # j	-0x260
            # j	0x1bc
            # j	0x4a8
            # j	0x15c
            # j	0x4a8
            # bne	t1, t0, 0x110
            # bne	t1, t0, 0x100
            # bne	t1, t0, 0xf4
            # bne	t1, t0, 0x48c
            # bnez	sp, 0x40
            # beqz	sp, 0x148
            # beqz	sp, 0x140
            # beqz	t0, 0x20
            # beqz	sp, -0xbc
            # beq	tp, t0, 0x78
            # beq	tp, t0, 8
            if op.is_conditional_branch(instruction_text):
                branch_offset = addr + int(raw_offset, 16)
                result.add_branch(BranchType.TrueBranch, branch_offset)
                result.add_branch(BranchType.FalseBranch,
                                  addr + instruction_len)
            else:  # UNCONDITIONAL JUMP
                branch_offset = addr + int(raw_offset, 16)
                result.add_branch(BranchType.UnconditionalBranch,
                                  branch_offset)
        elif arch == "SPARC":
            # brz,pn	%o3, 0x15240
            # bn	%icc, -0x46210
            # bg,a	-0x6927dc
            # bn,a	-0x3cf180
            # bn,a	-0x6af488
            # bn,pn	%icc, 0x38e98
            # bn,pn	%xcc, 0x90fd0
            # fbne	-0x69bc14
            # fbn	%fcc0, -0x46b2c
            # fbn	-0x36edec
            # fbn	0x3b969c
            # fbn	0x26d94
            # fbn	0x7722f0
            # fblg,pn	%fcc3, 0x390f4
            is_branch = 'bn' in instruction_text
            if is_branch:
                branch_offset = int(raw_offset, 16) + addr
                result.add_branch(BranchType.UnconditionalBranch,
                                  branch_offset)

        return result
Beispiel #22
0
    def get_instruction_info(self, data: bytes, addr: FileOffset) -> InstructionInfo:

        if not self.inialized_df:
            self.load_dex()
        ii = InstructionInfo()

        # Handle pseudoinstructions
        if data[0] == 0 and data[1] != 0:
            if data[1] > 3:
                ii.length = 2
                return ii
            ii.length = min(
                self.max_instr_length, self.df.pseudoinstructions[addr]._total_size
            )
            ii.add_branch(BranchType.FunctionReturn)
            return ii

        # Handle normal instructions
        insn_info = self.insns[data[0]]
        ii.length = insn_info.fmt.insn_len * 2

        if insn_info.mnemonic.startswith("return"):
            ii.add_branch(BranchType.FunctionReturn)
        elif insn_info.mnemonic == "throw":
            ii.add_branch(BranchType.ExceptionBranch)
            # TODO
        elif insn_info.mnemonic.startswith("goto"):
            data_to_parse = endian_swap_shorts(data[: 2 * insn_info.fmt.insn_len])
            args = parse_with_format(data_to_parse, insn_info.fmt.format_)
            offset = sign(args["A"], insn_info.fmt.format_.count("A"))
            ii.add_branch(BranchType.UnconditionalBranch, target=addr + offset * 2)
        elif (
            insn_info.mnemonic == "packed-switch"
            or insn_info.mnemonic == "sparse-switch"
        ):
            data_to_parse = endian_swap_shorts(data[: 2 * insn_info.fmt.insn_len])
            args = parse_with_format(data_to_parse, insn_info.fmt.format_)
            offset = sign(args["B"], insn_info.fmt.format_.count("B"))
            ii.add_branch(BranchType.UnresolvedBranch)
            # Adding more than 2 branches causes binja to segfault, so this has
            # to be handled in LLIL instead.
        elif insn_info.mnemonic == "fill-array-data":
            data_to_parse = endian_swap_shorts(data[: 2 * insn_info.fmt.insn_len])
            args = parse_with_format(data_to_parse, insn_info.fmt.format_)
            offset = sign(args["B"], insn_info.fmt.format_.count("B"))
            ii.add_branch(BranchType.TrueBranch, target=addr + offset * 2)
            ii.add_branch(
                BranchType.FalseBranch, target=addr + insn_info.fmt.insn_len * 2
            )
        elif insn_info.mnemonic.startswith("if-"):
            data_to_parse = endian_swap_shorts(data[: 2 * insn_info.fmt.insn_len])
            args = parse_with_format(data_to_parse, insn_info.fmt.format_)
            var = "C" if "C" in args else "B"
            offset = sign(args[var], insn_info.fmt.format_.count(var))
            ii.add_branch(BranchType.TrueBranch, target=addr + offset * 2)
            ii.add_branch(
                BranchType.FalseBranch, target=addr + insn_info.fmt.insn_len * 2
            )
        elif insn_info.mnemonic.startswith("invoke-"):
            if insn_info.mnemonic.startswith("invoke-custom"):
                log_warn("Resolution of invoke-custom is not implemented")
                ii.add_branch(BranchType.UnresolvedBranch)
            else:
                data_to_parse = endian_swap_shorts(data[: 2 * insn_info.fmt.insn_len])
                args = parse_with_format(data_to_parse, insn_info.fmt.format_)
                meth = self.df.method_ids[args["B"]]
                if meth._insns_off is not None:
                    ii.add_branch(BranchType.CallDestination, target=meth._insns_off)
        return ii
Beispiel #23
0
    def get_instruction_info(self, data, addr):
        result = InstructionInfo()
        result.length = 1

        if self.vtil == None:
            try:
                self.vtil = VTILParser.from_file(get_filename())
            except Exception as ex:
                log_error(str(ex))
                return result

        next_vip, _, _, _, code = find_instruction(addr, self.vtil)

        if code != None and code.startswith("js"):
            _, _, true, false = code.split(" ")
            true = find_block_address(int(true, 16), self.vtil)
            false = find_block_address(int(false, 16), self.vtil)
            result.add_branch(BranchType.TrueBranch, true)
            result.add_branch(BranchType.FalseBranch, false)
        elif code != None and code.startswith("vxcall"):
            addr = find_block_address(next_vip[0], self.vtil)
            result.add_branch(BranchType.UnconditionalBranch, addr)
        elif code != None and code.startswith("jmp"):
            if len(next_vip) == 1:
                addr = find_block_address(next_vip[0], self.vtil)
                result.add_branch(BranchType.UnconditionalBranch, addr)
            else:
                result.add_branch(BranchType.IndirectBranch)
                for vip in next_vip:
                    result.add_branch(BranchType.UnconditionalBranch,
                                      find_block_address(vip, self.vtil))
        elif code != None and code.startswith("vexit"):
            result.add_branch(BranchType.FunctionReturn)

        return result
Beispiel #24
0
 def perform_get_instruction_info(self, data, addr):
     instr, length, operands, flags, value = self.decode_instruction(
         data, addr)
     if instr is None:
         return None
     result = InstructionInfo()
     result.length = length
     opcode = data[0]
     if instr == 'JR':
         arg = data[1]
         dest = arg if arg < 128 else (256 - arg) * (-1)
         if opcode == 0x28 or opcode == 0x38:
             result.add_branch(BranchType.TrueBranch, addr + 2 + dest)
             result.add_branch(BranchType.FalseBranch, addr + 2)
         elif opcode == 0x20 or opcode == 0x30:
             result.add_branch(BranchType.TrueBranch, addr + 2)
             result.add_branch(BranchType.FalseBranch, addr + 2 + dest)
         else:
             result.add_branch(BranchType.UnconditionalBranch,
                               addr + 2 + dest)
     elif instr == 'JP':
         if opcode == 0xe9:
             result.add_branch(BranchType.UnconditionalBranch, 0xdead)
         else:
             arg = struct.unpack('<H', data[1:3])[0]
             if opcode == 0xca or opcode == 0xda:
                 result.add_branch(BranchType.TrueBranch, arg)
                 result.add_branch(BranchType.FalseBranch, addr + 3)
             elif opcode == 0xc2 or opcode == 0xd2:
                 result.add_branch(BranchType.TrueBranch, addr + 3)
                 result.add_branch(BranchType.FalseBranch, arg)
             else:
                 result.add_branch(BranchType.UnconditionalBranch, arg)
     elif instr == 'RET':
         result.add_branch(BranchType.FunctionReturn)
     elif instr == 'CALL':
         result.add_branch(BranchType.CallDestination,
                           struct.unpack("<H", data[1:3])[0])
     return result
Beispiel #25
0
    def get_instruction_info(self, data, addr):
        decoded = decode(data, addr)

        # on error, return nothing
        if decoded.status == DECODE_STATUS.ERROR or decoded.len == 0:
            return None

        # on non-branching, return length
        result = InstructionInfo()
        result.length = decoded.len
        if decoded.typ != INSTRTYPE.JUMP_CALL_RETURN:
            return result

        # jp has several variations
        if decoded.op == OP.JP:
            (oper_type, oper_val) = decoded.operands[0]

            # jp pe,0xDEAD
            if oper_type == OPER_TYPE.COND:
                assert decoded.operands[1][0] == OPER_TYPE.ADDR
                result.add_branch(BranchType.TrueBranch,
                                  decoded.operands[1][1])
                result.add_branch(BranchType.FalseBranch, addr + decoded.len)
            # jp (hl); jp (ix); jp (iy)
            elif oper_type in [
                    OPER_TYPE.REG_DEREF, OPER_TYPE.MEM_DISPL_IX,
                    OPER_TYPE.MEM_DISPL_IY
            ]:
                result.add_branch(BranchType.IndirectBranch)
            # jp 0xDEAD
            elif oper_type == OPER_TYPE.ADDR:
                result.add_branch(BranchType.UnconditionalBranch, oper_val)
            else:
                raise Exception('handling JP')

        # jr can be conditional
        elif decoded.op == OP.JR:
            (oper_type, oper_val) = decoded.operands[0]

            # jr c,0xdf07
            if oper_type == OPER_TYPE.COND:
                assert decoded.operands[1][0] == OPER_TYPE.ADDR
                result.add_branch(BranchType.TrueBranch,
                                  decoded.operands[1][1])
                result.add_branch(BranchType.FalseBranch, addr + decoded.len)
            # jr 0xdf07
            elif oper_type == OPER_TYPE.ADDR:
                result.add_branch(BranchType.UnconditionalBranch, oper_val)
            else:
                raise Exception('handling JR')

        # djnz is implicitly conditional
        elif decoded.op == OP.DJNZ:
            (oper_type, oper_val) = decoded.operands[0]
            assert oper_type == OPER_TYPE.ADDR
            result.add_branch(BranchType.TrueBranch, oper_val)
            result.add_branch(BranchType.FalseBranch, addr + decoded.len)

        # call can be conditional
        elif decoded.op == OP.CALL:
            (oper_type, oper_val) = decoded.operands[0]
            # call c,0xdf07
            if oper_type == OPER_TYPE.COND:
                assert decoded.operands[1][0] == OPER_TYPE.ADDR
                result.add_branch(BranchType.CallDestination,
                                  decoded.operands[1][1])
            # call 0xdf07
            elif oper_type == OPER_TYPE.ADDR:
                result.add_branch(BranchType.CallDestination, oper_val)
            else:
                raise Exception('handling CALL')

        # ret can be conditional
        elif decoded.op == OP.RET:
            if decoded.operands and decoded.operands[0][0] == OPER_TYPE.COND:
                # conditional returns dont' end block
                pass
            else:
                result.add_branch(BranchType.FunctionReturn)

        # ret from interrupts
        elif decoded.op == OP.RETI or decoded.op == OP.RETN:
            result.add_branch(BranchType.FunctionReturn)

        return result
Beispiel #26
0
	def get_instruction_info(self, data, addr):
		inst,args = self._get_asm(data, addr)
		if inst == "ill":
			return None
		res = InstructionInfo()
		res.length = self._inst_length(inst)

		if inst in ("jx"):
			if args[0] in self.regs:
				res.add_branch(BranchType.IndirectBranch)
			else:
				res.add_branch(BranchType.UnconditionalBranch, int(args[0], 16))
		elif inst in ("callx0", "callx4", "callx8", "callx12"):
			res.add_branch(BranchType.CallDestination)
		elif inst in ("ret", "retw", "ret.n", "retw.n"):
			res.add_branch(BranchType.FunctionReturn)
		elif inst == "j":
			res.add_branch(BranchType.UnconditionalBranch, int(args[0], 16))
		elif inst in ("call0", "call4", "call8", "call12"):
			res.add_branch(BranchType.CallDestination, int(args[0], 16))
		elif inst in ("loopgtz", "loopnez"):
			res.add_branch(BranchType.FalseBranch, int(args[1], 16))
			res.add_branch(BranchType.TrueBranch, addr + res.length)
		elif inst in self._branch_instrs or (inst.endswith(".n") and inst[:-2] in self._branch_instrs):
			res.add_branch(BranchType.TrueBranch, int(args[-1], 16))
			res.add_branch(BranchType.FalseBranch, addr + res.length)
		return res
Beispiel #27
0
	def perform_get_instruction_info(self, data, addr):
		instr, operand, length, value = self.decode_instruction(data, addr)
		if instr is None:
			return None

		result = InstructionInfo()
		result.length = length
		if instr == "jmp":
			if operand == ADDR:
				result.add_branch(BranchType.UnconditionalBranch, struct.unpack("<H", data[1:3])[0])
			else:
				result.add_branch(BranchType.UnresolvedBranch)
		elif instr == "jsr":
			result.add_branch(BranchType.CallDestination, struct.unpack("<H", data[1:3])[0])
		elif instr in ["rti", "rts"]:
			result.add_branch(BranchType.FunctionReturn)
		if instr in ["bcc", "bcs", "beq", "bmi", "bne", "bpl", "bvc", "bvs"]:
			dest = (addr + 2 + struct.unpack("b", data[1])[0]) & 0xffff
			result.add_branch(BranchType.TrueBranch, dest)
			result.add_branch(BranchType.FalseBranch, addr + 2)
		return result