예제 #1
0
    def apply(self):
        """
        Apply patches to found opaque branch
        :return: None
        """

        for src, dst in self._flow_patches_map.items():
            ir_block: IRBlock = self._ir_cfg.get_block(src)

            asm_instr = ir_block.assignblks[ir_block.dst_linenb].instr

            if asm_instr.name not in conditional_branch:
                log(f"Unsupported asm pattern at {hex(src)}", code='!')
                continue

            patch_addr = asm_instr.offset

            opcode1 = ida_bytes.get_byte(patch_addr)

            # Fast and Furious
            if opcode1 == 0x0F:
                ida_bytes.patch_bytes(
                    patch_addr,
                    b"\xe9" + pack("<I",
                                   (dst - (patch_addr + 5)) & (2**32 - 1)))
            elif ((opcode1 & 0xe0) == 0xe0) or ((opcode1 & 0x70) == 0x70):
                ida_bytes.patch_byte(patch_addr, 0xeb)
                ida_bytes.patch_byte(patch_addr + 1,
                                     (dst - (patch_addr + 2)) & 0xFF)
            else:
                log(f"Unknown first part of opcode at {hex(patch_addr)}",
                    code='!')
                continue

            log(f"Apply patch JCC -> JMP at {hex(patch_addr)}")
예제 #2
0
def write_segment(va_start, va_end, segm_name, data):
    ida_segment.add_segm(0, va_start, va_end, segm_name, None, 0xe)
    va = va_start
    for b in data:
        ida_bytes.patch_byte(va, ord(b))
        va += 1
    print("wrote 0x%x bytes to 0x%x [%s]" % (len(data), va_start, segm_name))
예제 #3
0
파일: decode.py 프로젝트: clayne/idapython
def references(function_location, decoding_str):
    """decodes all decoded strings by a given function by applying decoding_str
       to every byte.
       decoding_str should contain encoded_byte, for example:
       decode.references(0x401000, "(encoded_byte ^ 0xA2) + 0x21")"""
    for xref in idautils.XrefsTo(function_location):
        ea = xref.frm
        # The function needs to be defined for get_arg_addrs to work
        args = idaapi.get_arg_addrs(ea)
        encoded = idc.get_operand_value(args[0], 0)
        decoded = idc.get_operand_value(args[1], 0)

        decoded_str = ""
        i = 0
        encoded_byte = ida_bytes.get_wide_byte(encoded)
        while encoded_byte != 0:
            decoded_byte = eval(decoding_str)
            decoded_str += chr(decoded_byte)
            ida_bytes.patch_byte(decoded + i, decoded_byte)
            i += 1
            encoded_byte = ida_bytes.get_wide_byte(encoded + i)

        ida_bytes.create_strlit(decoded, i, STRTYPE_C)
        idc.set_cmt(ea, f"Decoded: {decoded_str}", 0)
        print(f"##At {hex(ea)} decoded: {decoded_str}")
def patch():
    ea = idc.find_binary(0,
                         idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE,
                         PATTERN)

    start_addr = None
    pattern_len = _pattern_len(PATTERN)

    while not (ea == ida_idaapi.BADADDR or idc.get_segm_name(ea) != '.text'):
        # If we don't have start address saved, save it and search for the next pattern match
        if not start_addr:
            start_addr = ea

        # If start address was saved before, we got end address. It's time to patch
        else:
            # Remove marker patterns to prevent re-encryption on the next script run
            fill_with_nops(start_addr, start_addr + pattern_len)
            fill_with_nops(ea, ea + pattern_len)

            # Decrypt the code between markers
            for addr in range(start_addr + pattern_len, ea):
                ida_bytes.patch_byte(addr, ~idc.get_wide_byte(addr))

            print('[0x%08X..0x%08X] Region patched' %
                  (start_addr, ea + pattern_len))

            start_addr = None

        ea = idc.find_binary(
            ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, PATTERN)

    print('[PATCHING FINISHED]')
