Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add De Brujin fuzzing #782

Merged
merged 7 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
801 changes: 475 additions & 326 deletions data/ui/fuzzing.ui

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions src/urh/controller/GeneratorTabController.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,9 +441,14 @@ def show_fuzzing_dialog(self, label_index: int):
fdc = FuzzingDialog(protocol=self.table_model.protocol, label_index=label_index,
msg_index=msg_index, proto_view=view, parent=self)
fdc.show()
fdc.finished.connect(self.refresh_label_list)
fdc.finished.connect(self.refresh_table)
fdc.finished.connect(self.set_fuzzing_ui_status)
fdc.finished.connect(self.on_fuzzing_dialog_finished)

@pyqtSlot()
def on_fuzzing_dialog_finished(self):
self.refresh_label_list()
self.refresh_table()
self.set_fuzzing_ui_status()
self.ui.tabWidget.setCurrentIndex(2)

@pyqtSlot()
def handle_plabel_fuzzing_state_changed(self):
Expand Down
29 changes: 15 additions & 14 deletions src/urh/controller/dialogs/FuzzingDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@


class FuzzingDialog(QDialog):
def __init__(self, protocol: ProtocolAnalyzerContainer, label_index: int, msg_index: int, proto_view: int, parent=None):
def __init__(self, protocol: ProtocolAnalyzerContainer, label_index: int, msg_index: int, proto_view: int,
parent=None):
super().__init__(parent)
self.ui = Ui_FuzzingDialog()
self.ui.setupUi(self)
Expand Down Expand Up @@ -113,9 +114,7 @@ def create_connects(self):
self.ui.spinBoxRandomMinimum.valueChanged.connect(self.on_random_range_min_changed)
self.ui.spinBoxRandomMaximum.valueChanged.connect(self.on_random_range_max_changed)
self.ui.spinBoxFuzzMessage.valueChanged.connect(self.on_fuzz_msg_changed)
self.ui.btnAddRange.clicked.connect(self.on_btn_add_range_clicked)
self.ui.btnAddBoundaries.clicked.connect(self.on_btn_add_boundaries_clicked)
self.ui.btnAddRandom.clicked.connect(self.on_btn_add_random_clicked)
self.ui.btnAddFuzzingValues.clicked.connect(self.on_btn_add_fuzzing_values_clicked)
self.ui.comboBoxFuzzingLabel.editTextChanged.connect(self.set_current_label_name)

def update_message_data_string(self):
Expand Down Expand Up @@ -245,11 +244,9 @@ def on_fuzzing_range_end_changed(self, value: int):
def on_lower_bound_checked_changed(self):
if self.ui.checkBoxLowerBound.isChecked():
self.ui.spinBoxLowerBound.setEnabled(True)
self.ui.btnAddBoundaries.setEnabled(True)
self.ui.spinBoxBoundaryNumber.setEnabled(True)
elif not self.ui.checkBoxUpperBound.isChecked():
self.ui.spinBoxLowerBound.setEnabled(False)
self.ui.btnAddBoundaries.setEnabled(False)
self.ui.spinBoxBoundaryNumber.setEnabled(False)
else:
self.ui.spinBoxLowerBound.setEnabled(False)
Expand All @@ -258,11 +255,9 @@ def on_lower_bound_checked_changed(self):
def on_upper_bound_checked_changed(self):
if self.ui.checkBoxUpperBound.isChecked():
self.ui.spinBoxUpperBound.setEnabled(True)
self.ui.btnAddBoundaries.setEnabled(True)
self.ui.spinBoxBoundaryNumber.setEnabled(True)
elif not self.ui.checkBoxLowerBound.isChecked():
self.ui.spinBoxUpperBound.setEnabled(False)
self.ui.btnAddBoundaries.setEnabled(False)
self.ui.spinBoxBoundaryNumber.setEnabled(False)
else:
self.ui.spinBoxUpperBound.setEnabled(False)
Expand All @@ -288,14 +283,21 @@ def on_random_range_max_changed(self):
self.ui.spinBoxRandomMinimum.setMaximum(self.ui.spinBoxRandomMaximum.value() - 1)

@pyqtSlot()
def on_btn_add_range_clicked(self):
def on_btn_add_fuzzing_values_clicked(self):
if self.ui.comboBoxStrategy.currentIndex() == 0:
self.__add_fuzzing_range()
elif self.ui.comboBoxStrategy.currentIndex() == 1:
self.__add_fuzzing_boundaries()
elif self.ui.comboBoxStrategy.currentIndex() == 2:
self.__add_random_fuzzing_values()

def __add_fuzzing_range(self):
start = self.ui.sBAddRangeStart.value()
end = self.ui.sBAddRangeEnd.value()
step = self.ui.sBAddRangeStep.value()
self.fuzz_table_model.add_range(start, end + 1, step)

