示例#1
0
 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)
示例#2
0
    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
        }
示例#3
0
    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)
示例#4
0
    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()
示例#5
0
    def test_memory_out_of_bounds(self):
        m = Memory(32)

        self.assertRaises(IndexError, m.__getitem__, 32)
        self.assertRaises(IndexError, m.__getitem__, -1)
示例#6
0
 def test_memory_seeting_value_to_big(self):
     m = Memory(8, cell_bit_size=8)
     self.assertRaises(OverflowError, m.__setitem__, 0, 0xFFF)
示例#7
0
    def test_memory_setting_value(self):
        m = Memory(8)

        m[0] = 0xFF

        self.assertEqual(m[0], 0xFF)
示例#8
0
文件: vm.py 项目: dzonerzy/dvm
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)
示例#9
0
文件: vm.py 项目: dzonerzy/dvm
 def vm_exec_mem(self, bytecode):
     self.mem = Memory(bytecode)
     self.vm_exec()
示例#10
0
 def setUp(self) -> None:
     self.memory = Memory()
     # just attach to own process, we're overriding the read values anyway
     self.memory.process = psutil.Process()
示例#11
0
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)
示例#12
0
文件: vm.py 项目: dzonerzy/dvm
 def vm_exec_mem(self, bytecode):
     self.mem = Memory(bytecode)
     self.vm_exec()
示例#13
0
文件: vm.py 项目: dzonerzy/dvm
 def _load(self, path):
     bc = file(path, "rb").read()
     self.mem = Memory(bc)
示例#14
0
文件: vm.py 项目: dzonerzy/dvm
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)
示例#15
0
    def test_memory_initialization(self):
        m = Memory(32)

        for i in range(0, 32):
            self.assertEqual(m[i], 0x0)
示例#16
0
文件: vm.py 项目: dzonerzy/dvm
 def _load(self, path):
     bc = file(path, "rb").read()
     self.mem = Memory(bc)
示例#17
0
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_()