예제 #5
0
파일: idamem.py 프로젝트: ITAYC0HEN/malduck
 def __setitem__(self, item, value):
     value_bytes = iterbytes_ord(value)
     for ea_start, ea_end in self._get_ea_range(item):
         for ea in range(ea_start, ea_end):
             try:
                 ida_bytes.patch_byte(ea, next(value_bytes))
             except StopIteration:
                 return
예제 #6
0
파일: nop.py 프로젝트: clayne/idapython
def nop():
    """Nops-out the current instruction and advance the cursor to the next instruction."""
    ea = idaapi.get_screen_ea()
    num_bytes = idc.get_item_size(ea)
    for i in range(num_bytes):
        ida_bytes.patch_byte(ea, 0x90)
        ea += 1
    ida_kernwin.refresh_idaview_anyway()
    ida_kernwin.jumpto(ea)
예제 #7
0
def nop_region(ea, size):
    """replace the given range with NOPs"""
    logger.debug("nopping region from 0x%x size 0x%x", ea, size)

    for i in range(ea, ea + size):
        ida_bytes.del_items(i)

    for i in range(ea, ea + size):
        ida_bytes.patch_byte(i, 0x90)

    ida_auto.auto_make_code(ea)
예제 #8
0
def patch_word(ea, value, wordsize=WORD_SIZE):
    """Patch the word at the given address.

    Words are patched using PatchByte(), PatchWord(), PatchDword(), or PatchQword(), as
    appropriate.
    """
    if wordsize == 1:
        ida_bytes.patch_byte(ea, value)
    elif wordsize == 2:
        ida_bytes.patch_word(ea, value)
    elif wordsize == 4:
        ida_bytes.patch_dword(ea, value)
    elif wordsize == 8:
        ida_bytes.patch_qword(ea, value)
    else:
        raise ValueError('Invalid argument: wordsize={}'.format(wordsize))
예제 #9
0
def main():
    print("[*] Start patching to XOR encoded blocks")
    ea = ida_kernwin.ask_addr(BADADDR, "What address is encoded block by xor?")
    xor_key = ida_kernwin.ask_long(0x00, "Waht is key for xor?(0-255)")

    valid_check(ea, xor_key)

    print hex(ea)
    print hex(xor_key)

    while True:
        b = ida_bytes.get_byte(ea)
        if b == 0:
            break
        ida_bytes.patch_byte(ea, b ^ xor_key)
        ea += 1

    print("[*] Finished patching to XOR encoded blocks")
예제 #10
0
    def set_byte(ea, value):
        """
            Static method allowing to set the value of one byte at an address.

            :param ea: The address at which changing the value.
            :param value: The value to set at the address.
            :raise RuntimeError: If it was not possible to change the value.
        """
        if not ida_bytes.patch_byte(ea, value):
            raise RuntimeError("Unable to set value {} at {}".format(ea, value))
예제 #11
0
def resolve_opaque_push_retn():

    PATTERNS = ["68 ?? ?? ?? ?? C3"]

    count_patched = 0

    for pattern in PATTERNS:

        ea = 0

        while ea != BADADDR:
            ea = ida_search.find_binary(
                ea, BADADDR, pattern, 16,
                SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE)
            ''' 
            pattern: 68 ?? ?? ?? ?? C3
            .text:00406922 68 B2 6A 00 10       push    0x10006ab2
            .text:00406927 C3                   retn
            
            patched:
            .text:00406922 E9 B2 6A 00 10       jmp     0x10006ab2
            .text:00406927 90                   nop
            '''

            if ea_in_bounds(ea):
                j_pos = ea
                pos_jmp = idc.get_wide_dword(j_pos + 1)  # absolute address

                offset = pos_jmp - 5 - j_pos

                # Patch the push and retn instructions with NOPs (6 bytes)
                for i in range(0, 6):
                    ida_bytes.patch_byte(j_pos + i, 0x90)

                ida_bytes.patch_byte(j_pos, 0xE9)
                ida_bytes.patch_dword(j_pos + 0x1, offset)

                idc.create_insn(ea)

                count_patched += 1

    print("\tPatched resolve_opaque_push_retn: {0}".format(count_patched))
