diff --git a/src/gui/dialogs/write_form.py b/src/gui/dialogs/write_form.py new file mode 100644 index 0000000..9693f39 --- /dev/null +++ b/src/gui/dialogs/write_form.py @@ -0,0 +1,25 @@ +# This file is part of ot-project. +# +# ot-project is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ot-project is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Foobar. If not, see . +# + +from PyQt5.Qt import QDialog + +from gui.ui.dialogs.write_form import Ui_WriteForm + + +class WriteForm(QDialog, Ui_WriteForm): + def __init__(self, parent=None): + super().__init__(parent) + self.setupUi(self) diff --git a/src/gui/main_window.py b/src/gui/main_window.py index c041dae..4458bea 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -14,13 +14,17 @@ # along with Foobar. If not, see . # import operator +import struct from PyQt5.Qt import QMainWindow, QHeaderView, QMessageBox from PyQt5.QtCore import pyqtSlot, QModelIndex from psutil import NoSuchProcess from gui.dialogs.process_view import ProcessView +from gui.dialogs.write_form import WriteForm +from gui.items.tree_item import TreeItem from gui.models.found_address_model import FoundAddressModel +from gui.models.saved_address_model import SavedAddressHeaderEnum from gui.ui.widgets.mainwindow import Ui_MainWindow from memory.memory import Memory from memory.type import Type @@ -41,6 +45,7 @@ def __init__(self): self.next_scan.clicked.connect(self.next_scan_clicked) self.actionAttach.triggered.connect(self.attach_triggered) self.found_table.doubleClicked.connect(self.found_table_double_clicked) + self.saved_results.doubleClicked.connect(self.saved_model_double_clicked) @pyqtSlot() def new_scan_clicked(self): @@ -84,3 +89,32 @@ def found_table_double_clicked(self, index: QModelIndex): return clicked_value = self.found_table.model().get_value(index.row()) self.saved_results.model().append_row(clicked_value) + + @pyqtSlot(QModelIndex) + def saved_model_double_clicked(self, index: QModelIndex): + if not index.isValid(): + return + column = index.column() + + if column == SavedAddressHeaderEnum.VALUE: + form = WriteForm(self) + x = form.exec_() + text = form.value.text() + if x and len(text) != 0: + item: TreeItem = self.saved_results.model().get_item(index) + value = item.get_internal_pointer() + try: + value.write(value.type.parse_value(text, form.ishex.isChecked())) + except struct.error: + QMessageBox(QMessageBox.NoIcon, "Error", "You can't write a larger number to " + "memory than you currently have set " + "as a type.\nSee limits.h for more " + "information", + QMessageBox.Ok, self).exec_() + except ValueError: + # this is a kinda temporary fix, I'm planning on adding a validator or some + # shit later, not entirely sure how to add them yet so this will do + QMessageBox(QMessageBox.NoIcon, "Error", "Error parsing value, you probably " + "entered text when trying to write " + "an integer...", + QMessageBox.Ok, self).exec_() diff --git a/src/gui/ui/dialogs/write_form.py b/src/gui/ui/dialogs/write_form.py new file mode 100644 index 0000000..393ab05 --- /dev/null +++ b/src/gui/ui/dialogs/write_form.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'write_form.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_WriteForm(object): + def setupUi(self, WriteForm): + WriteForm.setObjectName("WriteForm") + WriteForm.resize(238, 107) + WriteForm.setModal(True) + self.verticalLayout = QtWidgets.QVBoxLayout(WriteForm) + self.verticalLayout.setObjectName("verticalLayout") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.ishex = QtWidgets.QCheckBox(WriteForm) + self.ishex.setObjectName("ishex") + self.horizontalLayout.addWidget(self.ishex) + self.value = QtWidgets.QLineEdit(WriteForm) + self.value.setObjectName("value") + self.horizontalLayout.addWidget(self.value) + self.verticalLayout.addLayout(self.horizontalLayout) + self.buttonBox = QtWidgets.QDialogButtonBox(WriteForm) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.verticalLayout.addWidget(self.buttonBox) + + self.retranslateUi(WriteForm) + self.buttonBox.accepted.connect(WriteForm.accept) + self.buttonBox.rejected.connect(WriteForm.reject) + QtCore.QMetaObject.connectSlotsByName(WriteForm) + + def retranslateUi(self, WriteForm): + _translate = QtCore.QCoreApplication.translate + WriteForm.setWindowTitle(_translate("WriteForm", "Write")) + self.ishex.setText(_translate("WriteForm", "Hex")) diff --git a/src/gui/ui/dialogs/write_form.ui b/src/gui/ui/dialogs/write_form.ui new file mode 100644 index 0000000..731ee2d --- /dev/null +++ b/src/gui/ui/dialogs/write_form.ui @@ -0,0 +1,81 @@ + + + WriteForm + + + + 0 + 0 + 238 + 107 + + + + Write + + + true + + + + + + + + Hex + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + WriteForm + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WriteForm + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/views/saved_address_view.py b/src/gui/views/saved_address_view.py index 9aab5b6..90facb3 100644 --- a/src/gui/views/saved_address_view.py +++ b/src/gui/views/saved_address_view.py @@ -14,15 +14,13 @@ # along with Foobar. If not, see . # -from PyQt5.Qt import QTreeView, QComboBox, QWidget -from PyQt5.QtCore import QModelIndex, pyqtSlot, QMutexLocker +from PyQt5.Qt import QTreeView +from PyQt5.QtCore import QModelIndex, pyqtSlot -from gui.models.saved_address_model import SavedAddressModel -from gui.threads.saved_results_thread import mutex, SavedResultsThread -from gui.items.tree_item import SavedAddressHeaderEnum, TreeItem from gui.delegates.type_delegate import TypeDelegate +from gui.items.tree_item import SavedAddressHeaderEnum, TreeItem +from gui.models.saved_address_model import SavedAddressModel from memory.type import Type -from memory.value import Value class SavedAddressView(QTreeView): @@ -35,7 +33,6 @@ def __init__(self, parent=None): self.setItemDelegateForColumn(SavedAddressHeaderEnum.TYPE, type_delegate) self._datamodel.layoutChanged.connect(self.__init_comboboxes) - def append_row(self, value): """ Places a value at the end of the root item diff --git a/src/memory/binary_io.py b/src/memory/binary_io.py index 4cb6ed3..35a5fcf 100644 --- a/src/memory/binary_io.py +++ b/src/memory/binary_io.py @@ -41,3 +41,16 @@ def _read(self, address: int, value_type: Type): bytes_read = mem.read(size) return value_type.get_format().unpack(bytes_read)[0] + + def _write(self, address: int, data: bytes): + """ + writes data to a given address + + :param address: address to write to + :param data: data in bytes to write + :return: bytes written + """ + + with open(f"/proc/{self.pid}/mem", "r+b") as mem: + mem.seek(address) + return mem.write(data) diff --git a/src/memory/value.py b/src/memory/value.py index e845e8c..9b98bad 100644 --- a/src/memory/value.py +++ b/src/memory/value.py @@ -64,8 +64,8 @@ def read(self): self.value = super()._read(self.address, self.type) return self.value - def write(self, address): - pass + def write(self, new_value): + self._write(self.address, self.type.get_format().pack(new_value)) def change_type(self, typeof: Type): print("Swapping type")