def visit_insn(self, instruction): if instruction.op == idaapi.cit_block: while True: cblock = instruction.cblock size = cblock.size() if size >= 2: # Find block that has "If" and "return" as last 2 statements if cblock.back().op == idaapi.cit_return and \ cblock.at(size - 2).op == idaapi.cit_if and not cblock.at(size - 2).cif.ielse: cit_then = cblock.at(size - 2).cif.ithen # Skip if only one (not "if") statement in "then" branch if cit_then.cblock.size( ) == 1 and cit_then.cblock.front().op != idaapi.cit_if: return 0 # Replacing condition to opposite cit_if_condition = cblock.at(size - 2).cif.expr if cit_if_condition.op == idaapi.cot_lnot: # Ida has following bug: # when return type of call cexpr_t is not signed int, function idaapi.lnot leads to crash new_if_condition = idaapi.cexpr_t( cit_if_condition.x) else: new_if_condition = idaapi.cexpr_t( idaapi.lnot(cit_if_condition)) new_if_condition.thisown = False cblock.at(size - 2).cif.expr = new_if_condition del cit_if_condition # Take return from list of statements and later put it back cit_return = idaapi.cinsn_t(instruction.cblock.back()) cit_return.thisown = False instruction.cblock.pop_back() # Fill main block with statements from "Then" branch while cit_then.cblock: instruction.cblock.push_back( cit_then.cblock.front()) cit_then.cblock.pop_front() # Put back main return if there's no another return or "GOTO" already if instruction.cblock.back().op not in ( idaapi.cit_return, idaapi.cit_goto): new_return = idaapi.cinsn_t(cit_return) new_return.thisown = False instruction.cblock.push_back(new_return) # Put return into "Then" branch cit_then.cblock.push_back(cit_return) continue break return 0
def visit_insn(self, instruction): if instruction.op != idaapi.cit_block: return 0 while True: cblock = instruction.cblock size = cblock.size() # Find block that has "If" and "return" as last 2 statements if size < 2: break if cblock.at(size - 2).op != idaapi.cit_if: break cif = cblock.at(size - 2).cif if cblock.back().op != idaapi.cit_return or cif.ielse: break cit_then = cif.ithen # Skip if only one (not "if") statement in "then" branch if cit_then.cblock.size( ) == 1 and cit_then.cblock.front().op != idaapi.cit_if: return 0 inverse_if_condition(cif) # Take return from list of statements and later put it back cit_return = idaapi.cinsn_t() cit_return.assign(instruction.cblock.back()) cit_return.thisown = False instruction.cblock.pop_back() # Fill main block with statements from "Then" branch while cit_then.cblock: instruction.cblock.push_back(cit_then.cblock.front()) cit_then.cblock.pop_front() # Put back main return if there's no another return or "GOTO" already if instruction.cblock.back().op not in (idaapi.cit_return, idaapi.cit_goto): new_return = idaapi.cinsn_t() new_return.thisown = False new_return.assign(cit_return) instruction.cblock.push_back(new_return) # Put return into "Then" branch cit_then.cblock.push_back(cit_return) return 0
def make_block_insn(instructions, address, label_num=-1): block = None if type(instructions) is idaapi.cblock_t: block = instructions elif type(instructions) is list or type(instructions) is tuple: block = make_cblock(instructions) else: raise TypeError("Trying to make cblock instruicton neither of cblock_t or list|tuple") insn = idaapi.cinsn_t() insn.ea = address insn.op = idaapi.cit_block insn.cblock = block insn.label_num = label_num insn.thisown = False return insn
def make_expr_instr(expr): new_item = idaapi.cinsn_t() new_item.op = idaapi.cit_expr new_item.cexpr = expr new_item.thisown = False return new_item