Example #1
0
    def generate(self):
        idaapi.visit_patched_bytes(0, idaapi.BADADDR, self.get_patch_byte)
        if len(self.patched_bytes) == 0:
            msg = 'Cannot generate patch because there is no patch applied.'
            print('genpatch: %s' % msg)
            ida_kernwin.warning(msg)
            return False

        template_path = ''
        for path in sys.path:
            if 'plugins' in path:
                template_path = os.path.join(path, 'patch_template.txt')

        patch_path = idc.get_input_file_path() + '_patch.py'

        template_data = None
        with open(template_path, "r") as f:
            template_data = f.readlines()

        lines = 13
        with open(patch_path, "w") as f:
            for data in self.patched_bytes:
                template_data.insert(lines,
                                     "# address: 0x%x\n" % data['begin_addr'])
                lines += 1
                template_data.insert(lines,
                                     "# function name: %s\n" % data['name'])
                lines += 1
                template_data.insert(
                    lines,
                    "# comment: %s\n" % data['comment'].replace('\n', ' '))
                lines += 1
                template_data.insert(
                    lines, "matches = re.findall('%s', target_data)\n" %
                    data['original'])
                lines += 1
                template_data.insert(lines, "if len(matches) == 1:\n")
                lines += 1
                template_data.insert(
                    lines,
                    "    target_data = target_data.replace('%s', '%s')\n" %
                    (data['original'], data['patched']))
                lines += 1
                template_data.insert(lines, "else:\n")
                lines += 1
                template_data.insert(
                    lines, '    print("Patch pattern isn\'t unique")\n')
                lines += 1
                template_data.insert(lines, "    sys.exit()\n")
                lines += 1

            f.writelines(template_data)

        msg = 'Successfully generated patch to %s from Patched Bytes' % patch_path
        print('genpatch: %s' % msg)
        ida_kernwin.info(msg)
        return True
Example #2
0
def get_patched_bytes(start=None, end=None):
    start, end = fix_addresses(start, end)

    patched_bytes = dict()

    def collector(ea, fpos, original, patched):
        patched_bytes[ea] = PatchedByte(ea, fpos, original, patched)
        return 0

    idaapi.visit_patched_bytes(start, end, collector)

    return patched_bytes
Example #3
0
    def get_patched_bytes(self, start=None, end=None):
        if start is None:
            start = idaapi.cvar.inf.minEA
        if end is None:
            end = idaapi.cvar.inf.maxEA

        patched_bytes = dict()

        def collector(ea, fpos, original, patched):
            patched_bytes[ea] = PatchData(ea, fpos, original, patched)
            return 0

        idaapi.visit_patched_bytes(start, end, collector)
        return patched_bytes
Example #4
0
def formbook_patch_encrypted_bytecode():
    text_segm = ida_segment.get_segm_by_name('.text')
    if not text_segm:
        return idaapi.BADADDR

    seg_start = text_segm.startEA
    seg_end = text_segm.endEA
    fb_decrypt = FormBookDecryption()
    rc4_key = "faddefad156c45629c95d5f429363b0653ad5c1d".decode('hex')  # same as rc4_final from formbook_decrypt_hashes_and_strings()

    for i in [(0x40, 0x48), (0x41, 0x49), (0x42, 0x4a), (0x43, 0x4b), (0x44, 0x4c)]:
        egg_pattern = ''.join('{:02x} '.format(x) for x in [i[0], 0x90, 0x90, 0x90, i[1]])
        encrypted_start = idaapi.find_binary(seg_start, seg_end, egg_pattern, 16, idaapi.SEARCH_DOWN)
        if encrypted_start != idaapi.BADADDR:
            encrypted_end = idaapi.find_binary(encrypted_start + 5, seg_end, "90 90 90 90", 16, idaapi.SEARCH_DOWN)
            if encrypted_end != idaapi.BADADDR:
                encrypted_start += 5
                patch_length = encrypted_end - encrypted_start
                if idaapi.visit_patched_bytes(encrypted_start, encrypted_end, callback_on_patched_bytes) == 0:
                    encrypted_buff = idaapi.get_bytes(encrypted_start, patch_length)
                    decrypted_buff = fb_decrypt.decrypt_func2(encrypted_buff, rc4_key)
                    print('Patching encrypted bytecode at 0x{:x} ({:d} bytes)'.format(encrypted_start, patch_length))
                    idaapi.patch_many_bytes(encrypted_start, decrypted_buff)
                else:
                    print('Encrypted bytecode at 0x{:x} ({:d} bytes) is already patched'.format(encrypted_start, patch_length))
