Skip to content

Commit

Permalink
push
Browse files Browse the repository at this point in the history
  • Loading branch information
iGio90 committed Jul 19, 2019
0 parents commit f5f2aad
Show file tree
Hide file tree
Showing 11 changed files with 2,171 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
__pycache__
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions README.md
@@ -0,0 +1,39 @@
## ucdwarf

integrate unicorn emulator into dwarf.

### Installation

```
cd %Dwarf%/plugins/
git clone https://github.com/iGio90/ucdwarf
~~~
# make sure unicorn is installed:
pip3 install unicorn
```

### Features

* panel with emulator and console
* visual widgets for executed instructions, registers and memory accesses
* options

```
Dwarf - Copyright (C) 2019 Giovanni Rocca (iGio90)
This program 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.
This program 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 this program. If not, see <https://www.gnu.org/licenses/>
```
38 changes: 38 additions & 0 deletions agent.js
@@ -0,0 +1,38 @@
function Emulator() {
this.clean = function () {
loggedSend('emulator:::clean')
};

this.setup = function (tid, arch, mode) {
if (typeof tid !== 'number') {
tid = Process.getCurrentThreadId();
}
var msg = 'emulator:::setup:::' + tid;
if (isDefined(arch) && isDefined(mode)) {
msg += ':::' + arch + ':::' + mode;
}
loggedSend(msg)
};

this.start = function (until) {
loggedSend('emulator:::start:::' + until)
};

this.step = function () {
loggedSend('emulator:::step:::1')
};

this.stepFunction = function () {
loggedSend('emulator:::step:::2')
};

this.stepJump = function () {
loggedSend('emulator:::step:::3')
};

this.stop = function () {
loggedSend('emulator:::stop')
};
}

global.emulator = new Emulator();
131 changes: 131 additions & 0 deletions plugin.py
@@ -0,0 +1,131 @@
"""
Dwarf - Copyright (C) 2019 Giovanni Rocca (iGio90)
This program 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.
This program 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 this program. If not, see <https://www.gnu.org/licenses/>
"""
import os

from PyQt5.QtCore import QObject, pyqtSignal

from plugins.ucdwarf.src.emulator import Emulator, EmulatorThread
from plugins.ucdwarf.src.emulator_context_widget import EmulatorContextList
from ui.widget_console import DwarfConsoleWidget


EMULATOR_CALLBACKS_PATH = 'emulator_callbacks_path'
EMULATOR_INSTRUCTIONS_DELAY = 'emulator_instructions_delay'


class Plugin(QObject):
onEmulatorApi = pyqtSignal(list, name='onEmulatorApi')

@staticmethod
def __get_plugin_info__():
return {
'name': 'ucdwarf',
'description': 'unicorn emulator in Dwarf',
'version': '1.0.0',
'author': 'iGio90',
'homepage': 'https://github.com/iGio90/ucdwarf',
'license': 'https://www.gnu.org/licenses/gpl-3.0',
}

def __get_top_menu_actions__(self):
return []

def __get_agent__(self):
self.app.dwarf.onReceiveCmd.connect(self._on_receive_cmd)

with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'agent.js'), 'r') as f:
return f.read()

def __init__(self, app):
super().__init__()
self.app = app

self.console = None
self.emulator_panel = None
self.emulator = None
self._emu_queue = []
self._emu_thread = None

self.app.session_manager.sessionCreated.connect(self._on_session_created)
self.app.session_manager.sessionStopped.connect(self._on_session_stopped)
self.app.onUIElementCreated.connect(self._on_ui_element_created)

def _on_session_created(self):
self.emulator = Emulator(self.app.dwarf)
self._emu_thread = EmulatorThread(self)
self._emu_thread.onCmdCompleted.connect(self._on_emu_completed)
self._emu_thread.onError.connect(self._on_emu_error)
self._emu_thread.emulator = self.emulator

self.onEmulatorApi.connect(self._on_emulator_api)

self.create_widget()

def _on_session_stopped(self):
pass

def _on_receive_cmd(self, args):
message, data = args
if 'payload' in message:
what = message['payload']
parts = what.split(':::')
if len(parts) < 2:
return