def resolve_obf_calls(ea):
    next_instr_addr = idc.get_wide_dword(ea + 1)

    first_jmp_target = (ea + idc.get_wide_dword(ea + 0x7) + 0xB) & 0xFFFFFFFF
    second_jmp_target = (ea + idc.get_wide_dword(ea + 0xD) + 0x11) & 0xFFFFFFFF

    if first_jmp_target != second_jmp_target:
        return

    call_param = (first_jmp_target - ea - 5) & 0xFFFFFFFF

    # Now we can replace all code till next instruction's address with NOPs
    fill_with_nops(ea, next_instr_addr)

    # Insert CALL
    ida_bytes.patch_byte(ea, 0xE8)                      # CALL
    ida_bytes.patch_dword(ea + 1, call_param)
    idc.create_insn(ea)

    return True
예제 #13
0
    def bytes(self, value):
        """
            Setter allowing to change the bytes value of the element.

            .. warning::

                No check is made on the size of the array of the setter and
                it can rewrite more than the size of the element,

            :param value: A list of int corresponding to the bytes to change.
        """
        if isinstance(value, bytes):
            ida_bytes.patch_bytes(self.ea, value)
        elif isinstance(value, list):
            i = 0
            for e in value:
                ida_bytes.patch_byte(self.ea + i, e)
                i += 1
        else:
            raise TypeError(
                "Invalid arg {} for BipElt.bytes setter".format(value))
예제 #14
0
    def set_bytes(ea, byt):
        """
            Static method allowing to set the value of one byte at an address.

            :param int ea: The address at which changing the value.
            :param bytes byt: The buffer of bytes to set at the address. If a
                string is provided in python3 it will be decoded as ``latin-1``.
            :raise RuntimeError: If it was not possible to change one of the value.
        """
        if is_py3() and isinstance(byt, str):
            byt = bytearray(byt, 'latin-1')
        else:
            byt = bytearray(byt)
        for i in range(len(byt)):
            value = byt[i]
            if not ida_bytes.patch_byte(ea + i, value):
                raise RuntimeError("Unable to set value {} at {}".format(ea, value))
예제 #15
0
    def value(self, value):
        """
            Property setter which allow to set the value of this object.
            This property works only if the :meth:`~BipData.is_numerable`
            property returned True. If this object has no data
            (:meth:`~BipData.has_data` property return False) or is unknown
            (:meth:`~BipData.is_unknwon` return True) the value set is
            considered to be on 1 byte.

            For setting non numerical value or value on more than 8 bytes use
            the :meth:`~BipElt.bytes` property setter.

            This property is link to the type defined or guessed by IDA and
            it is a good idea to assure you have the proper type before using
            it.

            :param int value: An integer to which set the value of the
                current data element.
            :raise RuntimeError: If the setting of the value failed or if
                the value could not be set because of an unknown type.
        """
        if self.value == value: # case where we are setting at the same value
            return
        if (not self.has_data) or self.is_unknown or self.is_byte:
            if not ida_bytes.patch_byte(self.ea, value):
                raise RuntimeError("Unable to patch value: {}".format(self))
        elif self.is_word:
            if not ida_bytes.patch_word(self.ea, value):
                raise RuntimeError("Unable to patch value: {}".format(self))
        elif self.is_dword:
            if not ida_bytes.patch_dword(self.ea, value):
                raise RuntimeError("Unable to patch value: {}".format(self))
        elif self.is_qword:
            if not ida_bytes.patch_qword(self.ea, value):
                raise RuntimeError("Unable to patch value: {}".format(self))
        else:
            raise RuntimeError("Unable to patch value: {}".format(self))
