def setUp(self): self.memory = Memory(0x1000) self.sound_timer = Timer(freq=60) self.delay_timer = Timer(freq=60) self.cpu = Cpu(self.memory, None, delay_timer=self.delay_timer, sound_timer=self.sound_timer)
def __init__(self, memory, display, delay_timer, sound_timer): self._memory = memory self._display = display self._delay_timer = delay_timer self._sound_timer = sound_timer self._v = [Register(8) for i in range(0, 0x10)] # 0xF + 1 self._i = Register(16) self._pc = 0x0 self._stack = Memory(12, cell_bit_size=16) self._sp = 0 self._standard_ops = { 0x1: self._jump_to_address, 0x2: self._call_subroutine, 0x3: self._skip_if_reg_equal_const, 0x4: self._skip_if_reg_not_equal_const, 0x5: self._skip_if_reg_equal_reg, 0x6: self._set_reg_to_const, 0x7: self._add_const_to_reg, 0x9: self._skip_if_reg_not_equal_reg, 0xA: self._set_i_to_address, 0xB: self._jump_to_address_plus_v0, 0xC: self._set_reg_to_xor_rand_and_const, 0xD: self._draw_sprite, 0xE: self._skip_on_key_press_event, } self._extended_ops_decode = { 0x0: self._decode_0_ops, 0x8: self._decode_8_ops, 0xF: self._decode_F_ops } self._8_ops = { 0x0: self._mov_reg_to_reg, 0x1: self._bitwise_or, 0x2: self._bitwise_and, 0x3: self._bitwise_xor, 0x4: self._add_reg_to_reg, 0x5: self._sub_reg_to_reg, 0x6: self._right_shift, 0x7: self._sub_reg_to_reg_inv, 0xE: self._left_shift, } self._F_ops = { 0x07: self._mov_delay_to_reg, 0x0A: self._set_delay_to_reg, 0x15: self._set_sound_to_reg, 0x1E: self._add_reg_to_i, 0x29: self._mov_reg_sprite_addr_to_i, 0x33: self._mov_reg_to_bcd, 0x55: self._dump_regs, 0x65: self._load_regs }
def __init__(self): super().__init__() self.memory = Memory() self.setupUi(self) self.scan_byte_size.insertItems(0, [str(t) for t in Type]) self.scan_byte_size.setCurrentIndex(Type.UINT32.value) self.scan_widget.setEnabled(False) self.found_table.setModel(FoundAddressModel(self)) self.found_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.new_scan.clicked.connect(self.new_scan_clicked) 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) self.search_for.setValidator(QIntValidator(self)) self.scan_byte_size.currentIndexChanged.connect(self.type_changed)
def __init__(self): self._memory = Memory(0x1000) self._display = Display(64, 32) self._delay_timer = Timer(freq=60) self._sound_timer = Timer(freq=60) self._sound = Sound(self._sound_timer) self._cpu = Cpu(self._memory, self._display, delay_timer=self._delay_timer, sound_timer=self._sound_timer) self._fps_time = datetime.now() pygame.init()
def test_memory_out_of_bounds(self): m = Memory(32) self.assertRaises(IndexError, m.__getitem__, 32) self.assertRaises(IndexError, m.__getitem__, -1)
def test_memory_seeting_value_to_big(self): m = Memory(8, cell_bit_size=8) self.assertRaises(OverflowError, m.__setitem__, 0, 0xFFF)
def test_memory_setting_value(self): m = Memory(8) m[0] = 0xFF self.assertEqual(m[0], 0xFF)
class Dvm: mem = None opcodes = Opcodes() reservation = ReserverdBytes() stats = None vcpu = vCPU() vcpuloop = 0 vminstruction = 0 start_time = time.time() def __init__(self, path=None): self.stats = self.vm_exec if path is not None and path != "": self._load(path) def _load(self, path): bc = file(path, "rb").read() self.mem = Memory(bc) def _single_step(self): params = [] instruction = self.mem.ram[self.mem.bp] self.mem.inc_bp(1) for inst in self.opcodes.ops: self.vcpuloop += 1 if instruction == int(self.opcodes.ops[inst]): has_param = self.opcodes.ops_size[instruction] has_reservation = 0 if instruction in self.opcodes.ops_reservation: has_reservation = self.reservation.reserved[self.opcodes.ops_reservation[instruction]] for param in range(0, has_param): if has_reservation: if (has_reservation == 0x0f and param == range(0, has_param)[0]) or \ (has_reservation == 0x01 and param == range(0, has_param)[-1]): tmp = "" while self.mem.ram[self.mem.bp] != 0x00: tmp += chr(self.mem.ram[self.mem.bp]) self.mem.inc_bp(1) params.append(tmp+"\x00") self.mem.inc_bp(1) else: params.append(self.mem.ram[self.mem.bp]) self.mem.inc_bp(1) self.vminstruction += 1 return self._process_instruction(self.mem, instruction, params) raise VMUnsupportedInstruction(instruction) def _process_instruction(self, vm, inst, args): try: return self.vcpu.ops_func[inst](vm, args) except KeyError: raise VMNotImplementedInstruction(inst) def vm_exec(self): while self._single_step(): pass def vm_exec_mem(self, bytecode): self.mem = Memory(bytecode) self.vm_exec() def vm_exec_stats(self): tracer = trace.Trace( ignoredirs=[sys.prefix, sys.exec_prefix], trace=0, count=1) tracer.run('VM.stats()') r = tracer.results() instructions = 0 for c in r.counts: if "memory.py" not in c[0]: instructions += r.counts[c] print "\nStats:\n[+] vCPU instructions: %s\n[+] VM loops: %s\n[+] VM exec instructions: %s\n[+] Exec time: %.3f secs" % \ (instructions, self.vcpuloop, self.vminstruction, time.time()-self.start_time)
def vm_exec_mem(self, bytecode): self.mem = Memory(bytecode) self.vm_exec()
def setUp(self) -> None: self.memory = Memory() # just attach to own process, we're overriding the read values anyway self.memory.process = psutil.Process()
class MemoryTest(unittest.TestCase): def setUp(self) -> None: self.memory = Memory() # just attach to own process, we're overriding the read values anyway self.memory.process = psutil.Process() @patch.object(psutil.Process, "memory_maps", autospec=True) @patch.object(Memory, "read", autospec=True) def test_scan(self, read_mock: Mock, mem_map_mock: Mock): read_mock.side_effect = [123, 123] mem_map_mock.return_value = [InternalMmap("0-8", 8, "r--w")] self.assertEqual(self.memory.scan("123"), [Value(0, 0, 123), Value(0, 4, 123)]) @patch.object(psutil.Process, "memory_maps", autospec=True) @patch.object(Memory, "read", autospec=True) def test_scan_empty_search(self, read_mock: Mock, mem_map_mock: Mock): read_mock.side_effect = [123, 123] mem_map_mock.return_value = [InternalMmap("0-8", 8, "r--w")] def test_scan_cull_empty(self): self.assertEqual(self.memory._scan_cull(Value(0, 0, 123)), []) def test_scan_cull(self): maps = [InternalMmap("0-32", 32, "r--w")] # 15 because 32/4 = 8, since we need twice the scan area, we have a total of 16, then we # append a false value too to make sure the filtering works packed = [Value(0, 0, 123)] * 15 packed.append(Value(0, 0, 12)) with patch.object(Memory, "read", side_effect=packed), \ patch("builtins.open", mock_open()), \ patch("psutil.Process.__init__", return_value=None), \ patch("psutil.Process.memory_maps", return_value=maps): self.memory.attach(123) self.assertEqual(len(self.memory.scan(123)), 8) self.assertEqual(len(self.memory.scan(123)), 7) def test_attach(self): with patch("builtins.open", mock_open()), patch("psutil.Process.__init__", return_value=None): self.memory.attach(123) self.assertEqual(self.memory.pid, 123) def test_detach(self): with patch("builtins.open", mock_open()), patch("psutil.Process.__init__", return_value=None): self.memory.attach(123) self.memory.detach() self.assertEqual(self.memory.pid, 0)
def vm_exec_mem(self, bytecode): self.mem = Memory(bytecode) self.vm_exec()
def _load(self, path): bc = file(path, "rb").read() self.mem = Memory(bc)
class Dvm: mem = None opcodes = Opcodes() reservation = ReserverdBytes() stats = None vcpu = vCPU() vcpuloop = 0 vminstruction = 0 start_time = time.time() def __init__(self, path=None): self.stats = self.vm_exec if path is not None and path != "": self._load(path) def _load(self, path): bc = file(path, "rb").read() self.mem = Memory(bc) def _single_step(self): params = [] instruction = self.mem.ram[self.mem.bp] self.mem.inc_bp(1) for inst in self.opcodes.ops: self.vcpuloop += 1 if instruction == int(self.opcodes.ops[inst]): has_param = self.opcodes.ops_size[instruction] has_reservation = 0 if instruction in self.opcodes.ops_reservation: has_reservation = self.reservation.reserved[ self.opcodes.ops_reservation[instruction]] for param in range(0, has_param): if has_reservation: if (has_reservation == 0x0f and param == range(0, has_param)[0]) or \ (has_reservation == 0x01 and param == range(0, has_param)[-1]): tmp = "" while self.mem.ram[self.mem.bp] != 0x00: tmp += chr(self.mem.ram[self.mem.bp]) self.mem.inc_bp(1) params.append(tmp + "\x00") self.mem.inc_bp(1) else: params.append(self.mem.ram[self.mem.bp]) self.mem.inc_bp(1) self.vminstruction += 1 return self._process_instruction(self.mem, instruction, params) raise VMUnsupportedInstruction(instruction) def _process_instruction(self, vm, inst, args): try: return self.vcpu.ops_func[inst](vm, args) except KeyError: raise VMNotImplementedInstruction(inst) def vm_exec(self): while self._single_step(): pass def vm_exec_mem(self, bytecode): self.mem = Memory(bytecode) self.vm_exec() def vm_exec_stats(self): tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], trace=0, count=1) tracer.run('VM.stats()') r = tracer.results() instructions = 0 for c in r.counts: if "memory.py" not in c[0]: instructions += r.counts[c] print "\nStats:\n[+] vCPU instructions: %s\n[+] VM loops: %s\n[+] VM exec instructions: %s\n[+] Exec time: %.3f secs" % \ (instructions, self.vcpuloop, self.vminstruction, time.time()-self.start_time)
def test_memory_initialization(self): m = Memory(32) for i in range(0, 32): self.assertEqual(m[i], 0x0)
def _load(self, path): bc = file(path, "rb").read() self.mem = Memory(bc)
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.memory = Memory() self.setupUi(self) self.scan_byte_size.insertItems(0, [str(t) for t in Type]) self.scan_byte_size.setCurrentIndex(Type.UINT32.value) self.scan_widget.setEnabled(False) self.found_table.setModel(FoundAddressModel(self)) self.found_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.new_scan.clicked.connect(self.new_scan_clicked) 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) self.search_for.setValidator(QIntValidator(self)) self.scan_byte_size.currentIndexChanged.connect(self.type_changed) @pyqtSlot(int) def type_changed(self, index): int_validator = QIntValidator(self) double_validator = QRegExpValidator(QRegExp(r"-?[0-9]*[\.\,]?[0-9]*")) type_to_validator = {Type.UINT8: int_validator, Type.UINT16: int_validator, Type.UINT32: int_validator, Type.UINT64: int_validator, Type.FLOAT: double_validator, Type.DOUBLE: double_validator} self.search_for.setValidator(type_to_validator[Type(index)]) @pyqtSlot() def new_scan_clicked(self): if self.next_scan.isEnabled(): self.next_scan.setEnabled(False) self.found_table.model().set_values([]) self.memory.reset_scan() else: self.next_scan_clicked() self.next_scan.setEnabled(True) @pyqtSlot() def next_scan_clicked(self): # TODO: fix looking for negative values, probably have to fiddle with the type system try: scan_type = {0: operator.eq, 1: operator.gt, 2: operator.lt, 3: operator.ne} match_index = self.scan_matching.currentIndex() type_ = Type(self.scan_byte_size.currentIndex()) # since floating points are annoying we have to use isclose, I kinda wanna make # it configureable though but for now it will have to do if type_ == Type.FLOAT or type_ == Type.DOUBLE: scan_type[1] = math.isclose values = self.memory.scan(self.search_for.text(), type_, scan_type[match_index]) self.amount_found.setText("Found: {}".format(len(values))) self.found_table.model().set_values(values) except NoSuchProcess: QMessageBox(QMessageBox.NoIcon, "Error", "No readable memory", QMessageBox.Ok, self).exec_() @pyqtSlot() def attach_triggered(self): process_view = ProcessView() pid = process_view.exec_() if pid != 0: self.memory.attach(pid) self.scan_widget.setEnabled(True) @pyqtSlot(QModelIndex) def found_table_double_clicked(self, index: QModelIndex): if not index.isValid(): 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_()