archive: add 5 repo prompt(s) [skip ci]

This commit is contained in:
github-actions[bot]
2026-02-24 13:41:12 +00:00
parent e470794804
commit 5d484e8852
7 changed files with 46781 additions and 0 deletions
+786
View File
@@ -0,0 +1,786 @@
Project Path: arc_Krietz7_IDA-DataExportPlus_cznb5gwg
Source Tree:
```txt
arc_Krietz7_IDA-DataExportPlus_cznb5gwg
├── DataExportPlus.py
├── LICENSE
├── README.md
└── README.zh_CN.md
```
`DataExportPlus.py`:
```py
from os import getcwd, path
from struct import unpack
import idc
import idaapi
import ida_ida
from ida_kernwin import add_hotkey
from ida_bytes import get_flags
VERSION = "1.5.3"
# Notice: Since the selected value of IDA's self.DropdownListControl gets the index of the incoming List object,
# the constant definition of key values also needs to follow the 0-index
# Define constants for data base
DATA_BASE_HEX_KEY = 0
DATA_BASE_DEC_KEY = 1
DATA_BASE_OCT_KEY = 2
DATA_BASE_BIN_KEY = 3
# Define constants for data types
DATA_TYPE_BYTE_KEY = 0
DATA_TYPE_WORD_KEY = 1
DATA_TYPE_DWORD_KEY = 2
DATA_TYPE_QWORD_KEY = 3
DATA_TYPE_FLOAT_KEY = 4
DATA_TYPE_DOUBLE_KEY = 5
DATA_TYPE_STRING_LITERAL_KEY = 6
DATA_TYPE_ASSEMBLY_CODE_KEY = 7
DATA_TYPE_RAW_BYTES_KEY = 8
# Define constants for export formats
EXPORT_FORMAT_STRING_KEY = 0
EXPORT_FORMAT_C_VARIABLE_KEY = 1
EXPORT_FORMAT_PYTHON_VARIABLE_KEY = 2
class DEP_Conversion:
BASE_VALUES = {
DATA_BASE_HEX_KEY: 16,
DATA_BASE_DEC_KEY: 10,
DATA_BASE_OCT_KEY: 8,
DATA_BASE_BIN_KEY: 2,
}
C_TYPE_MAP = {
DATA_TYPE_BYTE_KEY: "char",
DATA_TYPE_WORD_KEY: "short",
DATA_TYPE_DWORD_KEY: "int",
DATA_TYPE_QWORD_KEY: "long long int",
DATA_TYPE_FLOAT_KEY: "float",
DATA_TYPE_DOUBLE_KEY: "double"
}
@staticmethod
def get_list():
Data_base_list = {
"Hexadecimal": DATA_BASE_HEX_KEY,
"Decimal": DATA_BASE_DEC_KEY,
"Octal": DATA_BASE_OCT_KEY,
"Binary": DATA_BASE_BIN_KEY,
}
Data_type_list = {
"Byte": DATA_TYPE_BYTE_KEY,
"Word": DATA_TYPE_WORD_KEY,
"Dword": DATA_TYPE_DWORD_KEY,
"Qword": DATA_TYPE_QWORD_KEY,
"Float": DATA_TYPE_FLOAT_KEY,
"Double": DATA_TYPE_DOUBLE_KEY,
"String literal": DATA_TYPE_STRING_LITERAL_KEY,
"Assembly Code": DATA_TYPE_ASSEMBLY_CODE_KEY,
"Raw bytes": DATA_TYPE_RAW_BYTES_KEY,
}
Data_exported_format_list = {
"String": EXPORT_FORMAT_STRING_KEY,
"C variable": EXPORT_FORMAT_C_VARIABLE_KEY,
"Python variable": EXPORT_FORMAT_PYTHON_VARIABLE_KEY,
}
return (Data_base_list, Data_type_list, Data_exported_format_list)
def __init__(self, address, data_bytes, data_type_key=DATA_TYPE_BYTE_KEY,
export_as_type_key=EXPORT_FORMAT_STRING_KEY, big_endian=False,
base_key=DATA_BASE_HEX_KEY, signed=False, pad_zero=False,
delimiter=" ", prefix="", suffix="", keep_comments=True,
keep_names=True):
self.address = address
self.Data_base_list, self.Data_type_list, _ = self.get_list()
self.data_bytes = data_bytes
self.export_as_type_key = export_as_type_key
self.big_endian = big_endian
self.signed = signed
self.pad_zero = pad_zero
self.base_key = base_key
self.data_type_key = data_type_key
self.delimiter = delimiter
self.prefix = prefix
self.suffix = suffix
self.keep_comments = keep_comments
self.keep_names = keep_names
def activate(self):
self.base = self.BASE_VALUES[self.base_key]
if self.data_type_key == DATA_TYPE_RAW_BYTES_KEY:
return "Cannot preview binary data"
output = self._get_conversion_output()
if output is None:
return None
if self.export_as_type_key == EXPORT_FORMAT_STRING_KEY:
return output
if self.export_as_type_key == EXPORT_FORMAT_C_VARIABLE_KEY:
return self._format_c_variable(output)
if self.export_as_type_key == EXPORT_FORMAT_PYTHON_VARIABLE_KEY:
return self._format_python_variable(output)
return None
def _get_conversion_output(self):
if self.data_type_key in [DATA_TYPE_BYTE_KEY, DATA_TYPE_WORD_KEY,
DATA_TYPE_DWORD_KEY, DATA_TYPE_QWORD_KEY]:
return self._number_conversion()
elif self.data_type_key in [DATA_TYPE_FLOAT_KEY, DATA_TYPE_DOUBLE_KEY]:
return self._float_conversion()
elif self.data_type_key == DATA_TYPE_STRING_LITERAL_KEY:
return self._string_literal_conversion()
elif self.data_type_key == DATA_TYPE_ASSEMBLY_CODE_KEY:
return self.assembly_code_conversion()
return None
def _format_c_variable(self, output):
var_name = f"IDA_{hex(self.address)[2:]}"
if self.data_type_key in self.C_TYPE_MAP:
c_type = self.C_TYPE_MAP[self.data_type_key]
if not self.signed:
c_type = f"unsigned {c_type}"
if self.data_type_key in [DATA_TYPE_FLOAT_KEY, DATA_TYPE_DOUBLE_KEY]:
output = output.replace("nan", "NAN")
return f"{c_type} {var_name}[] = {{{output}}};"
elif self.data_type_key == DATA_TYPE_STRING_LITERAL_KEY:
c_string = self._strliteral_to_c_string(self.data_bytes)
return f'unsigned char {var_name}[] = "{c_string}";'
elif self.data_type_key == DATA_TYPE_ASSEMBLY_CODE_KEY:
escaped_lines = '\\n"\n"'.join(line for line in output.splitlines())[:-1]
return f'const char* {var_name} = "{escaped_lines}";'
return None
def _format_python_variable(self, output):
var_name = f"IDA_{hex(self.address)[2:]}"
if self.data_type_key in [DATA_TYPE_BYTE_KEY, DATA_TYPE_WORD_KEY,
DATA_TYPE_DWORD_KEY, DATA_TYPE_QWORD_KEY]:
return f"{var_name} = [{output}]"
elif self.data_type_key in [DATA_TYPE_FLOAT_KEY, DATA_TYPE_DOUBLE_KEY]:
output = output.replace("nan", "float('nan')")
return f"{var_name} = [{output}]"
elif self.data_type_key == DATA_TYPE_STRING_LITERAL_KEY:
py_literal = self._bytes_to_py_literal(self.data_bytes)
return f"{var_name} = {py_literal}"
elif self.data_type_key == DATA_TYPE_ASSEMBLY_CODE_KEY:
return f"{var_name} = '''{output}'''"
return None
def _strliteral_to_c_string(self, data_bytes):
result = []
is_escape = False
for byte in data_bytes:
if byte == ord('\\'):
result.append("\\\\")
is_escape = False
elif byte == ord('"'):
result.append("\\\"")
is_escape = False
elif byte == ord('\n'):
result.append("\\n")
is_escape = False
elif byte == ord('\r'):
result.append("\\r")
is_escape = False
elif byte == ord('\t'):
result.append("\\t")
is_escape = False
elif 32 <= byte <= 126:
c = chr(byte)
# To avoid confusion with the previous \xHH, force escape if the current character is a hex letter
if c in '0123456789abcdefABCDEF' and is_escape:
result.append('""')
is_escape = False
result.append(c)
else:
result.append(f'\\x{byte:02X}')
is_escape = True
return ''.join(result)
def _bytes_to_py_literal(self, data_bytes):
return repr(data_bytes)
# base on Byte/Word/Dword/Qword convert byte stream to number
# parameter: base big_endian sign prefix suffix delimiter
def _number_conversion(self):
type_len_list = {DATA_TYPE_BYTE_KEY:1, DATA_TYPE_WORD_KEY:2,
DATA_TYPE_DWORD_KEY:4, DATA_TYPE_QWORD_KEY:8}
Number_len = type_len_list[self.data_type_key]
number_bytes_array = []
for i in range(0, len(self.data_bytes), Number_len):
chunk = self.data_bytes[i:i+Number_len]
if len(chunk) < Number_len:
chunk += b'\x00' * (Number_len - len(chunk))
number = int.from_bytes(chunk, byteorder='little' if not self.big_endian else 'big', signed=self.signed)
number_bytes_array.append(number)
def format_number(n):
base = self.base
prefix = self.prefix or ''
suffix = self.suffix or ''
is_negative = n < 0
num_abs = abs(n)
pad_width = 0
if self.pad_zero:
if base == 2:
pad_width = Number_len * 8
elif base == 8:
pad_width = Number_len * 3
elif base == 16:
pad_width = Number_len * 2
if base == 10:
s = str(num_abs)
elif base == 2:
s = bin(num_abs)[2:]
if pad_width:
s = s.zfill(pad_width)
elif base == 8:
s = oct(num_abs)[2:]
if pad_width:
s = s.zfill(pad_width)
elif base == 16:
s = hex(num_abs)[2:]
if pad_width:
s = s.zfill(pad_width)
result = prefix + s if not is_negative else '-' + prefix + s
return result + suffix
if self.base > 0 and self.base < 37:
return self.delimiter.join(format_number(i) for i in number_bytes_array)
return None
def _float_conversion(self):
type_len_list = {DATA_TYPE_FLOAT_KEY:4, DATA_TYPE_DOUBLE_KEY:8}
Number_len = type_len_list[self.data_type_key]
number_bytes_array = []
for i in range(0, len(self.data_bytes), Number_len):
chunk = self.data_bytes[i:i + Number_len]
if len(chunk) == Number_len:
number_bytes_array.append(chunk)
format_char = '<f' if self.data_type_key == DATA_TYPE_FLOAT_KEY else '<d'
if self.big_endian:
format_char = '>' + format_char[1]
float_values = []
for chunk in number_bytes_array:
value = unpack(format_char, chunk)[0]
float_values.append(value)
return self.delimiter.join(f"{self.prefix}{i}{self.suffix}" for i in float_values)
def _string_literal_conversion(self):
return str(self.data_bytes)[2:-1]
def assembly_code_conversion(self):
assembly_code_start = self.address
assembly_code_end = self.address + len(self.data_bytes)
output = ""
i = assembly_code_start
if(assembly_code_start > ida_ida.inf_get_max_ea() or assembly_code_start < ida_ida.inf_get_min_ea()):
return ""
while i < assembly_code_end:
if(self.keep_names):
addr_name = idc.get_name(i)
if addr_name:
output += "\n" + addr_name + ":\n"
if(self.keep_comments):
output += idc.generate_disasm_line(i,0)
else:
output += idc.generate_disasm_line(i,0).split(";")[0]
output += "\n"
i = idc.find_code(i, 1)
return output
class DEP_Form(idaapi.Form):
# idaapi information
min_ea = ida_ida.inf_get_min_ea()
max_ea = ida_ida.inf_get_max_ea()
# list
Data_base_list, Data_type_list, Data_exported_format_list = DEP_Conversion.get_list()
# We map data_type_key to form field visibility using O(1) time to look
# Here True = show field, False = hide field
FIELD_VISIBILITY = {
DATA_TYPE_BYTE_KEY: {
'_endianness': False, '_base': True, '_signed': True, '_pad_zero': True,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_WORD_KEY: {
'_endianness': True, '_base': True, '_signed': True, '_pad_zero': True,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_DWORD_KEY: {
'_endianness': True, '_base': True, '_signed': True, '_pad_zero': True,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_QWORD_KEY: {
'_endianness': True, '_base': True, '_signed': True, '_pad_zero': True,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_FLOAT_KEY: {
'_endianness': True, '_base': False, '_signed': False, '_pad_zero': False,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_DOUBLE_KEY: {
'_endianness': True, '_base': False, '_signed': False, '_pad_zero': False,
'_delimiter': True, '_prefix': True, '_suffix': True,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_STRING_LITERAL_KEY: {
'_endianness': False, '_base': False, '_signed': False, '_pad_zero': False,
'_delimiter': False, '_prefix': False, '_suffix': False,
'_keep_comments': False, '_keep_names': False
},
DATA_TYPE_ASSEMBLY_CODE_KEY: {
'_endianness': False, '_base': False, '_signed': False, '_pad_zero': False,
'_delimiter': False, '_prefix': False, '_suffix': False,
'_keep_comments': True, '_keep_names': True
},
DATA_TYPE_RAW_BYTES_KEY: {
'_endianness': False, '_base': False, '_signed': False, '_pad_zero': False,
'_delimiter': False, '_prefix': False, '_suffix': False,
'_keep_comments': False, '_keep_names': False
}
}
def __init__(self, select_addr_start, select_addr_end, select_len):
self.export_address_start = select_addr_start
self.export_address_end = select_addr_end
self.export_address_len = select_len
self.Data_bytes = b""
self.export_data_type_key = DATA_TYPE_BYTE_KEY
# Format Options
self.export_big_endian = False
self.export_base_key = DATA_BASE_HEX_KEY
self.export_signed = False
self.export_delimiter = ","
self.export_prefix = "0x"
self.export_suffix = ""
self.export_as_type_key = EXPORT_FORMAT_STRING_KEY
self.export_keep_comments = True
self.export_keep_names = True
self.export_pad_zero = False
self.export_data = None
self.export_file_path = path.join(getcwd(), "export_results.txt")
data_type_flag = get_flags(self.export_address_start)
checks = [
(idc.is_byte, DATA_TYPE_BYTE_KEY),
(idc.is_word, DATA_TYPE_WORD_KEY),
(idc.is_dword, DATA_TYPE_DWORD_KEY),
(idc.is_qword, DATA_TYPE_QWORD_KEY),
(idc.is_float, DATA_TYPE_FLOAT_KEY),
(idc.is_double, DATA_TYPE_DOUBLE_KEY),
(idc.is_strlit, DATA_TYPE_STRING_LITERAL_KEY),
(idc.is_code, DATA_TYPE_ASSEMBLY_CODE_KEY),
]
self.export_data_type_key = next((key for func, key in checks if func(data_type_flag)), DATA_TYPE_BYTE_KEY)
super(DEP_Form, self).__init__(
r'''STARTITEM 0
BUTTON YES* Export
Export Plus: Export Data
{FormChangeCb}
<Start Address :{_address_start}>
<End Address :{_address_end}>
<Selected Length :{_length}>
<~Selected Data~ :{_select_data}>
< Data Type :{_data_type}>
< Export As :{_export_type}>
Export Format:
<##- Endianness :{_endianness}>
<##- Base :{_base}>
<##- Signed :{_signed}>
<##- Pad Zero :{_pad_zero}>
<##- Delimiter :{_delimiter}>
<##- Prefix :{_prefix}>
<##- Suffix :{_suffix}>
<##- Keep Comments:{_keep_comments}>
<##- Keep Names :{_keep_names}>
<~Export Window~: {_export_text}>
<Export File Path: {_export_file_path}>''',
{
"FormChangeCb": self.FormChangeCb(self.OnFormChange),
"_address_start": self.NumericInput(value = self.export_address_start, tp=self.FT_ADDR, swidth=30),
"_address_end": self.NumericInput(value = self.export_address_end, tp=self.FT_ADDR, swidth=30),
"_length": self.NumericInput(value = self.export_address_len, swidth = 30),
"_select_data": self.StringInput(value = "",swidth = 30),
"_data_type": self.DropdownListControl(items = list(self.Data_type_list.keys()), selval = self.export_data_type_key),
"_export_type": self.DropdownListControl(items =list(self.Data_exported_format_list.keys())),
"_endianness": self.DropdownListControl(items = ["Little-endian","Big-endian"]),
"_base": self.DropdownListControl(items = list(self.Data_base_list.keys())),
"_signed": self.DropdownListControl(items = ["False", "True"]),
"_pad_zero": self.DropdownListControl(items = ["False", "True"]),
"_delimiter": self.StringInput(value = self.export_delimiter,swidth = 30),
"_prefix": self.StringInput(value = self.export_prefix,swidth = 30),
"_suffix": self.StringInput(value = self.export_suffix,swidth = 30),
"_keep_comments": self.DropdownListControl(items = ["False", "True"], selval = 1),
"_keep_names": self.DropdownListControl(items = ["False", "True"], selval = 1),
"_export_text": self.MultiLineTextControl(text="", swidth=48),
"_export_file_path": self.FileInput(value=self.export_file_path, save=True, swidth=30),
}
)
self.Compile()
def OnFormChange(self, fid):
if fid == -1:
self._initalizate()
elif fid in [self._address_start.id, self._address_end.id, self._length.id]:
self._update_address_fields(fid)
elif fid in [self._data_type.id, self._export_type.id, self._signed.id]:
self._update_export_settings()
self._update_field_visibility()
self._update_field_availability()
self._set_controls_default_value()
elif fid in [self._endianness.id, self._base.id, self._signed.id, self._pad_zero.id,
self._delimiter.id, self._prefix.id, self._suffix.id,
self._keep_comments.id, self._keep_names.id]:
self._update_format_settings(fid)
elif fid == self._export_file_path.id:
self.export_file_path = self.GetControlValue(self._export_file_path)
self._refresh_export_window()
return 1
def _initalizate(self):
self.EnableField(self._select_data, False)
self._update_address_fields(-1)
self._update_export_settings()
self._update_field_visibility()
self._update_field_availability()
self._set_controls_default_value()
def _update_address_fields(self, fid):
input_export_address_start = self.GetControlValue(self._address_start)
input_export_address_end = self.GetControlValue(self._address_end)
input_export_address_len = self.GetControlValue(self._length)
self.min_ea = ida_ida.inf_get_min_ea()
self.max_ea = ida_ida.inf_get_max_ea()
try:
if fid in (self._address_start.id, self._address_end.id):
if not (self.min_ea <= input_export_address_start <= self.max_ea and
self.min_ea <= input_export_address_end <= self.max_ea):
return 1
if input_export_address_start >= input_export_address_end:
return 1
input_export_address_len = input_export_address_end - input_export_address_start
self.SetControlValue(self._length, input_export_address_len)
elif fid == self._length.id:
if not (self.min_ea <= input_export_address_start <= self.max_ea and
input_export_address_start + input_export_address_len <= self.max_ea):
return 1
input_export_address_end = input_export_address_start + input_export_address_len
self.SetControlValue(self._address_end, input_export_address_end)
if (self.min_ea <= input_export_address_start and
self.max_ea > input_export_address_start + input_export_address_len):
self.Data_bytes, data_str = self._get_ea_data(input_export_address_start, input_export_address_len)
self.SetControlValue(self._select_data, data_str)
self.export_address_start = input_export_address_start
self.export_address_len = input_export_address_len
except TypeError:
return 1
def _update_export_settings(self):
self.export_data_type_key = self.GetControlValue(self._data_type)
self.export_as_type_key = self.GetControlValue(self._export_type)
self.export_signed = {0: False, 1: True}[self.GetControlValue(self._signed)]
def _update_field_visibility(self):
visibility = self.FIELD_VISIBILITY.get(self.export_data_type_key, {})
for field_name, show in visibility.items():
self.ShowField(getattr(self, field_name), show)
self.ShowField(self._export_type,
self.export_data_type_key != DATA_TYPE_RAW_BYTES_KEY)
def _update_field_availability(self):
if self.export_as_type_key == EXPORT_FORMAT_STRING_KEY:
self.EnableField(self._delimiter, True)
self.EnableField(self._prefix, True)
self.EnableField(self._suffix, True)
else:
self.EnableField(self._delimiter, False)
self.EnableField(self._prefix, False)
self.EnableField(self._suffix, False)
def _update_format_settings(self, fid):
self.export_big_endian = self.GetControlValue(self._endianness)
self.export_base_key = self.GetControlValue(self._base)
self.export_signed = {0: False, 1: True}[self.GetControlValue(self._signed)]
self.export_pad_zero = {0: False, 1: True}[self.GetControlValue(self._pad_zero)]
self.export_delimiter = self.GetControlValue(self._delimiter)
self.export_prefix = self.GetControlValue(self._prefix)
self.export_suffix = self.GetControlValue(self._suffix)
self.export_keep_comments = {0: False, 1: True}[self.GetControlValue(self._keep_comments)]
self.export_keep_names = {0: False, 1: True}[self.GetControlValue(self._keep_names)]
if fid in [self._base.id, self._signed.id]:
self._set_controls_default_value()
def _get_ea_data(self, address, length):
data_byte = idc.get_bytes(address, length)
data_str = ' '.join([f"{i:02X}" for i in bytearray(data_byte)])
return data_byte, data_str.strip()
def _refresh_export_window(self):
t = DEP_Conversion(
address=self.export_address_start, data_bytes=self.Data_bytes,
data_type_key=self.export_data_type_key, export_as_type_key=self.export_as_type_key,
big_endian=self.export_big_endian, base_key=self.export_base_key,
signed=self.export_signed, pad_zero=self.export_pad_zero,
delimiter=self.export_delimiter, prefix=self.export_prefix, suffix=self.export_suffix,
keep_comments=self.export_keep_comments, keep_names=self.export_keep_names
)
self.export_data = t.activate()
self.SetControlValue(self._export_text, idaapi.textctrl_info_t(
text=self.export_data, flags=32, tabsize=0))
def _set_controls_default_value(self):
self._set_default_prefix_value()
self._set_default_delimiter_value()
self._set_default_suffix_value()
def _set_default_prefix_value(self):
if self.export_data_type_key in [DATA_TYPE_BYTE_KEY, DATA_TYPE_WORD_KEY,
DATA_TYPE_DWORD_KEY, DATA_TYPE_QWORD_KEY]:
Prefix_list = {DATA_BASE_HEX_KEY: "0x", DATA_BASE_DEC_KEY: "",
DATA_BASE_OCT_KEY: "0o", DATA_BASE_BIN_KEY: "0b"}
self.export_prefix = Prefix_list[self.export_base_key]
if (self.export_as_type_key == EXPORT_FORMAT_C_VARIABLE_KEY and
self.export_base_key == DATA_BASE_OCT_KEY):
self.export_prefix = "0"
elif self.export_data_type_key in [DATA_TYPE_FLOAT_KEY, DATA_TYPE_DOUBLE_KEY]:
self.export_prefix = ""
self.SetControlValue(self._prefix, self.export_prefix)
def _set_default_delimiter_value(self):
if self.export_data_type_key in [DATA_TYPE_BYTE_KEY, DATA_TYPE_WORD_KEY,
DATA_TYPE_DWORD_KEY, DATA_TYPE_QWORD_KEY,
DATA_TYPE_FLOAT_KEY, DATA_TYPE_DOUBLE_KEY]:
self.export_delimiter = ", "
self.SetControlValue(self._delimiter, self.export_delimiter)
def _set_default_suffix_value(self):
self.export_suffix = ""
if self.export_as_type_key == EXPORT_FORMAT_C_VARIABLE_KEY:
suffix_map = {
DATA_TYPE_BYTE_KEY: "", DATA_TYPE_WORD_KEY: "",
DATA_TYPE_DWORD_KEY: "L", DATA_TYPE_QWORD_KEY: "LL",
DATA_TYPE_FLOAT_KEY: "", DATA_TYPE_DOUBLE_KEY: ""
}
suffix = suffix_map.get(self.export_data_type_key, "")
if not self.export_signed and self.export_data_type_key in [
DATA_TYPE_BYTE_KEY, DATA_TYPE_WORD_KEY, DATA_TYPE_DWORD_KEY, DATA_TYPE_QWORD_KEY]:
suffix = "U" + suffix
self.export_suffix = suffix
self.SetControlValue(self._suffix, self.export_suffix)
class DataExportPlus(idaapi.plugin_t):
flags = idaapi.PLUGIN_DRAW
comment = "Export Data"
help = ""
wanted_name = "Data Export Plus"
version = VERSION
def init(self):
print("=" * 80)
print("Start Data Export Plus plugin")
idc.del_idc_hotkey("Shift+E")
add_hotkey("Shift-E", self.hotkeystart)
return idaapi.PLUGIN_OK
def term(self):
return
def hotkeystart(self):
self.run(None)
def run(self, args):
ea_addr_start, ea_addr_end, ea_item_size = self.GetEAItem()
form = DEP_Form(ea_addr_start, ea_addr_end, ea_item_size)
IsExport = form.Execute()
if IsExport:
if path.exists(form.export_file_path):
k = idc.ask_yn(1, "Export file already exists, Do you want to overwrite it?")
if k == -1 or k == 0:
form.Free()
return 1
try:
if form.export_data_type_key == DATA_TYPE_RAW_BYTES_KEY:
with open(form.export_file_path, "wb") as file_handle:
file_handle.write(form.Data_bytes)
else:
with open(form.export_file_path, "w", encoding="utf-8") as file_handle:
file_handle.write(form.export_data)
print("Stored export results in", form.export_file_path)
except:
idc.warning("Export file failed")
form.Free()
return 1
def GetEAItem(self):
selection, ea_addr_start, ea_addr_end = idaapi.read_range_selection(None)
if selection:
if ea_addr_start <= ea_addr_end:
ea_item_size = ea_addr_end - ea_addr_start
else:
ea_item_size = ea_addr_start - ea_addr_end
else:
ea_addr_start = idc.get_screen_ea()
ea_item_size = idc.get_item_size(idc.get_screen_ea())
ea_addr_end = ea_addr_start + ea_item_size
return ea_addr_start, ea_addr_end, ea_item_size
def PLUGIN_ENTRY():
return DataExportPlus()
```
`LICENSE`:
```
MIT License
Copyright (c) 2024 Krietz7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
`README.md`:
```md
# IDA-DataExportPlus
[中文](README.zh_CN.md)
a IDA Pro plugin for exporting data, it can replace the IDA Pro original Data Export Window.
The plugin supports export data base on different data type, include integer and floating point types of different sizes. Additional it also supports export assembly code.
## Installation
Copy `DataExportPlus.py` to IDA plugins directory. Requires IDA Pro version 7.6 or above
## Usage
Use hotkey `Shift+E` to Call out the plugin window
<img width="2560" height="1444" alt="image" src="https://github.com/user-attachments/assets/3d100006-847c-40d9-af1f-629d93f9c0aa" />
You can change the format of the exported data in this window
<img width="2559" height="1408" alt="image" src="https://github.com/user-attachments/assets/ca58e48b-8b00-4afc-9839-8b4c9b00d4e3" />
Exporting assembly code
<img width="2475" height="1410" alt="image" src="https://github.com/user-attachments/assets/15d4bb43-2b9e-44d0-a9ad-b62f6d5fc841" />
```
`README.zh_CN.md`:
```md
# IDA-DataExportPlus
一个用于导出数据的IDA PRO插件,它可以替换IDA Pro原始的数据导出窗口。
该插件支持基于不同数据类型的数据导出,包括不同大小的整数和浮点类型。除此之外也支持导出汇编代码。
## 安装
复制`dataexportplus.py`到IDA插件目录下。需要IDA Pro版本7.6或以上
## 使用方法
使用快捷键`Shift+E`以唤出插件窗口
<img width="2560" height="1444" alt="image" src="https://github.com/user-attachments/assets/3d100006-847c-40d9-af1f-629d93f9c0aa" />
您可以在此窗口中更改导出数据的格式
<img width="2559" height="1408" alt="image" src="https://github.com/user-attachments/assets/ca58e48b-8b00-4afc-9839-8b4c9b00d4e3" />
导出汇编代码
<img width="2475" height="1410" alt="image" src="https://github.com/user-attachments/assets/15d4bb43-2b9e-44d0-a9ad-b62f6d5fc841" />
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff