Skip to content

Commit

Permalink
Implement signed/unsigned conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
korcankaraokcu committed Jul 11, 2022
1 parent f13351d commit 4bf7908
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 60 deletions.
89 changes: 49 additions & 40 deletions PINCE.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,9 @@ def treeWidget_AddressTable_context_menu_event(self, event):
edit_type = edit_menu.addAction("Type[Alt+Enter]")
edit_value = edit_menu.addAction("Value[Enter]")
show_hex = menu.addAction("Show as hexadecimal")
show_dec = menu.addAction("Show as decimal")
show_unsigned = menu.addAction("Show as unsigned")
show_signed = menu.addAction("Show as signed")
toggle_record = menu.addAction("Toggle selected records[Space]")
menu.addSeparator()
browse_region = menu.addAction("Browse this memory region[Ctrl+B]")
Expand All @@ -620,16 +623,21 @@ def treeWidget_AddressTable_context_menu_event(self, event):
what_reads = menu.addAction("Find out what reads this address")
what_accesses = menu.addAction("Find out what accesses this address")
if current_row is None:
deletion_list = [edit_menu.menuAction(), show_hex, toggle_record, browse_region, disassemble, what_writes,
what_reads, what_accesses]
deletion_list = [edit_menu.menuAction(), show_hex, show_dec, show_unsigned, show_signed, toggle_record,
browse_region, disassemble, what_writes, what_reads, what_accesses]
GuiUtils.delete_menu_entries(menu, deletion_list)
else:
current_text = current_row.text(TYPE_COL)
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(current_text)
if type_defs.VALUE_INDEX.has_length(index):
GuiUtils.delete_menu_entries(menu, [show_hex])
elif hex_repr:
show_hex.setText("Show as decimal")
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(current_text)
if type_defs.VALUE_INDEX.is_integer(index):
if value_repr is type_defs.VALUE_REPR.HEX:
GuiUtils.delete_menu_entries(menu, [show_unsigned, show_signed, show_hex])
elif value_repr is type_defs.VALUE_REPR.UNSIGNED:
GuiUtils.delete_menu_entries(menu, [show_unsigned, show_dec])
elif value_repr is type_defs.VALUE_REPR.SIGNED:
GuiUtils.delete_menu_entries(menu, [show_signed, show_dec])
else:
GuiUtils.delete_menu_entries(menu, [show_hex, show_dec, show_unsigned, show_signed])
font_size = self.treeWidget_AddressTable.font().pointSize()
menu.setStyleSheet("font-size: " + str(font_size) + "pt;")
action = menu.exec_(event.globalPos())
Expand All @@ -638,7 +646,10 @@ def treeWidget_AddressTable_context_menu_event(self, event):
edit_address: self.treeWidget_AddressTable_edit_address,
edit_type: self.treeWidget_AddressTable_edit_type,
edit_value: self.treeWidget_AddressTable_edit_value,
show_hex: self.treeWidget_AddressTable_show_hex,
show_hex: lambda: self.treeWidget_AddressTable_change_repr(type_defs.VALUE_REPR.HEX),
show_dec: lambda: self.treeWidget_AddressTable_change_repr(type_defs.VALUE_REPR.UNSIGNED),
show_unsigned: lambda: self.treeWidget_AddressTable_change_repr(type_defs.VALUE_REPR.UNSIGNED),
show_signed: lambda: self.treeWidget_AddressTable_change_repr(type_defs.VALUE_REPR.SIGNED),
toggle_record: self.toggle_selected_records,
browse_region: self.browse_region_for_selected_row,
disassemble: self.disassemble_selected_row,
Expand Down Expand Up @@ -666,7 +677,7 @@ def exec_track_watchpoint_widget(self, watchpoint_type):
return
address = selected_row.text(ADDR_COL)
value_type_text = selected_row.text(TYPE_COL)
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(value_type_text)
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(value_type_text)
if byte_len == -1:
value_text = selected_row.text(VALUE_COL)
encoding, option = type_defs.string_index_to_encoding_dict[index]
Expand Down Expand Up @@ -823,7 +834,7 @@ def update_address_table(self):
table_contents = []
address_expr_list = []
value_type_list = []
hex_repr_list = []
value_repr_list = []
rows = []
while True:
row = it.value()
Expand All @@ -838,16 +849,19 @@ def update_address_table(self):
except type_defs.InferiorRunningException:
address_list = address_expr_list
for address, value_type in zip(address_list, value_type_list):
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(value_type)
table_contents.append((address, index, length, zero_terminate))
hex_repr_list.append(hex_repr)
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(value_type)
signed = False
if value_repr == type_defs.VALUE_REPR.SIGNED:
signed = True
table_contents.append((address, index, length, zero_terminate, signed))
value_repr_list.append(value_repr)
new_table_contents = GDB_Engine.read_memory_multiple(table_contents)
for row, address, address_expr, value, hex_repr in zip(rows, address_list, address_expr_list,
new_table_contents, hex_repr_list):
for row, address, address_expr, value, value_repr in zip(rows, address_list, address_expr_list,
new_table_contents, value_repr_list):
row.setText(ADDR_COL, address or address_expr)
if value is None:
value = ""
elif hex_repr:
elif value_repr == type_defs.VALUE_REPR.HEX:
value = hex(value)
else:
value = str(value)
Expand All @@ -860,7 +874,7 @@ def resize_address_table(self):
def pushButton_AddAddressManually_clicked(self):
manual_address_dialog = ManualAddressDialogForm()
if manual_address_dialog.exec_():
desc, address_expr, address_type, length, zero_terminate, hex_repr = manual_address_dialog.get_values()
desc, address_expr, address_type, length, zero_terminate = manual_address_dialog.get_values()
self.add_entry_to_addresstable(desc, address_expr, address_type, length, zero_terminate)