Example #5
0
def main():
    print("Visiting all patched bytes:")
    v = patched_bytes_visitor()
    r = idaapi.visit_patched_bytes(0, idaapi.BADADDR, v)
    if r != 0:
        print("visit_patched_bytes() returned %d" % r)
    else:
        print("Patched: %d Skipped: %d" % (v.patch, v.skip))
Example #6
0
    def OnCommand(self, n, cmd_id):

        # Apply patches to a file
        if cmd_id == self.cmd_apply_patches:

            # Set initial start/end EA values
            start_ea = 0x0
            end_ea = idaapi.cvar.inf.maxEA

            # Set initial output file values
            org_file = GetInputFilePath()
            bkp_file = "%s.bak" % org_file

            # Create the form
            f = PatchApplyForm(start_ea, end_ea, org_file, bkp_file)

            # Execute the form
            ok = f.Execute()
            if ok == 1:
                # Get restore checkbox
                self.restore = f.rRestore.checked

                # Get updated ea max/min
                start_ea = f.intStartEA.value
                end_ea = f.intEndEA.value

                # Get updated file path
                new_org_file = f.orgFile.value

                # Backup the file before replacing
                if f.rBackup.checked:
                    bkp_file = f.bkpFile.value
                    shutil.copyfile(org_file, bkp_file)

                # Apply patches
                try:
                    self.patch_file = open(new_org_file, 'rb+')
                except Exception, e:
                    idaapi.warning("Cannot update file '%s'" % new_org_file)
                else:
                    r = idaapi.visit_patched_bytes(start_ea, end_ea,
                                                   self.apply_patch_byte)
                    self.patch_file.close()
                    self.restore = False

                    # Update db input file, so we are working
                    # with a patched version.
                    #if not org_file == new_org_file:
                    #    idaapi.set_root_filename(new_org_file)
                    #    org_file = new_org_file

            # Dispose the form
            f.Free()
Example #7
0
    def OnCommand(self, n, cmd_id):

        # Apply patches to a file
        if cmd_id == self.cmd_apply_patches:

            # Set initial start/end EA values
            start_ea = 0x0
            end_ea = idaapi.cvar.inf.maxEA

            # Set initial output file values
            org_file = GetInputFilePath()
            bkp_file = "%s.bak" % org_file

            # Create the form
            f = PatchApplyForm(start_ea, end_ea, org_file, bkp_file)

            # Execute the form
            ok = f.Execute()
            if ok == 1:
                # Get restore checkbox
                self.restore = f.rRestore.checked

                # Get updated ea max/min
                start_ea = f.intStartEA.value
                end_ea = f.intEndEA.value

                # Get updated file path
                new_org_file = f.orgFile.value

                # Backup the file before replacing
                if f.rBackup.checked:
                    bkp_file = f.bkpFile.value
                    shutil.copyfile(org_file, bkp_file)

                # Apply patches
                try:
                    self.patch_file = open(new_org_file,'rb+')
                except Exception, e:
                    idaapi.warning("Cannot update file '%s'" % new_org_file)
                else:
                    r = idaapi.visit_patched_bytes(start_ea, end_ea, self.apply_patch_byte)
                    self.patch_file.close()
                    self.restore = False

                    # Update db input file, so we are working
                    # with a patched version.
                    #if not org_file == new_org_file:
                    #    idaapi.set_root_filename(new_org_file)
                    #    org_file = new_org_file

            # Dispose the form
            f.Free()