예제 #16
0
def resolve_opaque_jnz_jz():

    PATTERNS = [
        "0F 84 ?? ?? ?? ?? 0F 85 ?? ?? ?? ??",  # jz + jnz
        "0F 85 ?? ?? ?? ?? 0F 84 ?? ?? ?? ??",  # jnz + jz
        "74 ?? 0F 85 ?? ?? ?? ??",  # jz short + jnz
        "0F 84 ?? ?? ?? ?? 75 ??",  # jz + jnz short
        "75 ?? 0F 84 ?? ?? ?? ??",  # jnz short + jz
        "0F 85 ?? ?? ?? ?? 74 ??",  # jnz + jz short
        "74 ?? 75 ??",  # jz short + jnz short
        "75 ?? 74 ??"  # jnz short + jz short
    ]

    count_patched = 0
    count_not_patched = 0

    for pattern in PATTERNS:

        ea = 0

        while ea != BADADDR:
            ea = ida_search.find_binary(
                ea, BADADDR, pattern, 16,
                SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE)
            ''' 
            pattern: 0F 85 ?? ?? ?? ?? 0F 84 ?? ?? ?? ??
            .text:0040690E 66 21 CF            and     di, cx
            .text:00406911 0F 85 AE F4 FF FF   jnz     loc_405DC5 <- j_1_pos
            .text:00406917 0F 84 A8 F4 FF FF   jz      loc_405DC5 <- j_2_pos
            
            patched:
            .text:0040690E 66 21 CF            and     di, cx
            .text:00406911 E9 A9 F4 FF FF      jmp     loc_405DC5
            .text:00406916 90                  nop
            .text:00406917 90                  nop
            .text:00406918 90                  nop
            .text:00406919 90                  nop
            .text:0040691a 90                  nop
            .text:0040691b 90                  nop
            .text:0040691c 90                  nop
            '''

            if ea_in_bounds(ea):
                # .text:00406911 0F 85 AE F4 FF FF  jnz loc_405DC5 <- j_1_pos
                #                      AE F4 FF FF                 <- j_1_value Relative offset value
                j_1_pos = ea
                j_1_value, j_1_size = get_j_val(j_1_pos)

                j_2_pos = ea + j_1_size
                j_2_value, j_2_size = get_j_val(j_2_pos)

                pos_jmp = j_1_pos + j_1_value + j_1_size

                if j_1_value - j_2_value == j_2_size:

                    # Patch the jz and jnz instructions with NOPs
                    for i in range(0, j_1_size + j_2_size):
                        ida_bytes.patch_byte(j_1_pos + i, 0x90)

                    if j_1_size == 2:  # jz short or jnz short
                        # Patch with a relative short jmp (size = 2) in the position of the first conditional jmp
                        addr_to_jmp = j_1_value
                        ida_bytes.patch_byte(j_1_pos, 0xEB)
                        ida_bytes.patch_byte(j_1_pos + 0x1, addr_to_jmp)
                    else:  # jz or jnz
                        # Patch with a relative jmp (size = 5) in the position of the first conditional jmp
                        addr_to_jmp = j_1_value + 1
                        ida_bytes.patch_byte(j_1_pos, 0xE9)
                        ida_bytes.patch_dword(j_1_pos + 0x1, addr_to_jmp)

                    idc.create_insn(ea)

                    count_patched += 1

                else:

                    count_not_patched += 1

    print("\tPatched resolve_opaque_jnz_jz: {0}".format(count_patched))
    print("\tNot Patched resolve_opaque_jnz_jz: {0}".format(count_not_patched))
예제 #17
0
def MemCopy( dest, src, length ) :
    for i in xrange(0, length):
        #if (i < 20):
        #	print "set byte at %#x to %#x" % (dest+i, idc.Byte(src+i))
        ida_bytes.patch_byte(dest+i,ida_bytes.get_byte(src+i))
예제 #18
0
def patch_bytes(ea, buf):
    for i, b in enumerate(buf):
        ida_bytes.patch_byte(ea + i, b)
예제 #19
0
def range_xor(start_addr, end_addr, xor_num):
    for the_addr in range(start_addr, end_addr + 1):
        the_byte = get_byte(the_addr)
        patch_byte(the_addr, the_byte ^ xor_num)