def pushButton_MemoryView_clicked(self):
Expand Down Expand Up @@ -1283,13 +1297,11 @@ def treeWidget_AddressTable_item_clicked(self, row, column):
if (len(FreezeVars) == 0):
FreezeStop = 1

def treeWidget_AddressTable_show_hex(self):
row = GuiUtils.get_current_item(self.treeWidget_AddressTable)
value_text = row.text(TYPE_COL)
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(value_text)
hex_repr = not hex_repr
def treeWidget_AddressTable_change_repr(self, new_repr):
value_text = GuiUtils.get_current_item(self.treeWidget_AddressTable).text(TYPE_COL)
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(value_text)
for row in self.treeWidget_AddressTable.selectedItems():
row.setText(TYPE_COL, GuiUtils.valuetype_to_text(index, length, zero_terminate, hex_repr))
row.setText(TYPE_COL, GuiUtils.valuetype_to_text(index, length, zero_terminate, new_repr))
self.update_address_table()

def treeWidget_AddressTable_edit_value(self):
Expand Down Expand Up @@ -1338,25 +1350,25 @@ def treeWidget_AddressTable_edit_address(self):
if not row:
return
desc, address_expr, value_type = self.read_address_table_entries(row=row)
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(value_type)
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(value_type)
manual_address_dialog = ManualAddressDialogForm(description=desc, address=address_expr, index=index,
length=length, zero_terminate=zero_terminate, hex_repr=hex_repr)
length=length, zero_terminate=zero_terminate)
manual_address_dialog.setWindowTitle("Edit Address")
if manual_address_dialog.exec_():
desc, address_expr, address_type, length, zero_terminate, hex_repr = manual_address_dialog.get_values()
address_type_text = GuiUtils.valuetype_to_text(address_type, length, zero_terminate, hex_repr)
desc, address_expr, address_type, length, zero_terminate = manual_address_dialog.get_values()
address_type_text = GuiUtils.valuetype_to_text(address_type, length, zero_terminate, value_repr)
self.change_address_table_entries(row, desc, address_expr, address_type_text)