Example #8
0
 def visit_patched_bytes(self):
     """Iterates through patched bytes and stores them in a buffer."""
     try:
         visitor = self.PatchVisitor()
         result = idaapi.visit_patched_bytes(0, idaapi.BADADDR, visitor)
         if result != 0:
             dap_err("visit_patched_bytes() returned unexpected result",
                     "error code ({})".format(result))
             return []
         return visitor.patched_bytes
     except Exception as e:
         dap_err("Exception encountered while visiting patched bytes",
                 str(e))
     except:
         dap_err("Unknown")
Example #9
0
 def _unpatch(self, from_ea, to_ea):
     if self.disalePatchedBytes:
         self.unp_from_ea = from_ea
         idaapi.visit_patched_bytes(from_ea, to_ea, self._bytes_unpatcher)
Example #10
0
 def _unpatch(self, from_ea, to_ea):
     if self.disalePatchedBytes:
         self.unp_from_ea = from_ea
         idaapi.visit_patched_bytes(from_ea, to_ea, self._bytes_unpatcher)
Example #11
0
 def refreshitems(self):
     self.items_data = []
     self.items = []
     idaapi.visit_patched_bytes(0, idaapi.BADADDR, self.get_patch_byte)
Example #12
0
 def refreshitems(self):
     self.items_data = []
     self.items = []
     idaapi.visit_patched_bytes(0, idaapi.BADADDR, self.get_patch_byte)
Example #13
0
    def OnCommand(self, n, cmd_id):

        # Apply patches to a file
        if cmd_id == self.cmd_apply_patches:

            # Set initial start/end EA values
            start_ea = 0x0
            end_ea = idaapi.cvar.inf.maxEA

            # Set initial output file values
            org_file = GetInputFilePath()
            bkp_file = "%s.bak" % org_file

            # Create the form
            f = PatchApplyForm(start_ea, end_ea, org_file, bkp_file)

            # Execute the form
            ok = f.Execute()
            if ok == 1:
                # Get restore checkbox
                self.restore = f.rRestore.checked

                # Get updated ea max/min
                start_ea = f.intStartEA.value
                end_ea = f.intEndEA.value

                # Get updated file path
                new_org_file = f.orgFile.value

                # Backup the file before replacing
                if f.rBackup.checked:
                    bkp_file = f.bkpFile.value
                    shutil.copyfile(org_file, bkp_file)

                # Apply patches
                try:
                    self.patch_file = open(new_org_file,'rb+')
                except Exception as e:
                    idaapi.warning("Cannot update file '%s'" % new_org_file)
                else:
                    r = idaapi.visit_patched_bytes(start_ea, end_ea, self.apply_patch_byte)
                    self.patch_file.close()
                    self.restore = False

                    # Update db input file, so we are working
                    # with a patched version.
                    #if not org_file == new_org_file:
                    #    idaapi.set_root_filename(new_org_file)
                    #    org_file = new_org_file

            # Dispose the form
            f.Free()

        # Restore selected byte(s)
        elif cmd_id == self.cmd_restore_bytes:

            # List start/end
            if n == -2 or n ==-3:
                return 1

            elif not len(self.items) > 0:
                idaapi.warning("There are no patches to restore.")
                return 1

            # Nothing selected
            elif n == -1:
                idaapi.warning("Please select bytes to restore.")
                return 1

            ea = self.items_data[n][0]
            fpos =  self.items_data[n][1]
            buf = self.items_data[n][4]

            addr_str = "%#x" % ea
            fpos_str = "%#x" % fpos if fpos != -1 else "N/A"  
            patch_str = self.items[n][3]
            org_str = self.items[n][4]

            # Create the form
            f = PatchRestoreForm(addr_str, fpos_str, patch_str, org_str)

            # Execute the form
            ok = f.Execute()
            if ok == 1:

                # Restore original bytes
                idaapi.put_many_bytes(ea, struct.pack("B"*len(buf), *buf))

                # Refresh all IDA views
                self.refreshitems()

            # Dispose the form
            f.Free()

        return 1