예제 #20
0
def patch_encrypted_buffer(encrypted_buffer_address, decrypted_buffer):
	if (encrypted_buffer_address not in patched_addresses):
		for index in range(0, len(decrypted_buffer)):
			ida_bytes.patch_byte(encrypted_buffer_address + index, decrypted_buffer[index])
		MakeStr(encrypted_buffer_address, encrypted_buffer_address + len(decrypted_buffer))
		patched_addresses.append(encrypted_buffer_address)
예제 #21
0
 def __call__(self):
     ida_bytes.patch_byte(self.ea, self.value)
def fill_with_nops(start, stop):
    for p in range(start, stop):
        ida_bytes.patch_byte(p, 0x90)
        idc.create_insn(p)

    idc.create_insn(stop)
예제 #23
0
 def revert_patch(self):
     for b in self.bytes:
         ida_bytes.patch_byte(b.ea, b.original)
예제 #24
0
 def apply_patch(self):
     for b in self.bytes:
         ida_bytes.patch_byte(b.ea, b.patched)
예제 #25
0
def resolve_fs30():

    PATTERNS = ["64 ?? 30 00 00 00", "64 ?? ?? 30 00 00 00"]

    count_patched = 0
    count_not_patched = 0

    for pattern in PATTERNS:

        ea = 0

        while ea != BADADDR:
            '''
             pattern: 64 ?? 30 00 00 00
            .text:00407644 64 A1 30 00 00 00                       mov     eax, large fs:30h
            .text:0040764A 50                                      push    eax
            .text:0040764B 80 ED AD                                sub     ch, 0ADh
            .text:0040764E B5 32                                   mov     ch, 32h
            .text:00407650 66 21 D7                                and     di, dx
            .text:00407653 5A                                      pop     edx
            .text:00407654 8A 72 02                                mov     dh, [edx+2]
            .text:00407657 84 F6                                   test    dh, dh
            .text:00407659 74 11                                   jz      short loc_40766C

             pattern: 64 ?? ?? 30 00 00 00
            .text:00406E42 64 8B 15 30 00 00 00                    mov     edx, large fs:30h
            .text:00406E49 52                                      push    edx
            .text:00406E4A 66 35 3D 1B                             xor     ax, 1B3Dh
            .text:00406E4E 20 CD                                   and     ch, cl
            .text:00406E50 28 D1                                   sub     cl, dl
            .text:00406E52 59                                      pop     ecx
            .text:00406E53 8A 51 02                                mov     dl, [ecx+2]
            .text:00406E56 84 D2                                   test    dl, dl
            .text:00406E58 74 11                                   jz      short loc_406E6B

            patched:
            .text:00406E42 64 8B 15 30 00 00 00                    mov     edx, large fs:30h
            .text:00406E49 52                                      push    edx
            .text:00406E4A 66 35 3D 1B                             xor     ax, 1B3Dh
            .text:00406E4E 20 CD                                   and     ch, cl
            .text:00406E50 28 D1                                   sub     cl, dl
            .text:00406E52 59                                      pop     ecx
            .text:00406E53 8A 51 02                                mov     dl, [ecx+2]
            .text:00406E56 84 D2                                   test    dl, dl
            .text:00406E58 EB 11                                   jmp     short loc_406E6B <-----

            '''

            ea = ida_search.find_binary(
                ea, BADADDR, pattern, 16,
                SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE)

            if ea_in_bounds(ea):

                instr = ida_ua.decode_insn(ea)

                if instr:

                    # while not jmp related instruction found
                    while ((instr.itype <= idaapi.NN_ja)
                           or (instr.itype >= idaapi.NN_jmpshort)):

                        # move to next instr
                        ea = ea + instr.size
                        instr = ida_ua.decode_insn(ea)

                    # ea contains conditional jmp instruction
                    # Patch with relative unconditional jmp
                    ida_bytes.patch_byte(ea, 0xEB)
                    idc.create_insn(ea)

                    count_patched += 1

                else:

                    count_not_patched += 1

    print("\tPatched resolve_fs30: {0}".format(count_patched))
    print("\tNot Patched resolve_fs30: {0}".format(count_not_patched))