def treeWidget_AddressTable_edit_type(self):
row = GuiUtils.get_current_item(self.treeWidget_AddressTable)
if not row:
return
value_type = row.text(TYPE_COL)
value_index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(value_type)
dialog = EditTypeDialogForm(index=value_index, length=length, zero_terminate=zero_terminate, hex_repr=hex_repr)
value_index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(value_type)
dialog = EditTypeDialogForm(index=value_index, length=length, zero_terminate=zero_terminate)
if dialog.exec_():
params = dialog.get_values()
type_text = GuiUtils.valuetype_to_text(*params)
value_index, length, zero_terminate = dialog.get_values()
type_text = GuiUtils.valuetype_to_text(value_index, length, zero_terminate, value_repr)
for row in self.treeWidget_AddressTable.selectedItems():
row.setText(TYPE_COL, type_text)
self.update_address_table()
Expand All @@ -1368,7 +1380,7 @@ def change_address_table_entries(self, row, description="", address_expr="", add
except type_defs.InferiorRunningException:
address = address_expr
value = ''
index, length, zero_terminate, byte_len, hex_repr = GuiUtils.text_to_valuetype(address_type)
index, length, zero_terminate, byte_len, value_repr = GuiUtils.text_to_valuetype(address_type)
if address:
value = GDB_Engine.read_memory(address, index, length, zero_terminate)

Expand Down Expand Up @@ -1471,14 +1483,13 @@ def pushButton_CreateProcess_clicked(self):
# Add Address Manually Dialog
class ManualAddressDialogForm(QDialog, ManualAddressDialog):
def __init__(self, parent=None, description="No Description", address="0x",
index=type_defs.VALUE_INDEX.INDEX_INT32, length=10, zero_terminate=True, hex_repr=False):
index=type_defs.VALUE_INDEX.INDEX_INT32, length=10, zero_terminate=True):
super().__init__(parent=parent)
self.setupUi(self)
self.adjustSize()
self.setMinimumWidth(300)
self.setFixedHeight(self.height())
self.lineEdit_length.setValidator(QHexValidator(999, self))
self.hex_repr = hex_repr
GuiUtils.fill_value_combobox(self.comboBox_ValueType, index)
self.lineEdit_description.setText(description)
self.lineEdit_address.setText(address)
Expand Down Expand Up @@ -1590,17 +1601,15 @@ def get_values(self):
if self.checkBox_zeroterminate.isChecked():
zero_terminate = True
address_type = self.comboBox_ValueType.currentIndex()
return description, address, address_type, length, zero_terminate, self.hex_repr
return description, address, address_type, length, zero_terminate


class EditTypeDialogForm(QDialog, EditTypeDialog):
def __init__(self, parent=None, index=type_defs.VALUE_INDEX.INDEX_INT32, length=10, zero_terminate=True,
hex_repr=False):
def __init__(self, parent=None, index=type_defs.VALUE_INDEX.INDEX_INT32, length=10, zero_terminate=True):
super().__init__(parent=parent)
self.setupUi(self)
self.setMaximumSize(100, 100)
self.lineEdit_Length.setValidator(QHexValidator(999, self))
self.hex_repr = hex_repr
GuiUtils.fill_value_combobox(self.comboBox_ValueType, index)
if type_defs.VALUE_INDEX.is_string(self.comboBox_ValueType.currentIndex()):
self.label_Length.show()
Expand Down Expand Up @@ -1667,7 +1676,7 @@ def get_values(self):
if self.checkBox_ZeroTerminate.isChecked():
zero_terminate = True
address_type = self.comboBox_ValueType.currentIndex()
return address_type, length, zero_terminate, self.hex_repr
return address_type, length, zero_terminate


class LoadingDialogForm(QDialog, LoadingDialog):
Expand Down Expand Up @@ -2552,7 +2561,7 @@ def exec_hex_view_add_address_dialog(self):
manual_address_dialog = ManualAddressDialogForm(address=hex(selected_address),
index=type_defs.VALUE_INDEX.INDEX_AOB)
if manual_address_dialog.exec_():
desc, address_expr, address_type, length, zero_terminate, hex_repr = manual_address_dialog.get_values()
desc, address_expr, address_type, length, zero_terminate = manual_address_dialog.get_values()
self.parent().add_entry_to_addresstable(desc, address_expr, address_type, length, zero_terminate)