cmd = parts[0]
if cmd == 'emulator':
self.onEmulatorApi.emit(parts[1:])

def _on_emulator_api(self, data):
if self.emulator and self._emu_thread:
if not self._emu_thread.isRunning():
self._emu_thread.cmd = data
self._emu_thread.start()
else:
self._emu_queue.append(data)

def _on_emu_completed(self, result):
self.log(result) # todo: send back to script???
if self._emu_queue:
self._emu_thread.cmd = self._emu_queue[0]
self._emu_queue = self._emu_queue[1:]
self._emu_thread.start()
else:
self._emu_thread.cmd = ''

def _on_emu_error(self, err_str):
self.log(err_str)
if self._emu_queue:
self._emu_queue.clear()

def _on_ui_element_created(self, elem, widget):
if elem == 'console':
self.console = DwarfConsoleWidget(self.app, has_input=False)
widget.qtabs.addTab(self.console, 'emulator')
elif elem == 'registers':
self.context_widget = widget
self.emulator_context_widget = EmulatorContextList(self.context_widget)
self.context_widget.addTab(self.emulator_context_widget, 'emulator')

def create_widget(self):
from plugins.ucdwarf.src.panel_emulator import EmulatorPanel
self.emulator_panel = EmulatorPanel(self)
self.app.main_tabs.addTab(self.emulator_panel, 'Emulator')
return self.emulator_panel

def log(self, what):
self.console.log(str(what))
76 changes: 76 additions & 0 deletions src/dialog_emulator_configs.py
@@ -0,0 +1,76 @@
"""
Dwarf - Copyright (C) 2019 Giovanni Rocca (iGio90)
This program 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.
This program 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 this program. If not, see <https://www.gnu.org/licenses/>
"""
from PyQt5.QtWidgets import *

from lib import prefs
from lib.prefs import Prefs
from plugins.ucdwarf.plugin import EMULATOR_INSTRUCTIONS_DELAY, EMULATOR_CALLBACKS_PATH


class EmulatorConfigsDialog(QDialog):
def __init__(self, dwarf, parent=None):
super(EmulatorConfigsDialog, self).__init__(parent)
self.dwarf = dwarf
self._prefs = Prefs()

layout = QVBoxLayout(self)

self.setMinimumWidth(500)

layout.addWidget(QLabel('callbacks path'))
callbacks_layout = QHBoxLayout()
pick_path = QPushButton('choose')
pick_path.clicked.connect(self.pick_callbacks_path)
current_callbacks_path = self._prefs.get(EMULATOR_CALLBACKS_PATH)
if current_callbacks_path == '':
current_callbacks_path = 'none'
self.callbacks_path_label = QLabel(current_callbacks_path)
callbacks_layout.addWidget(pick_path)
callbacks_layout.addWidget(self.callbacks_path_label)
layout.addLayout(callbacks_layout)

layout.addWidget(QLabel('delay between instructions'))
self.instructions_delay = QLineEdit()
self.instructions_delay.setText(str(self._prefs.get(EMULATOR_INSTRUCTIONS_DELAY, 0.5)))
layout.addWidget(self.instructions_delay)

buttons = QHBoxLayout()
cancel = QPushButton('cancel')
cancel.clicked.connect(self.close)
buttons.addWidget(cancel)
accept = QPushButton('accept')
accept.clicked.connect(self.accept)
buttons.addWidget(accept)

layout.addLayout(buttons)

def pick_callbacks_path(self):
r = QFileDialog.getOpenFileName()
if len(r) > 0 and len(r[0]) > 0:
self._prefs.put(EMULATOR_CALLBACKS_PATH, r[0])
self.callbacks_path_label.setText(r[0])

@staticmethod
def show_dialog(dwarf):
dialog = EmulatorConfigsDialog(dwarf)
result = dialog.exec_()

if result == QDialog.Accepted:
try:
dialog._prefs.put(EMULATOR_INSTRUCTIONS_DELAY, float(dialog.instructions_delay.text()))
except:
pass

0 comments on commit f5f2aad

Please sign in to comment.