예제 #26
0
def resolve_loops():

    PATTERNS = ["81 FB ?? ?? ?? ?? 75"]

    count_patched = 0
    count_not_patched = 0

    for pattern in PATTERNS:

        ea = 0

        while ea != BADADDR:
            '''
             pattern: 81 FB ?? ?? ?? ?? 75
            .text:00406AA0 01 C7                add     edi, eax
            .text:00406AA2 66 41                inc     cx
            .text:00406AA4 43                   inc     ebx
            .text:00406AA5 81 FB A6 01 00 00    cmp     ebx, 1A6h
            .text:00406AAB 75 F3                jnz     short loc_406AA0

            patched:
            .text:00406AA0 01 C7                add     edi, eax
            .text:00406AA2 66 41                inc     cx
            .text:00406AA4 43                   inc     ebx
            .text:00406AA5 90                   nop
            .text:00406AA6 90                   nop
            .text:00406AA7 90                   nop
            .text:00406AA8 90                   nop
            .text:00406AA9 90                   nop
            .text:00406AAA 90                   nop
            .text:00406AAB 90                   nop
            .text:00406AAC 90                   nop
            '''

            ea = ida_search.find_binary(
                ea, BADADDR, pattern, 16,
                SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE)

            if ea_in_bounds(ea):

                # Patch CMP and conditional jmp instructions in order to remove the loop
                ida_bytes.patch_byte(ea + 0, 0x90)
                ida_bytes.patch_byte(ea + 1, 0x90)
                ida_bytes.patch_byte(ea + 2, 0x90)
                ida_bytes.patch_byte(ea + 3, 0x90)
                ida_bytes.patch_byte(ea + 4, 0x90)
                ida_bytes.patch_byte(ea + 5, 0x90)
                ida_bytes.patch_byte(ea + 6, 0x90)
                ida_bytes.patch_byte(ea + 7, 0x90)

                idc.create_insn(ea)

                count_patched += 1

    print("\tPatched resolve_loops: {0}".format(count_patched))
    print("\tNot Patched resolve_loops: {0}".format(count_not_patched))
