hexforge_modules/misc_modules.py (224 lines of code) (raw):
import ida_kernwin
import idaapi
import idc
import binascii
import re
from hexforge_modules import helper
REGEX_HEX = re.compile(r"[^0-9a-fA-F]")
class PatchMemory(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::patch_memory"
self.ACTION_TEXT = "patch memory"
self.ACTION_TOOLTIP = "patch memory"
# function to execute
def _action(self) -> None:
data = self._show()
helper.write_bytes_to_selected(data)
def _show(self):
f = self.InputFormT()
f, _ = f.Compile()
# Show form
f.Execute()
data = None
try:
data_input = f.hex_data.value
if f.Data_UTF8.checked: # ascii data
data = data_input.encode()
else: # hex data
data = binascii.unhexlify(re.sub(REGEX_HEX, "", data_input))
except binascii.Error as e:
print(e)
f.Free()
return data
class InputFormT(ida_kernwin.Form):
def __init__(self):
self.__n = 0
F = ida_kernwin.Form
F.__init__(
self,
r"""BUTTON YES* Ok
Patch memory Settings
{FormChangeCb}
<Data UTF8:{Data_UTF8}>{cData_UTF8Group}>
<##Data :{hex_data}>
""",
{
"FormChangeCb": F.FormChangeCb(self.OnFormChange),
"cData_UTF8Group": F.ChkGroupControl(("Data_UTF8",)),
"hex_data": F.MultiLineTextControl(
text="", flags=F.MultiLineTextControl.TXTF_FIXEDFONT
),
},
)
def OnFormChange(self, fid):
return 1
class NopMemory(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::nop_memory"
self.ACTION_TEXT = "nop memory"
self.ACTION_TOOLTIP = "nop memory"
def _action(self) -> None:
self._nop_selected_bytes()
def _nop_selected_bytes(self):
data = helper.get_selected_bytes()
if data is None:
idaapi.msg("Failed to get selected bytes.\n")
return
# create NOP array with the size of the selection
nop_data = bytearray(len(data))
nop_data[:] = b"\x90" * len(data)
# write the NOPs to the selected address range
helper.write_bytes_to_selected(nop_data)
class CopyMemory(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::copy_memory"
self.ACTION_TEXT = "copy memory"
self.ACTION_TOOLTIP = "copy memory"
def _action(self) -> None:
from PyQt5.Qt import QApplication
data = helper.get_selected_bytes()
try:
QApplication.clipboard().setText(binascii.hexlify(data).decode("utf-8"))
except (binascii.Error, UnicodeDecodeError) as e:
print(e)
return None
class DumpMemory(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::dump_memory"
self.ACTION_TEXT = "dump memory"
self.ACTION_TOOLTIP = "dump memory"
# function to execute
def _action(self) -> None:
result = self._show()
if result:
start_addr, end_addr, filepath = result
self.dump_memory_to_file(start_addr, end_addr, filepath)
def _show(self):
f = self.InputFormT()
f, _ = f.Compile()
# Show form
f.Execute()
start_addr = None
end_addr = None
filepath = None
try:
start_addr = int(f.start_addr.value, 16)
end_addr = int(f.end_addr.value, 16)
filepath = f.filepath.value
except ValueError as e:
print(e)
f.Free()
return start_addr, end_addr, filepath
def dump_memory_to_file(self, start_addr, end_addr, filepath):
size = end_addr - start_addr
data = idaapi.get_bytes(start_addr, size)
if data:
with open(filepath, "wb") as f:
f.write(data)
print(f"Memory dumped to {filepath}")
else:
print("Failed to read memory")
class InputFormT(ida_kernwin.Form):
def __init__(self):
self.__n = 0
F = ida_kernwin.Form
F.__init__(
self,
r"""BUTTON YES* Ok
Dump Memory
{FormChangeCb}
<Start Address :{start_addr}>
<End Address :{end_addr}>
<Filepath :{filepath}>
""",
{
"FormChangeCb": F.FormChangeCb(self.OnFormChange),
"start_addr": F.StringInput(),
"end_addr": F.StringInput(),
"filepath": F.StringInput(),
},
)
def OnFormChange(self, fid):
return 1
class GetRVA(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::get_RVA"
self.ACTION_TEXT = "get RVA"
self.ACTION_TOOLTIP = "get RVA"
def _action(self) -> None:
from PyQt5.Qt import QApplication
image_base = idaapi.get_imagebase()
current_addr = idc.get_screen_ea()
if current_addr != idc.BADADDR:
rva = current_addr - image_base
print(f"Image Base: 0x{image_base:X}")
print(f"Current Address: 0x{current_addr:X}")
print(f"RVA: 0x{rva:X}")
try:
QApplication.clipboard().setText(f"0x{rva:X}")
except (binascii.Error, UnicodeDecodeError) as e:
print(e)
return None
else:
print("No valid address selected!")
class GetCurrentAddress(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::get_current_address"
self.ACTION_TEXT = "get current address"
self.ACTION_TOOLTIP = "get current address"
def _action(self) -> None:
from PyQt5.Qt import QApplication
image_base = idaapi.get_imagebase()
current_addr = idc.get_screen_ea()
if current_addr != idc.BADADDR:
print(f"Image Base: 0x{image_base:X}")
print(f"Current Address: 0x{current_addr:X}")
try:
QApplication.clipboard().setText(f"0x{current_addr:X}")
except (binascii.Error, UnicodeDecodeError) as e:
print(e)
return None
else:
print("No valid address selected!")
class GetFileOffset(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::get_file_offset"
self.ACTION_TEXT = "get file offset address"
self.ACTION_TOOLTIP = "get file offset address"
def _action(self) -> None:
from PyQt5.Qt import QApplication
current_ea = idc.get_screen_ea()
# Map the VA to the corresponding file offset
file_offset = idaapi.get_fileregion_offset(current_ea)
if file_offset != -1:
print(f"Current Address: 0x{current_ea:X}")
print(f"File Offset: 0x{file_offset:X}")
try:
QApplication.clipboard().setText(f"0x{file_offset:X}")
except (binascii.Error, UnicodeDecodeError) as e:
print(e)
return None
else:
print("Failed to compute file offset.")
class SetMemory(helper.ModuleTemplate):
def __init__(self):
self.ACTION_NAME = "hexforge::set_memory"
self.ACTION_TEXT = "set memory"
self.ACTION_TOOLTIP = "set memory"
# function to execute
def _action(self) -> None:
value = self._show()
data = helper.get_selected_bytes()
val_data = bytearray(len(data))
val_data[:] = value * len(data)
helper.write_bytes_to_selected(val_data)
def _show(self):
f = self.InputFormT()
f, _ = f.Compile()
# Show form
f.Execute()
value = None
try:
value_input = f.Value.value
value = binascii.unhexlify(re.sub(REGEX_HEX, "", value_input))
except binascii.Error as e:
print(e)
f.Free()
return value
class InputFormT(ida_kernwin.Form):
def __init__(self):
self.__n = 0
F = ida_kernwin.Form
F.__init__(
self,
r"""BUTTON YES* Ok
Set memory Settings
{FormChangeCb}
<##1-byte value :{Value}>
""",
{
"FormChangeCb": F.FormChangeCb(self.OnFormChange),
"Value": F.StringInput(),
},
)
def OnFormChange(self, fid):
return 1