def verticalScrollBar_HexView_mouse_release_event(self, event):
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ How to use line_profiler: Add ```@profile``` tag to the desired function and run
- Refactorize memory write/read functions
- - ReferencedStringsWidgetForm refreshes the cache everytime the comboBox_ValueType changes, this creates serious performance issues if total results are more than 800k. Only update the visible rows to prevent this(check ```disassemble_check_viewport``` for an example)
- - Implement same system for the TrackBreakpointWidgetForm if necessary. Do performance tests
- - Consider using a class instead of primitive return types to store the raw bytes. This also gets rid of the unnecessary parameter only_bytes. This class should also include a method to display None type as red '??' text for Qt
- - Consider using a class instead of primitive return types to store the raw bytes. This class should also include a method to display None type as red '??' text for Qt
- - text_to_valuetype is a bad design pattern. Store the information inside the items of tableWidget_AddressTable instead
- - read_memory_multiple follows a bad design pattern, use named tuples or something like that
- - Provide an option to cut BOM bytes when writing to memory with the types UTF-16 and UTF-32
Expand Down
17 changes: 8 additions & 9 deletions libpince/GDB_Engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ def inject_with_dlopen_call(library_path):


#:tag:MemoryRW
def read_memory(address, value_index, length=None, zero_terminate=True, only_bytes=False, mem_handle=None):
def read_memory(address, value_index, length=None, zero_terminate=True, signed=False, mem_handle=None):
"""Reads value from the given address
Args:
Expand All @@ -768,7 +768,7 @@ def read_memory(address, value_index, length=None, zero_terminate=True, only_byt
INDEX_STRING or INDEX_AOB. Ignored otherwise
zero_terminate (bool): If True, data will be split when a null character has been read. Only used when
value_index is INDEX_STRING. Ignored otherwise
only_bytes (bool): Returns only bytes instead of converting it to the according type of value_index
signed (bool): Casts the data as signed if True, unsigned if False. Only usable with integer types
mem_handle (BinaryIO): A file handle that points to the memory file of the current process
This parameter is used for optimization, intended for internal usage. Check read_memory_multiple for an example
Don't forget to close the handle after you're done if you use this parameter manually
Expand All @@ -777,7 +777,6 @@ def read_memory(address, value_index, length=None, zero_terminate=True, only_byt
str: If the value_index is INDEX_STRING or INDEX_AOB
float: If the value_index is INDEX_FLOAT32 or INDEX_FLOAT64
int: If the value_index is anything else
bytes: If the only_bytes is True
None: If an error occurs while reading the given address
"""
try:
Expand Down Expand Up @@ -826,8 +825,6 @@ def read_memory(address, value_index, length=None, zero_terminate=True, only_byt
# Maybe creating a function that toggles logging on and off? Other functions could use it too
# print("Can't access the memory at address " + hex(address) + " or offset " + hex(address + expected_length))
return
if only_bytes:
return data_read
if type_defs.VALUE_INDEX.is_string(value_index):
encoding, option = type_defs.string_index_to_encoding_dict[value_index]
returned_string = data_read.decode(encoding, option)
Expand All @@ -840,6 +837,8 @@ def read_memory(address, value_index, length=None, zero_terminate=True, only_byt
elif value_index is type_defs.VALUE_INDEX.INDEX_AOB:
return " ".join(format(n, '02x') for n in data_read)
else:
if type_defs.VALUE_INDEX.is_integer(value_index) and signed:
data_type = data_type.lower()
return struct.unpack_from(data_type, data_read)[0]


Expand All @@ -856,7 +855,7 @@ def read_memory_multiple(nested_list):
parameters are the same with the function read_memory.
Examples:
All parameters are passed-->[[address1, value_index1, length1, zero_terminate1, only_bytes], ...]
All parameters are passed-->[[address1, value_index1, length1, zero_terminate1, signed], ...]
Parameters are partially passed--▼
[[address1, value_index1],[address2, value_index2, length2],[address3, value_index3, length3], ...]
Expand All @@ -881,10 +880,10 @@ def read_memory_multiple(nested_list):
except IndexError:
zero_terminate = True
try:
only_bytes = item[4]
signed = item[4]
except IndexError:
only_bytes = False
data_read = read_memory(address, index, length, zero_terminate, only_bytes, mem_handle)
signed = False
data_read = read_memory(address, index, length, zero_terminate, signed, mem_handle)
data_read_list.append(data_read)
mem_handle.close()
return data_read_list
Expand Down
Loading

0 comments on commit 4bf7908

Please sign in to comment.