예제 #27
0
def resolve_opaque_mov_push():

    PATTERNS = [
        "BB 00 00 00 00", "BB 01 00 00 00", "BB 02 00 00 00", "BB 03 00 00 00",
        "BB 04 00 00 00", "BB 05 00 00 00", "BB 06 00 00 00", "BB 07 00 00 00",
        "BB 08 00 00 00", "BB 09 00 00 00", "6A ?? 5B"
    ]

    count_patched = 0
    count_not_patched = 0

    for pattern in PATTERNS:

        ea = 0

        print(pattern)

        while ea != BADADDR:

            ea = ida_search.find_binary(
                ea, BADADDR, pattern, 16,
                SEARCH_NEXT | SEARCH_DOWN | SEARCH_CASE)
            ''' pattern: BB 00 00 00 00
            .text:00406A83 BB 00 00 00 00     mov     ebx, 0
            .text:00406A88 66 01 D0           add     ax, dx
            .text:00406A8B 81 F1 B5 15 00 00  xor     ecx, 15B5h
            .text:00406A91 66 35 7A 13        xor     ax, 137Ah
            .text:00406A95 85 DB              test    ebx, ebx
            .text:00406A97 74 14              jz      short loc_406AAD

            Patched EBX > 0
            pattern: BB 09 00 00 00
            .text:00406BE3 BB 09 00 00 00     mov     ebx, 9
            .text:00406BE8 20 D1              and     cl, dl
            .text:00406BEA 66 09 D6           or      si, dx
            .text:00406BED 66 89 D6           mov     si, dx
            .text:00406BF0 85 DB              test    ebx, ebx
            .text:00406BF2 74 02              jz      short loc_406BF6

            Patched EBX == 0
            .text:00406A83 90                 nop
            .text:00406A84 90                 nop
            .text:00406A85 90                 nop
            .text:00406A86 90                 nop
            .text:00406A87 90                 nop
            .text:00406A88 90                 nop
            .text:00406A89 90                 nop
            .text:00406A8A 90                 nop
            .text:00406A8B 90                 nop
            .text:00406A8C 90                 nop
            .text:00406A8D 90                 nop
            .text:00406A8E 90                 nop
            .text:00406A8F 90                 nop
            .text:00406A90 90                 nop
            .text:00406A91 90                 nop
            .text:00406A92 90                 nop
            .text:00406A93 90                 nop
            .text:00406A94 90                 nop
            .text:00406A95 90                 nop
            .text:00406A96 90                 nop
            .text:00406A97 EB 14              jmp     short loc_406AAD

            '''

            if ea_in_bounds(ea):
                '''
                .text:00406A83 BB 00 00 00 00     mov     ebx, <0-9> <- ebx_value
                .text:00406A88 66 01 D0           add     ax, dx
                .text:00406A8B 81 F1 B5 15 00 00  xor     ecx, 15B5h
                .text:00406A91 66 35 7A 13        xor     ax, 137Ah
                .text:00406A95 85 DB              test    ebx, ebx
                .text:00406A97 74 14              jz      short loc_406AAD
                '''

                original_ea = ea

                ebx_value = Byte(ea + 1)

                instr = ida_ua.decode_insn(ea)

                if instr:

                    has_test = False

                    # while not jmp related instruction found
                    while ((instr.itype <= idaapi.NN_ja)
                           or (instr.itype >= idaapi.NN_jmpshort)):

                        # move to next instr
                        ea = ea + instr.size
                        instr = ida_ua.decode_insn(ea)

                        # Check in order to validate that has test func and is candidate to be patched
                        if instr.itype == idaapi.NN_test:

                            has_test = True

                    # at this point "ea" variable contains the last instruction address
                    # that is the conditional jump found
                    if has_test:

                        if instr.itype == idaapi.NN_jz:

                            # ebx_value > 0 and NN_jz -> Patch with NOPs
                            if ebx_value > 0:
                                '''
                                .text:00406BE3 BB 09 00 00 00     mov     ebx, 9
                                .text:00406BE8 20 D1              and     cl, dl
                                .text:00406BEA 66 09 D6           or      si, dx
                                .text:00406BED 66 89 D6           mov     si, dx
                                .text:00406BF0 85 DB              test    ebx, ebx
                                .text:00406BF2 74 02              jz      short loc_406BF6
                                '''

                                relative_offset = ea - original_ea

                                # Patch the complete function
                                number_nops = ea - original_ea + instr.size

                                for i in range(0, number_nops):

                                    ida_bytes.patch_byte(original_ea + i, 0x90)

                                idc.create_insn(ea)

                            # ebx_value = 0 and NN_jz -> Patch with JMP
                            else:
                                '''
                                .text:00406A83 BB 00 00 00 00     mov     ebx, 0
                                .text:00406A88 66 01 D0           add     ax, dx
                                .text:00406A8B 81 F1 B5 15 00 00  xor     ecx, 15B5h
                                .text:00406A91 66 35 7A 13        xor     ax, 137Ah
                                .text:00406A95 85 DB              test    ebx, ebx
                                .text:00406A97 74 14              jz      short loc_406AAD
                                '''

                                # ea contains the conditional jmp address
                                relative_offset = Byte(ea + 1)

                                # NOP
                                number_nops = ea - original_ea + instr.size

                                for i in range(0, number_nops):

                                    ida_bytes.patch_byte(original_ea + i, 0x90)

                                # Patch the conditional jmp to unconditional jmp
                                ida_bytes.patch_byte(ea, 0xEB)
                                ida_bytes.patch_byte(ea + 1, relative_offset)

                                idc.create_insn(ea)

                            count_patched += 1

                    else:

                        count_not_patched += 1

    print("\tPatched resolve_opaque_mov_push: {0}".format(count_patched))
    print(
        "\tNot Patched resolve_opaque_mov_push: {0}".format(count_not_patched))