@pyqtSlot()
def on_btn_add_boundaries_clicked(self):
def __add_fuzzing_boundaries(self):
lower_bound = -1
if self.ui.spinBoxLowerBound.isEnabled():
lower_bound = self.ui.spinBoxLowerBound.value()
Expand All @@ -307,8 +309,7 @@ def on_btn_add_boundaries_clicked(self):
num_vals = self.ui.spinBoxBoundaryNumber.value()
self.fuzz_table_model.add_boundaries(lower_bound, upper_bound, num_vals)

@pyqtSlot()
def on_btn_add_random_clicked(self):
def __add_random_fuzzing_values(self):
n = self.ui.spinBoxNumberRandom.value()
minimum = self.ui.spinBoxRandomMinimum.value()
maximum = self.ui.spinBoxRandomMaximum.value()
Expand Down Expand Up @@ -354,7 +355,7 @@ def on_fuzz_msg_changed(self, index: int):
@pyqtSlot()
def on_btn_repeat_values_clicked(self):
num_repeats, ok = QInputDialog.getInt(self, self.tr("How many times shall values be repeated?"),
self.tr("Number of repeats:"), 1, 1)
self.tr("Number of repeats:"), 1, 1)
if ok:
self.ui.chkBRemoveDuplicates.setChecked(False)
min_row, max_row, _, _ = self.ui.tblFuzzingValues.selection_range()
Expand Down
41 changes: 40 additions & 1 deletion src/urh/cythonext/util.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ from cython.parallel import prange
from libc.math cimport log10,pow
from libcpp cimport bool

from cpython cimport array
import array

from urh.cythonext.util cimport iq

cpdef tuple minmax(iq[:] arr):
Expand Down Expand Up @@ -287,4 +290,40 @@ cpdef tuple get_crc_datarange(uint8_t[:] inpt, uint8_t[:] polynomial, uint64_t v
# No beginning found
return 0, 0
finally:
free(steps)
free(steps)

cdef db(unsigned int t, unsigned int p, unsigned int k, unsigned int n,
uint8_t* a, uint8_t* sequence, uint64_t* current_index):
cdef unsigned int i,j

if t > n:
if n % p == 0:
for i in range(1, p+1):
sequence[current_index[0]] = a[i]
current_index[0] += 1
else:
a[t] = a[t - p]
db(t + 1, p, k, n, a, sequence, current_index)
for j in range(a[t - p] + 1, k):
a[t] = j
db(t+1, t, k, n, a, sequence, current_index)

cpdef array.array de_bruijn(unsigned int n):
cdef unsigned int k = 2 # Alphabet size is 2 because our alphabet is [0, 1]
cdef uint64_t len_sequence = k ** n

cdef uint8_t* a = <uint8_t*>calloc(k*n, sizeof(uint8_t))

cdef array.array array_template = array.array('B', [])
cdef array.array sequence
sequence = array.clone(array_template, len_sequence, zero=False)

cdef uint64_t* current_index = <uint64_t*>calloc(1, sizeof(uint64_t))

db(1, 1, k, n, a, sequence.data.as_uchars, current_index)

try:
return sequence
finally:
free(a)
free(current_index)
22 changes: 22 additions & 0 deletions src/urh/models/GeneratorTableModel.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import array
import time
from collections import defaultdict

from PyQt5.QtCore import Qt, QModelIndex, pyqtSlot, pyqtSignal
Expand Down Expand Up @@ -139,6 +140,27 @@ def add_empty_row_behind(self, row_index: int, num_bits: int):
undo_action = InsertBitsAndPauses(self.protocol, row_index+1, tmp_protocol)
self.undo_stack.push(undo_action)

def generate_de_bruijn(self, row_index: int, start: int, end: int):
if start < 0 or end < 0:
return

f = 1 if self.proto_view == 0 else 4 if self.proto_view == 1 else 8
start, end = f * start, f * end

de_bruijn_seq = util.de_bruijn(end-start)

tmp_protocol = ProtocolAnalyzer(None)
tmp_protocol.messages = []
LINE_BREAK_AFTER = 5000 * f
for i in range(0, len(de_bruijn_seq), LINE_BREAK_AFTER):
message = Message(plain_bits=de_bruijn_seq[i:i+LINE_BREAK_AFTER],
pause=0,
message_type=self.protocol.default_message_type)
tmp_protocol.messages.append(message)

undo_action = InsertBitsAndPauses(self.protocol, row_index+1, tmp_protocol)
self.undo_stack.push(undo_action)

def __set_italic_font_for_label_range(self, row, label, italic: bool):
message = self.protocol.messages[row]
for j in range(*message.get_label_range(lbl=label, view=self.proto_view, decode=False)):
Expand Down
Loading