Showing preview only (452K chars total). Download the full file or copy to clipboard to get everything.
Repository: yakuza8/peniot
Branch: master
Commit: fd1c644653a7
Files: 116
Total size: 418.4 KB
Directory structure:
gitextract_1myw_xe2/
├── .gitignore
├── LICENSE
├── README.md
├── setup.py
└── src/
├── Entity/
│ ├── __init__.py
│ ├── attack.py
│ ├── attack_suite.py
│ ├── input_format.py
│ └── protocol.py
├── GUI/
│ ├── __init__.py
│ ├── custom_widgets.py
│ ├── hard_coded_texts.py
│ ├── tkinter.py
│ └── utils.py
├── Utils/
│ ├── CommonUtil/
│ │ └── __init__.py
│ ├── ExtendUtil/
│ │ ├── __init__.py
│ │ ├── export_attack_suite_template.py
│ │ ├── export_attack_template.py
│ │ ├── export_protocol_template.py
│ │ ├── export_util.py
│ │ └── import_util.py
│ ├── FilterUtil/
│ │ ├── __init__.py
│ │ └── pyshark_filter_util.py
│ ├── FuzzerUtil/
│ │ ├── __init__.py
│ │ └── radamsa_util.py
│ ├── RandomUtil/
│ │ ├── __init__.py
│ │ └── random_generated_names.py
│ ├── ReportUtil/
│ │ ├── __init__.py
│ │ └── report_generator.py
│ ├── SnifferUtil/
│ │ ├── __init__.py
│ │ └── generic_sniffer.py
│ └── __init__.py
├── __init__.py
├── captured_packets/
│ └── __init__.py
├── module_installer.py
├── peniot.py
└── protocols/
├── AMQP/
│ ├── __init__.py
│ ├── amqp_protocol.py
│ ├── amqp_scanner.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── amqp_dos_attack.py
│ │ ├── amqp_fuzzing_attack_suite.py
│ │ ├── amqp_payload_size_fuzzer.py
│ │ └── amqp_random_payload_fuzzing.py
│ └── examples/
│ ├── __init__.py
│ ├── receiver_example.py
│ └── sender_example.py
├── BLE/
│ ├── Adafruit_BLESniffer/
│ │ ├── .gitignore
│ │ ├── API Manifest.txt
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── SnifferAPI/
│ │ │ ├── CaptureFiles.py
│ │ │ ├── Devices.py
│ │ │ ├── Exceptions.py
│ │ │ ├── Logger.py
│ │ │ ├── Notifications.py
│ │ │ ├── Packet.py
│ │ │ ├── Sniffer.py
│ │ │ ├── SnifferCollector.py
│ │ │ ├── UART.py
│ │ │ ├── Version.py
│ │ │ ├── __init__.py
│ │ │ └── myVersion.py
│ │ ├── __init__.py
│ │ ├── documentation.html
│ │ ├── requirements.txt
│ │ ├── setup.cfg
│ │ ├── sniffer.py
│ │ ├── sniffer_uart_protocol.xlsx
│ │ └── wireshark_dissector_source/
│ │ ├── OSX/
│ │ │ └── readme.md
│ │ ├── packet-btle.c
│ │ └── packet-nordic_ble.c
│ ├── BLETest.py
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── ble_replay_attack.py
│ │ └── ble_sniff_attack.py
│ ├── ble_advertiser.py
│ ├── ble_device.py
│ ├── ble_protocol.py
│ ├── ble_replay_attack.py
│ ├── ble_sniff.py
│ └── ble_tools.py
├── CoAP/
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── coap_dos_attack.py
│ │ ├── coap_fuzzing_attack_suite.py
│ │ ├── coap_payload_size_fuzzer.py
│ │ ├── coap_random_payload_fuzzing.py
│ │ ├── coap_replay_attack.py
│ │ └── coap_sniff_attack.py
│ ├── coap_protocol.py
│ ├── coap_scanner.py
│ └── examples/
│ ├── __init__.py
│ ├── client_example.py
│ ├── resource_example.py
│ └── server_example.py
├── MQTT/
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── mqtt_dos_attack.py
│ │ ├── mqtt_fuzzing_attack_suite.py
│ │ ├── mqtt_generation_based_fuzzing.py
│ │ ├── mqtt_payload_size_fuzzer.py
│ │ ├── mqtt_random_payload_fuzzing.py
│ │ ├── mqtt_replay_attack.py
│ │ ├── mqtt_sniff_attack.py
│ │ └── mqtt_topic_name_fuzzing.py
│ ├── examples/
│ │ ├── Demo/
│ │ │ ├── __init__.py
│ │ │ ├── demo_publisher.py
│ │ │ └── demo_subscriber.py
│ │ ├── __init__.py
│ │ ├── publisher_example.py
│ │ └── subscriber_example.py
│ ├── mqtt_protocol.py
│ └── mqtt_scanner.py
└── __init__.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# IntelliJ
.idea/
/out/
src/logging.conf
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Berat Cankar, Bigehan Bingöl, Doğukan Çavdaroğlu, Ebru Çelebi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# PENIOT: Penetration Testing Tool for IoT
#### Table of Contents
* [Project Description](#Project-Description)
* [What is PENIOT?](#What-is-PENIOT)
* [Why is PENIOT required?](#Why-is-PENIOT-required)
* [What does PENIOT provide?](#What-does-PENIOT-provide)
* [Build Instructions](#Build-Instructions)
* [Documentation](#Documentation)
* [Testing](#Testing)
* [Contributors](#Contributors)
* [Developer's Note](#Developers-Note)
* [Project Poster](#Project-Poster)
## Project Description
### What is PENIOT?
[PENIOT](https://senior.ceng.metu.edu.tr/2019/peniot/) is a penetration testing tool for Internet of Things (IoT) devices.
It helps you to test/penetrate your devices by targeting their internet connectivity
with different types of security attacks. In other words, you can expose your device
to both active and passive security attacks. After deciding target device and necessary
information (or parameters) of that device, you can perform active security attacks like
altering/consuming system resources, replaying valid communication units and so on.
Also, you can perform passive security attacks such as breaching of confidentiality of
important information or reaching traffic analysis. Thanks to PENIOT, all those operations
can be semi-automated or even fully automated. In short, PENIOT is a package/framework for
targeting IoT devices with protocol based security attacks.
Also, it gives you a baseline structure for your further injections of new security attacks
or new IoT protocols. One of the most important features of PENIOT is being extensible.
By default, it has several common IoT protocols and numerous security attacks related to
those protocols. But, it can be extended further via exporting basic structure of internally
used components so that you can develop your attacks in harmony with the internal structure
of the PENIOT.
### Why is PENIOT required?
The IoT paradigm has experienced immense growth in the past decade, with billions of devices
connected to the Internet. Most of these devices lack even basic security measures due to
their capacity constraints and designs made without security in mind due to the shortness
of time-to-market. Due to the high connectivity in IoT, attacks that have devastating
effects in extended networks can easily be launched by hackers through vulnerable devices.
Up until now, penetration testing was done manually if it was not ignored at all.
This procedure made testing phase of devices very slow. On the other hand, the firms which
produce IoT devices should always be up to date on testing their devices in terms of
reliability, robustness as well as their provided functionalities since being exposed to
security attacks by malicious people could cause unexpected impacts on end-users.
The main aim of PENIOT is to accelerate the process of security testing. It enables you to
figure out security flaws on your IoT devices by automating the time consuming penetration
testing phase.
### What does PENIOT provide?
First of all, PENIOT provides novelty. It is one of the first examples of penetration testing
tools on IoT field. There are only one or two similar tools which are specialized on IoT,
but they are still on development phase, so not completed yet.
Since the number of IoT devices is increasing drastically, IoT devices become more and more
common in our daily life. Smart homes, smart bicycles, medical sensors, fitness trackers,
smart locks and connected factories are just a few examples of IoT products. Given this,
we felt the need to choose some of the most commonly used IoT protocols to plant into PENIOT
by default. We chose the following protcols as the default IoT protocols included in the
PENIOT. These IoT protocols are tested with various types of security attacks such as DoS,
Fuzzing, Sniffing and Replay attacks.
Following protocols are currently supported:
* Advanced Message Queuing Protocol ([AMQP](https://www.amqp.org/))
* Bluetooth Low Energy ([BLE](https://www.bluetooth.com/))
* Constraint Application Protocol ([CoAP](https://coap.technology/))
* Message Queuing Telemetry Transport ([MQTT](http://mqtt.org/))
Moreover, it enables you to export internal mainframe of its own implemented protocol and
attacks to implement your own protocols or attacks. Also, you can extend already existing
protocols with your newly implemented attacks. And lastly, it provides you an easy to use,
user friendly graphical user interface.
## Build Instructions
Firstly, you need to have Python's **setuptools** module installed in your machine. Also,
you need to install **python-tk** and **[bluepy](https://github.com/IanHarvey/bluepy)**
before installation and build.
In short, you need the followings before running installation script.
* setuptools
* python-tk
* bluepy
> Note that it is suggested to have a separate virtual environment particularly created
> for Peniot since the dependent libraries are pretty old and can cause some trouble to
> install them among your existing external libraries
You can build project in your local by executing following codes.
```shell
$ git clone git@github.com:yakuza8/peniot.git
$ cd peniot
$ python setup.py install
```
Even if we try to provide you up-to-date installation script, there can be some missing parts in
it since the project cannot be maintained so long. Please inform us if there is any problem
with installation.
**Important Note**: You need to have [Radamsa](https://gitlab.com/akihe/radamsa) installed
in your machine in order for generating fuzzing payloads in fuzzing attacks.
## Execution
You can run Peniot via command line or your favorite IDE after setting up a virtual environment and
installing the necessary libraries described above.
```shell
$ python src/peniot.py
```
After running this command, you should see an user interface appeared. Then you can explore the tool
by yourself.
## Documentation
You can find *Design Overview Document* and *Final Design Document* under the **resources/documents** folder.
Several diagrams are attached under the **resources/diagrams** folder. Here is the simplest
representation of how PENIOT is separated modules and how it is designed.
<p align="center">
<img src="/resources/diagrams/peniot_structure_component_diagram.png">
</p>
## Testing
Most of the attacks have their own sample integration tests under their attack scripts. In
order to run those tests, you need to have a running program for the target protocol. We try to
provide you with example programs for each protocol where one can find server/client scripts
under each protocol's **examples** directory.
## Contributors
This project is contributed by the following project members:
- Berat Cankar
- Bilgehan Bingöl
- Doğukan Çavdaroğlu
- Ebru Çelebi
and is supervised by **Pelin Angın**.
## Developer's Note
Firstly, let me thank you for visiting our project site. We tried to provide you how one can
penetrate and hack IoT devices over the protocols they use thanks to end-to-end security attacks.
Our main purpose is to hack those devices with generic security attacks. One can simply find
specific attacks for any protocol, but as I said ours was to provide generic and extendable
penetration framework.
Secondly, PENIOT is developed with **Python2.7**. And our code maybe had gone into *legacy state*.
But nevertheless, we wanted to share it to public so that anyone could get insight and
inspiration to develop their own penetration tools, that is what makes us happy if it could happen.
Thirdly, we also will try to port our tool into **Python3** if we can spare necessary time for that.
When it happens, we will inform it from this page as well. Thanks for your attention.
Developer: @yakuza8 (Berat Cankar)
## Project Poster
<p align="center">
<img src="/resources/peniot_vectorized.svg">
</p>
================================================
FILE: setup.py
================================================
from os import path
from setuptools import setup, find_packages
import sys
sys.path.insert(0, "src")
with open(path.join(".", "README.md")) as f:
long_description = f.read()
setup(
name="Peniot",
version="1.0",
description="Penetration Testing Tool for IoT devices",
long_description=long_description,
author="Berat Cankar,Bilgehan Bingol,Ebru Celebi,Dogukan Cavdaroglu",
url="https://senior.ceng.metu.edu.tr/2019/peniot/",
platform="Unix",
packages=find_packages(),
include_package_data=True,
install_requires=[
"Cython",
"paho-mqtt",
"scapy",
"pyshark-legacy",
"coapthon",
"fpdf",
"pygame==1.9.4",
"pika",
"pexpect",
"enum",
],
classifiers=["Programming Language :: Python :: 2.7.9"],
)
================================================
FILE: src/Entity/__init__.py
================================================
"""
This package contains the following entities:
1) Protocol
2) Attack Suite
3) Attack
4) Input Format
In this module, we have the backend entities to represent and structure our code
And these entities have the following relations in between: (Connection endpoints represent cardinality of entity)
- Protocol 1----------* Attack Suite
- Attack suite 1----------* Attack
- Attack 1----------* Input format
"""
================================================
FILE: src/Entity/attack.py
================================================
import logging
from GUI import hard_coded_texts as hct
class Attack(object):
name = None
inputs = []
default_parameters = []
def __init__(self, name, inputs, default_parameters, definition, logger=None):
self.name = name
self.inputs = inputs
self.default_parameters = default_parameters
self.definition = definition
if logger is None:
self.logger = logging.getLogger(hct.get_logger_name())
else:
self.logger = logging.getLogger("Default logger")
# Load default parameters into input format values
self.load_default_parameters()
def get_attack_name(self):
return self.name
def set_attack_name(self, name):
self.name = name
return self
def get_inputs(self):
return self.inputs
def set_inputs(self, inputs):
self.inputs = inputs
return self
def insert_input(self, _input):
if self.inputs is not None:
self.inputs.append(_input)
def get_default_parameters(self):
return self.default_parameters
def set_default_parameters(self, default_parameters):
self.default_parameters = default_parameters
return self
def insert_default_parameters(self, _default_parameter):
if self.default_parameters is not None:
self.default_parameters.append(_default_parameter)
def get_definition(self):
return self.definition
def set_definition(self, definition):
self.definition = definition
def set_input_value(self, input_name):
for _input in self.inputs:
if _input.get_name() == input_name:
setattr(self, _input.get_name(), _input.get_value())
def run(self):
# Set all the input values of the class, then show begins
for _input in self.inputs:
setattr(self, _input.get_name(), _input.get_value())
# Will be filled by inherited class
def stop_attack(self):
pass # Will be filled by attacks
def load_default_parameters(self):
for _input_index, _input in enumerate(self.inputs):
_input.set_value(self.default_parameters[_input_index])
================================================
FILE: src/Entity/attack_suite.py
================================================
class AttackSuite(object):
name = None
attacks = []
def __init__(self, name, attacks):
self.name = name
self.attacks = attacks
def get_attack_suite_name(self):
return self.name
def set_attack_suite_name(self, name):
self.name = name
return self
def get_attacks(self):
return self.attacks
def set_attacks(self, attacks):
self.attacks = attacks
return self
def insert_attack(self, attack):
if self.attacks is not None:
self.attacks.append(attack)
def run(self):
for attack in self.attacks:
attack.run()
================================================
FILE: src/Entity/input_format.py
================================================
class InputFormat(object):
def __init__(self, label_name, name, value, _type, default_value=None, mandatory=False, secret=False,
from_captured_packets=False):
self.label_name = label_name
self.name = name
self.value = value
self.type = _type
self.mandatory = mandatory
self.default_value = default_value
self.secret = secret
self.from_captured_packets = from_captured_packets
def get_label_name(self):
return self.label_name
def set_label_name(self, label_name):
self.label_name = label_name
return self
def get_name(self):
return self.name
def set_name(self, name):
self.name = name
return self
def get_value(self):
return self.value
def set_value(self, value):
self.value = value
return self
def get_type(self):
return self.type
def set_type(self, _type):
self.type = _type
return self
def set_mandatory(self, mandadory):
self.mandatory = mandadory
return self
def is_mandatory(self):
return self.mandatory
def set_default_value(self, default_value):
self.default_value = default_value
return self
def get_default_value(self):
return self.default_value
def is_secret(self):
return self.secret
def set_secret(self, secret):
self.secret = secret
return self
def is_from_captured_packets(self):
return self.from_captured_packets
def set_from_captured_packets(self, from_captured_packets):
self.from_captured_packets = from_captured_packets
return self
================================================
FILE: src/Entity/protocol.py
================================================
class Protocol(object):
name = None
attack_suites = []
def __init__(self, name, attack_suites, definition):
self.name = name
self.attack_suites = attack_suites
self.definition = definition
def get_protocol_name(self):
return self.name
def set_protocol_name(self, name):
self.name = name
return self
def get_attack_suites(self):
return self.attack_suites
def set_attack_suites(self, attack_suites):
self.attack_suites = attack_suites
return self
def get_definition(self):
return self.definition
def set_definition(self, new_def):
self.definition = new_def
return self
def insert_attack_suite(self, attack_suite):
if self.attack_suites is not None:
self.attack_suites.append(attack_suite)
================================================
FILE: src/GUI/__init__.py
================================================
"""
This package includes graphical user interface of PENIOT
"""
================================================
FILE: src/GUI/custom_widgets.py
================================================
from Tkinter import *
from hard_coded_texts import get_project_name
class Header(Frame):
"""
Generic header template class which is used for construction of different screens
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background="white")
# Create the header
header = Label(self, text=get_project_name(), width=55, font=("Arial", 20), height=5)
header.grid()
header.configure(background="white")
class CustomButton(Button):
"""
Generic button template to use them throughout the screens
"""
def __init__(self, parent_window, text, _function, row, columnspan=None, sticky=None, column=None, height=2,
foreground="black"):
Button.__init__(self, parent_window, command=_function, text=text, font=("Arial", 15), borderwidth=0,
height=height, highlightthickness=0, background="white", foreground=foreground)
self.grid(row=row, columnspan=columnspan, sticky=sticky, column=column)
class CustomLabel(Label):
"""
Generic label template to use them throughout the screens
"""
def __init__(self, parent_window, text, row, column, rowspan=None, columnspan=None, sticky=None):
Label.__init__(self, parent_window, text=text, font=("Arial", 15))
self.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, sticky=sticky)
class CustomRadiobutton(Radiobutton):
"""
Generic radio button template to use them throughout the screens
"""
def __init__(self, parent_window, text, row, column, sticky, variable, value):
Radiobutton.__init__(self, parent_window, text=text, font=("Arial", 13), variable=variable, value=value)
self.grid(row=row, column=column, sticky=sticky)
================================================
FILE: src/GUI/hard_coded_texts.py
================================================
"""
This file contains some methods which return hard-coded texts and constant texts
"""
# Window title, size and background color
project_title = "Peniot"
window_size = "800x650"
window_background_color = "white"
mandatory_fields_background_color = "red"
# Button labels
start_testing_label = "Start Testing"
extend_peniot_label = "Extend Peniot"
view_captured_packets = "View Captured Packets"
help_label = "Help"
back_to_menu_label = "Back to menu"
about_us_label = "About us"
footer_label = "2018-2019 CENG Term Project"
go_to_input_page = "Go to input page"
back_to_attack_selection_page = "Back to attacks selection"
back_to_attack_suite_page = "Back to the attack suite page"
back_to_attack_details = "Back to attacks details"
perform_attack = "Perform the attack"
load_default_parameters = "Load default parameters"
stop_attack_go_back = "Stop the attack and go back"
generate_report = "Generate report"
# Settings for logger
logging_format = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
logger_name = "Attack Reporting Page"
# Color for the console
console_background_color = "black"
console_foreground_color = "white"
def get_project_name():
return "Peniot:Penetration testing tool for Internet of Things"
def get_about_us():
return "The developers of PENIOT project are the following : \n" \
" Berat Cankar\n" \
" Bilgehan Bingol\n" \
" Dogukan Cavdaroglu\n" \
" Ebru Celebi\n" \
"The supervisor of the project is :\n" \
" Asst. Prof. Dr. Pelin Angin "
def get_help():
return "PENIOT enables users to test their IoT devices.For now,it supports the \n" \
"following protocols:\n" \
" * MQTT\n" \
" * CoAP\n" \
" * BLE\n" \
" * AMQP\n" \
"For each protocol, there is at least one attack.After selecting protocol\n" \
"and attacks, you just need to provide some information about your\n" \
"device or network.PENIOT will handle the rest while you are resting.\n" \
"At the end, it will provide a report which states the results of the performed attack.\n"
def get_extension_help():
return "Extension utility which enables you to export internal structure of entities\n" \
"(Attack, AttackSuite and Protocol) or import your implemented entities into\n" \
"Peniot so that you can simulate/execute your own implementations."
def get_logger_name():
"""
Returns the logger name we will use for reporting the attack results
"""
return logger_name
================================================
FILE: src/GUI/tkinter.py
================================================
import logging
import tkFileDialog
import ttk
from threading import Timer
from custom_widgets import *
from hard_coded_texts import *
from utils import *
from Entity.attack import Attack
from Entity.attack_suite import AttackSuite
from Utils import CommonUtil
from Utils.ExtendUtil.export_util import ExportUtil, ExportOptions
from Utils.ExtendUtil.import_util import ImportUtil, ImportOptions
from Utils.ReportUtil.report_generator import GenerateReport
root = None
class HomePage(Frame):
"""
This is the first page which users see when they start the application.
It simply contains a menu with the following options:
- Start Testing
- Help
- About us
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0)
# Start testing button
CustomButton(self, start_testing_label, lambda: change_frame(self, ProtocolsPage(root)), 1)
# Extension button
CustomButton(self, extend_peniot_label, lambda: change_frame(self, ExtensionPage(root)), 2)
# View captured packets button
CustomButton(self, view_captured_packets, lambda: change_frame(self, ViewCapturedPackets(root)), 3)
# Help button
CustomButton(self, help_label, lambda: change_frame(self, Help(root)), 4)
# About us button
CustomButton(self, about_us_label, lambda: change_frame(self, AboutUs(root)), 5)
# Footer
footer = Label(self, text=footer_label, width=55, font=("Arial", 20), height=5)
footer.grid(row=6)
footer.configure(background=window_background_color)
# Make it visible
self.grid()
class AboutUs(Frame):
"""
This page displays information about the developers of the project.
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0)
# Information about us
info_about_us = Label(self, text=get_about_us(), width=55, anchor=W, justify=LEFT, font=("Arial", 15),
height=10)
info_about_us.grid(row=1)
info_about_us.configure(background=window_background_color)
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, HomePage(root)), 2)
# Make it visible
self.grid()
class Help(Frame):
"""
This page displays information about the tool.
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0)
# Information about us
info_about_us = Label(self, text=get_help(), width=70, anchor=W, justify=LEFT, font=("Arial", 15), height=10)
info_about_us.grid(row=1)
info_about_us.configure(background=window_background_color)
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, HomePage(root)), 2)
# Make it visible
self.grid()
class ViewCapturedPackets(Frame):
"""
This page enables users to download captured packets.
"""
CAPTURED_PACKET_PATH = os.path.dirname(os.path.abspath(__file__))[:-4] + "/captured_packets/"
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Generate content
self.generate_content()
# Make it visible
self.grid()
def generate_content(self):
"""
This method is used to generate rows representing the files
"""
# Destroy the existing widgets
for widget in self.winfo_children():
widget.destroy()
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0, columnspan=4)
# Row index
row_index = 1
# Get the file names
file_names = get_captured_packet_files()
for file_name in file_names:
# Remove .txt part
file_name_without_extension = file_name[:-4]
info = file_name_without_extension.split("_")
# Protocol name
protocol_name = Label(self, text=info[0])
protocol_name.grid(row=row_index, column=0)
protocol_name.configure(background=window_background_color)
# Date
date = Label(self, text=info[1] + " " + info[2])
date.grid(row=row_index, column=1)
date.configure(background=window_background_color)
# Download button
CustomButton(self, "Download", lambda file_name=file_name: self.download_file(file_name), row_index, None,
None, 2)
# Delete button
print file_name
CustomButton(self, "Delete", lambda file_name=file_name: self.delete_captured_packets_file(file_name),
row_index, None,
None, 3)
# Increment row index
row_index = row_index + 1
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, HomePage(root)), row_index, 3)
self.grid()
def delete_captured_packets_file(self, file_name):
"""
This method is used to delete a captured packets file
"""
os.remove(self.CAPTURED_PACKET_PATH + file_name)
# Generate content
self.generate_content()
def download_file(self, file_name):
"""
This methods is used to export the selected packets file.
"""
# Get the directory
directory_name = tkFileDialog.askdirectory(initialdir=os.getcwd(), title="Select directory to download packets")
try:
# Read the file
packets_file = os.open(os.path.dirname(os.path.abspath(__file__))[:-4] + "/captured_packets/" + file_name,
os.O_RDONLY)
# Open a file
new_file = os.open(directory_name + "/" + file_name, os.O_RDWR | os.O_CREAT)
# Copy the file content
while True:
data = os.read(packets_file, 2048)
if not data:
break
os.write(new_file, data)
# Close the files
os.close(packets_file)
os.close(new_file)
# Create pop-up
pop_up_window(root, None, "Downloaded successfully")
except Exception as e:
if len(directory_name) == 0:
return
else:
pop_up_window(root, None, "Download operation is failed because of\n{0}".format(e), justify=CENTER)
class ProtocolsPage(Frame):
"""
This page displays the possible options for protocols.
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0, columnspan=2)
# Get protocols
protocols = get_protocols()
# Current row index
row_index = 1
# Create a button for each protocols
for protocol in protocols:
# Create the button for the protocol
CustomButton(self, protocol["protocol"].get_protocol_name(),
lambda selected_protocol=protocol: change_frame(self, AttacksPage(root,
selected_protocol)),
row_index, None, E, 0)
CustomButton(self, "?",
lambda selected_protocol=protocol: pop_up_window(root,
selected_protocol[
"protocol"].get_protocol_name(),
selected_protocol[
"protocol"].get_definition()),
row_index, None, W, 1)
# Increment the row index
row_index = row_index + 1
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, HomePage(root)), row_index, 2)
# Make it visible
self.grid()
class ExtensionPage(Frame):
"""
This page displays the extension options and help button that explains how to extend for PENIOT.
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0, columnspan=2)
# Current row index
row_index = 1
# Export button
CustomButton(self, "Export", lambda: change_frame(self, ExportPage(root)), row_index, None, E, 0)
row_index = row_index + 1
# Import button
CustomButton(self, "Import", lambda: change_frame(self, ImportPage(root)), row_index, None, E, 0)
row_index = row_index + 1
# Help button
CustomButton(self, help_label, lambda: change_frame(self, ExtensionHelp(root)), row_index, 2)
row_index = row_index + 1
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, HomePage(root)), row_index, 2)
# Make it visible
self.grid()
class ImportPage(Frame):
"""
These pages make the user select import or export options
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
self.file_path = ""
self.option = ImportOptions.ATTACK_OR_ATTACK_SUITE
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0, columnspan=4)
row_index = 1
CustomLabel(self, text="Option:", row=row_index, column=0, sticky=E)
option_combo_box = ttk.Combobox(self, values=["Protocol", "Attack or Attack Suite"], font=("Arial", 15))
option_combo_box.grid(row=row_index, column=1, sticky=W + E, columnspan=2)
option_combo_box.bind("<<ComboboxSelected>>",
lambda x: combobox_element_changed(option_combo_box, protocol_name_label,
self.protocol_name_combo_box))
option_combo_box.current(1)
row_index = row_index + 1
protocol_name_label = CustomLabel(self, text="Protocol Name:", row=row_index, column=0, sticky=E)
self.protocol_name_combo_box = ttk.Combobox(self, font=("Arial", 15))
self.protocol_name_combo_box.grid(row=row_index, column=1, sticky=W + E, columnspan=2)
self.protocol_name_combo_box.bind("<<ComboboxSelected>>",
lambda x: combobox_protocol_name_changed(self.protocol_name_combo_box))
row_index = row_index + 1
# Names of available protocols
self.protocol_names = []
# Get protocol names
self.get_protocol_names()
self.selected_protocol = self.protocol_names[0]
CustomLabel(self, text="File Path:", row=row_index, column=0, sticky=E)
file_path_entry = Entry(self, font=("Arial", 15))
file_path_entry.grid(row=row_index, column=1, sticky=W + E, columnspan=2)
CustomButton(self, "Select File", lambda: get_file_path(file_path_entry), row_index, None, W, 3, height=1)
row_index = row_index + 1
CustomButton(self, "Import",
lambda: self.import_button_click(file_path_entry.get(), self.option, self.selected_protocol),
row_index, None, W, 3)
CustomButton(self, back_to_menu_label, lambda: change_frame(self, ExtensionPage(root)), row_index, None, E, 0)
for col in range(5):
self.columnconfigure(col, weight=1)
for row in range(8):
self.rowconfigure(row, weight=1)
self.grid()
def get_file_path(entry):
self.file_path = tkFileDialog.askopenfilename()
entry.delete(0, END)
entry.insert(0, self.file_path)
def combobox_element_changed(combo, label, combobox):
if combo.get() == "Protocol":
label.grid_forget()
combobox.grid_forget()
self.option = ImportOptions.PROTOCOL
else:
label.grid(row=2, column=0, sticky=E)
combobox.grid(row=2, column=1, sticky=W + E, columnspan=2)
self.option = ImportOptions.ATTACK_OR_ATTACK_SUITE
def combobox_protocol_name_changed(combo):
self.selected_protocol = combo.get()
def import_button_click(self, file_path, option, selected_protocol):
try:
if not os.path.isfile(file_path):
pop_up_window(root, None, "Please select a valid file.")
return
ImportUtil.import_action(file_path, option, selected_protocol)
# Update the protocol list since the user may import a new protocol
self.get_protocol_names()
pop_up_window(root, None, "Files are imported successfully")
except Exception as e:
pop_up_window(root, None, "Import operation is failed because of\n{0}".format(e), justify=CENTER)
def get_protocol_names(self):
protocols = get_protocols()
self.protocol_names = []
for protocol in protocols:
self.protocol_names.append(protocol["protocol"].get_protocol_name())
self.protocol_name_combo_box['values'] = self.protocol_names
class ExportPage(Frame):
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0, columnspan=4)
s = ttk.Style()
s.configure(".", font=("Arial", 15))
tab_control = ttk.Notebook(self)
attack_tab = TabFrame(tab_control, ExportOptions.ATTACK)
tab_control.add(attack_tab, text="Attack")
attacksuite_tab = TabFrame(tab_control, ExportOptions.ATTACK_SUITE)
tab_control.add(attacksuite_tab, text="Attack Suite")
protocol_tab = TabFrame(tab_control, ExportOptions.PROTOCOL)
tab_control.add(protocol_tab, text="Protocol")
tab_control.grid(row=1, column=0, columnspan=4, rowspan=3, sticky=W + E + S + N)
CustomButton(self, back_to_menu_label, lambda: change_frame(self, ExtensionPage(root)), 7, None, E, 1)
self.grid()
class TabFrame(Frame):
def __init__(self, parent_window, option):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
self.file_path = None
row = 0
CustomLabel(self, text="Protocol Name:", row=row, column=1, sticky=E)
protocol_name_entry = Entry(self, font=("Arial", 15))
protocol_name_entry.grid(row=row, column=2, sticky=W + E, columnspan=2)
row = row + 1
attack_name_entry = Entry(self, font=("Arial", 15))
if option == ExportOptions.ATTACK:
CustomLabel(self, text="Attack Name:", row=row, column=1, sticky=E)
attack_name_entry.grid(row=row, column=2, sticky=W + E, columnspan=2)
row = row + 1
attack_suite_name_entry = Entry(self, font=("Arial", 15))
if option == ExportOptions.ATTACK_SUITE:
CustomLabel(self, text="Attack Suite Name:", row=row, column=1, sticky=E)
attack_suite_name_entry.grid(row=row, column=2, sticky=W + E, columnspan=2)
row = row + 1
CustomLabel(self, text="File Path:", row=row, column=1, sticky=E)
file_path_entry = Entry(self, font=("Arial", 15))
file_path_entry.grid(row=row, column=2, sticky=W + E, columnspan=2)
CustomButton(self, "Select File Path", lambda: get_file_path(file_path_entry), row, None, W, 4, height=1)
row = row + 1
CustomLabel(self, text="File Name:", row=row, column=1, sticky=E)
file_name_entry = Entry(self, font=("Arial", 15))
file_name_entry.grid(row=row, column=2, sticky=W + E, columnspan=2)
row = row + 1
rad_var = IntVar()
for export_index, export_option in enumerate(ExportUtil.get_export_texts_and_values()):
export_value = export_option.get("value")
if export_index == 0:
rad_var.set(export_value)
CustomRadiobutton(self, text=export_option.get("text"), row=row, column=2, sticky=W + S, variable=rad_var,
value=export_value)
row = row + 1
CustomButton(self, "Export",
lambda: export_button_click(protocol_name=protocol_name_entry.get(),
attack_name=attack_name_entry.get(),
attack_suite_name=attack_suite_name_entry.get(),
file_path=file_path_entry.get(),
file_name=file_name_entry.get(), extension=rad_var.get(),
option=option),
row, None, W, 4)
for col in range(5):
self.columnconfigure(col, weight=1)
for row in range(8):
self.rowconfigure(row, weight=1)
self.grid()
def get_file_path(entry):
self.file_path = tkFileDialog.askdirectory()
entry.delete(0, END)
entry.insert(0, self.file_path)
def export_button_click(protocol_name, attack_name, attack_suite_name, file_path, file_name, extension, option):
try:
if not os.path.exists(file_path):
pop_up_window(root, None, "Please enter a valid file path.")
return
ExportUtil.export_action(protocol_name=protocol_name,
attack_name=attack_name,
attack_suite_name=attack_suite_name,
file_path=file_path,
file_name=file_name, extension=extension,
option=option)
pop_up_window(root, None, "Files are exported successfully.")
except Exception as e:
pop_up_window(root, None, "Export operation is failed because of\n{0}".format(e), justify=CENTER)
class ExtensionHelp(Frame):
"""
This page gives detailed information on how to extend PENIOT.
"""
def __init__(self, parent_window):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Create the header
Header(self).grid(row=0)
# information about us
extension_info = Label(self, text=get_extension_help(), width=70, justify=CENTER, font=("Arial", 15), height=10)
extension_info.grid(row=1)
extension_info.configure(background=window_background_color)
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, ExtensionPage(root)), 2)
# Make it visible
self.grid()
class AttacksPage(Frame):
"""
This page displays the possible attacks for the selected protocol.
"""
def __init__(self, parent_window, protocol):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Set the selected protocol
self.protocol = protocol
# Create the header
Header(self).grid(row=0)
# Get protocol's attack suites
attacks_suites = get_attacks(protocol["package_name"])
# current row index
row_index = 1
# Create a button for each attack
for attack_suite in attacks_suites:
if isinstance(attack_suite, Attack):
# Create the button for the attack
CustomButton(self, attack_suite.get_attack_name(),
lambda selected_attack=attack_suite: change_frame(self,
AttackDetailsPage(root,
self.protocol,
selected_attack,
None)),
row_index)
# Increment the row index
row_index = row_index + 1
elif isinstance(attack_suite, AttackSuite):
# Create the button for the attack suite
CustomButton(self, attack_suite.get_attack_suite_name(),
lambda selected_attack_suite=attack_suite: change_frame(self,
AttackSuiteDetailsPage(root,
self.protocol,
selected_attack_suite)),
row_index)
# Increment the row index
row_index = row_index + 1
if not is_default_protocol(self.protocol["protocol"].get_protocol_name()):
# Back to attack selection page button
CustomButton(self, "Delete Protocol", lambda: self.delete_protocol(), row_index, foreground="red")
row_index = row_index + 1
# Back to menu button
CustomButton(self, back_to_menu_label, lambda: change_frame(self, ProtocolsPage(root)), row_index)
# Make it visible
self.grid()
def delete_protocol(self):
is_successful = delete_protocol(self.protocol["protocol"].get_protocol_name())
if is_successful:
change_frame(self, ProtocolsPage(root))
class AttackSuiteDetailsPage(Frame):
"""
This page displays the details of the selected attack suite.
"""
def __init__(self, parent_window, protocol, attack_suite):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Set the selected protocol
self.protocol = protocol
# Set the selected attack suite
self.attack_suite = attack_suite
# Create the header
Header(self).grid(row=0, columnspan=2)
# row index
row_index = 1
# Create buttons for attacks
for attack_in_suite in attack_suite.get_attacks():
# Create the button for the attack
CustomButton(self, attack_in_suite.get_attack_name(),
lambda selected_attack=attack_in_suite: change_frame(self,
AttackDetailsPage(root, self.protocol,
selected_attack,
attack_suite)),
row_index, 2)
# Increment row index
row_index = row_index + 1
# Back to attack selection page button
CustomButton(self, back_to_attack_selection_page, lambda: change_frame(self, AttacksPage(root, self.protocol)),
row_index, 2)
# Make it visible
self.grid()
class AttackDetailsPage(Frame):
"""
This page displays the details of the selected attack.
"""
def __init__(self, parent_window, protocol, attack, attack_suite):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Set the selected protocol
self.protocol = protocol
# Set the attack suite
self.attack_suite = attack_suite
# Set the selected attack
self.attack = attack
# Create the header
Header(self).grid(row=0, columnspan=2)
# Definition of the attack
attack_definition = Label(self, text=self.attack.get_definition(), width=70, justify=CENTER,
font=("Arial", 15),
height=10)
attack_definition.grid(row=1)
attack_definition.configure(background=window_background_color)
# Back to the previous page
if self.attack_suite is None:
# Back to attack selection page button
CustomButton(self, back_to_attack_selection_page,
lambda: change_frame(self, AttacksPage(root, self.protocol)),
2, None, W)
else:
# Back to attack suite details page button
CustomButton(self, back_to_attack_suite_page,
lambda: change_frame(self, AttackSuiteDetailsPage(root, self.protocol, attack_suite)),
2, None, W)
if not is_default_protocol(self.protocol["protocol"].get_protocol_name()):
# Delete attack button
CustomButton(self, "Delete Attack", lambda: self.delete_attack(), 2, foreground="red")
# Go to input page button
CustomButton(self, go_to_input_page,
lambda: change_frame(self, InputsPage(root, self.protocol, self.attack, self.attack_suite)),
2, None, E)
# Make it visible
self.grid()
def delete_attack(self):
is_successful = delete_attack(self.attack.get_attack_name())
if is_successful:
# Back to the previous page
if self.attack_suite is None:
# Back to attack selection page button
change_frame(self, AttacksPage(root, self.protocol))
else:
# Back to attack suite details page button
change_frame(self, AttackSuiteDetailsPage(root, self.protocol, self.attack_suite))
class InputsPage(Frame):
"""
This page is used to get inputs from the user.
"""
def __init__(self, parent_window, protocol, attack, attack_suite):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Set the selected protocol
self.protocol = protocol
# Set the attack suite
self.attack_suite = attack_suite
# Set the selected attack
self.attack = attack
# file path if necessary
self.file_path = ""
# Create the header
Header(self).grid(row=0, columnspan=3)
# Inputs of the attack
row_index = 1
# Get inputs
self.inputs = self.attack.get_inputs()
# Create an empty list for input values
self.input_values = []
# For each input, create a Label-Entity pair
for _input in self.inputs:
label = Label(self, text=_input.get_label_name())
label.grid(row=row_index)
label.configure(background=window_background_color)
# Create a StringVar for the input
string_var = StringVar(value=str(_input.get_value()))
# Add it to the list
self.input_values.append(string_var)
# Create an entry for the input
if _input.is_secret():
# Bind it to the string var
entry = Entry(self, show="*", textvariable=string_var)
else:
# Bind it to the string var
entry = Entry(self, textvariable=string_var)
entry.grid(row=row_index, column=1)
if _input.is_mandatory():
entry.configure(background=mandatory_fields_background_color)
else:
entry.configure(background=window_background_color)
if _input.is_from_captured_packets():
CustomButton(self, "Select File", lambda: self.get_file_path(entry), row_index, None, W, 2,
height=1)
# Increment the row index
row_index = row_index + 1
# Back to attack details page button
CustomButton(self, back_to_attack_details,
lambda: change_frame(self,
AttackDetailsPage(root, self.protocol, self.attack, self.attack_suite)),
row_index, None,
None, 0)
# Perform the attack page button
CustomButton(self, perform_attack, lambda: self.navigate_to_attack_reporting_page(), row_index, None,
None, 1)
# Set default parameters of the current protocol
row_index += 1
CustomButton(self, load_default_parameters, lambda: (
self.attack.load_default_parameters(),
self.load_default_parameters_to_variables()
), row_index, 2, None, None)
# Make it visible
self.grid()
def get_file_path(self, entry):
path_to_captured_packets = os.path.dirname(os.path.abspath(__file__)) + "/../captured_packets"
self.file_path = tkFileDialog.askopenfilename(initialdir=path_to_captured_packets,
filetypes=[("pcap-files", "BLE*.pcap")])
entry.delete(0, END)
entry.insert(0, self.file_path)
def set_input_values(self):
"""
This function sets the values of the inputs using the self.input_values field.
"""
for i in range(0, len(self.inputs)):
# Get the input from the user
value = self.input_values[i].get()
# If this is a mandatory field, but user did not provide any value for it,
# Then simply create a pop-up explaining the situation
if self.inputs[i].is_mandatory() and value.strip() is "":
pop_up_window(root, "Input Validation",
"Please, be sure that you provide valid values for the mandatory fields.")
# input validation failed
return False
# If the user provide a value for the input, use it
# Otherwise, use the default one
if value is not "":
# convert string to the expected type
try:
value = InputsPage._check_value_type(self.inputs[i], value)
except Exception:
return False
else:
value = self.inputs[i].get_default_value()
# Set the value
self.inputs[i].set_value(value)
return True
def navigate_to_attack_reporting_page(self):
"""
This function is called when we want to start testing
"""
# Set the input values
is_valid = self.set_input_values()
# If we have valid inputs, then continue with the attack
if is_valid:
# Change page to the attack reporting page
change_frame(self, AttackReportingPage(root, self.protocol, self.attack, self.attack_suite))
else:
pop_up_window(root, "Input Validation",
"Please, be sure that you provide valid values for input fields.")
def load_default_parameters_to_variables(self):
for _input_index, _input in enumerate(self.inputs):
self.input_values[_input_index].set(str(_input.get_value()))
@staticmethod
def _check_value_type(_input, _value):
try:
if _input.type == bool:
return CommonUtil.get_boolean_value(_value)
else:
return _input.type(_value)
except TypeError as _:
raise _
class AttackReportingPage(Frame):
"""
This page is used to show the results of the attack.
"""
def __init__(self, parent_window, protocol, attack, attack_suite):
Frame.__init__(self, parent_window)
# Configure the window
self.configure(background=window_background_color)
# Set the selected protocol
self.protocol = protocol
# Set the attack suite
self.attack_suite = attack_suite
# Set the selected attack
self.attack = attack
# Create the header
Header(self).grid(row=0, columnspan=2)
# Create the console
self.console = Text(self)
self.console.grid(row=1, columnspan=2, sticky="nsew")
self.console.configure(background=console_background_color, foreground=console_foreground_color, wrap='word')
# Change the default output stream
sys.stdout = self
# Change the default input stream
sys.stdin = self
# Create a stream handler
stream_handler = logging.StreamHandler(self)
stream_handler.setLevel(logging.INFO)
# Create a formatter
formatter = logging.Formatter(logging_format)
stream_handler.setFormatter(formatter)
# Create a logger
self.logger = logging.getLogger(logger_name)
self.logger.addHandler(stream_handler)
# Start the testing after 1 seconds. Create a Timer object so we can stop execution later
self.timer = Timer(1.0, self.perform_attack)
self.timer.start()
# Stop the attack and back to menu button
CustomButton(self, stop_attack_go_back, lambda: self.attack_stopper(), 2, 1, None, 0)
CustomButton(self, generate_report, lambda: self.report_generator(), 2, 1, None, 1)
# Make it visible
self.grid()
# Override write function
def write(self, text):
self.console.insert(END, str(text))
# Change the state of the console to Disabled so that nobody can write
# Update the tasks so that the user can see the logs
self.update_idletasks()
# Override readline function
def readline(self):
return_value = None
while return_value is None:
# Get the return value
return_value = self.get_number()
# continue until we have a valid return value
if return_value is None:
continue
return return_value
# Used to get user selection for BLE sniffing attack
def get_number(self):
return_value = None
text = self.console.get(1.0, END)[::-1].encode("ascii")
if text[0] == '\n' and text[1] == '\n':
for i in text:
if i == ">":
break
elif str.isdigit(i):
if return_value is None:
return_value = ""
return_value = i + return_value
return return_value
def perform_attack(self):
# Start message
self.logger.info("Performing the attack")
# Run the attack
self.attack.run()
# Exit message
self.logger.info("Attack is performed successfully")
# Define the attack stopper function to end attacks
def attack_stopper(self):
# Remove handlers
self.attack.stop_attack() # Call the underlying attack's own stopper
for handler in self.logger.handlers:
handler.close()
self.logger.removeHandler(handler)
# There will be some more changes here to close open pipes and so on.
# Then, change the frame and go back
change_frame(self, InputsPage(root, self.protocol, self.attack, self.attack_suite))
def report_generator(self):
directory = tkFileDialog.askdirectory()
try:
if type(directory) == str and len(directory) > 0:
directory = directory if directory.endswith('/') else directory + '/'
GenerateReport.generate_pdf_from_text(
self.protocol['protocol'].get_protocol_name(),
self.attack.get_attack_name(),
self.console.get("1.0", END),
directory
)
pop_up_window(root, None, 'Report is successfully generated.', justify=CENTER)
except Exception as e:
pop_up_window(root, None, 'Report cannot be generated properly.\nPlease check given directory path.',
justify=CENTER)
def run():
# Create the root window
root = create_root()
# Create HomePage and make it the current window
HomePage(root).tkraise()
root.mainloop()
================================================
FILE: src/GUI/utils.py
================================================
# This file contains methods which are used in the GUI.
import importlib
import inspect
import os
import pkgutil
import shutil
from Tkinter import *
from hard_coded_texts import project_title, window_size, window_background_color
from Utils.ExtendUtil.import_util import ImportUtil
# list of default protocols
DEFAULT_PROTOCOLS = ["MQTT", "CoAP", "AMQP", "BLE"]
def is_default_protocol(protocol_name):
"""
Check whether the given protocol is default or not
"""
if DEFAULT_PROTOCOLS.__contains__(protocol_name):
return True
return False
def delete_protocol(protocol_name):
"""
Deletes the given protocol
"""
path_to_protocol = os.path.dirname(os.path.abspath(__file__)) + "/../protocols/" + protocol_name
shutil.rmtree(path_to_protocol)
return True
def delete_attack(attack_name):
"""
Deletes the given attack
"""
# Get the protocol name
protocol_name = attack_name[:attack_name.index(" ")]
# Get the attack real name
# Remove protocol name
attack_name = attack_name[attack_name.index(" ") + 1:]
# Remove 'Attack' label at the end
attack_name = attack_name[:attack_name.index(" ")]
# Delete the attack
path_to_attack = os.path.dirname(
os.path.abspath(__file__)) + "/../protocols/" + protocol_name + "/attacks/" + attack_name
shutil.rmtree(path_to_attack)
return True
def pop_up_window(root, protocol_name, definition, justify=LEFT):
"""
A pop up message generator.
"""
popup = Toplevel(root)
# Prevent pop-up from resizing
popup.resizable(False, False)
popup.wm_title(protocol_name)
label = Label(popup, text=definition, anchor=W, font=("Arial", 10), justify=justify, wraplength=800)
# A pop-up with protocol name on top and definition below
label.pack(side="top", fill="both", pady=10)
button1 = Button(popup, text="OK", command=popup.destroy)
button1.pack(expand=True, fill=BOTH)
# Prohibits any other window to accept events
popup.grab_set()
# Center the window
center_widget(popup)
popup.mainloop()
def get_protocols():
"""
it simply searches for the subclasses of Protocol class and returns the all protocols
"""
# Available protocols
protocols = []
# Base package to start searching for protocols
packages = ["src.protocols"]
# Continue to search until no package is available
while len(packages) > 0:
# Get the package
package = packages.pop()
# Get the package module
package_module = importlib.import_module(package)
prefix = package_module.__name__ + "."
for finder, name, ispkg in pkgutil.iter_modules(package_module.__path__, prefix):
# If it is a package, add it to the package list
if ispkg:
packages.append(name)
else:
# For some modules, we may have errors, skip those errors for now
try:
mod = importlib.import_module(name)
except ImportError:
continue
for tname, klass in inspect.getmembers(mod):
if inspect.isclass(klass):
# If the class inherits from Protocol class, simply add it to the protocol list
if "Protocol" in [c.__name__ for c in inspect.getmro(klass)[1:]]:
protocols.append({"package_name": package, "protocol": klass()})
return protocols
def get_attacks(package_name):
"""
it simply searches for the subclasses of Attack class in the given package and returns the attacks
"""
# Available attack names
attack_names = []
# Available attack suites
attack_suites = []
# Available attacks
attacks = []
# Base package to start searching for protocols
packages = [package_name + ".attacks"]
# Continue to search until no package is available
while len(packages) > 0:
# Get the package
package = packages.pop()
package_module = importlib.import_module(package)
prefix = package_module.__name__ + "."
for finder, name, ispkg in pkgutil.iter_modules(package_module.__path__, prefix):
# If it is a package, add it to the package list
if ispkg:
packages.append(name)
else:
try:
mod = importlib.import_module(name)
except ImportError:
continue
for tname, klass in inspect.getmembers(mod):
if inspect.isclass(klass):
# If the class inherits from Attack class, simply add it to the attack list
if "Attack" in [c.__name__ for c in inspect.getmro(klass)[1:]]:
attack = klass()
# check whether we have this attack in the list or not
if not attack_names.__contains__(attack.get_attack_name()):
attacks.append(attack)
attack_names.append(attack.get_attack_name())
# If the class inherits from AttackSuite class, simply add it to the Attack suite list
if "AttackSuite" in [c.__name__ for c in inspect.getmro(klass)[1:]]:
attack_suite = klass()
attack_suites.append(attack_suite)
# Remove attack names included in the attack suites
for attack_suite in attack_suites:
for attack in attack_suite.get_attacks():
if attack_names.__contains__(attack.get_attack_name()):
attack_names.remove(attack.get_attack_name())
# Final list of available attacks
available_attacks = []
# Retrieve attack whose name is included in the attack name list
for attack in attacks:
for attack_name in attack_names:
if attack.get_attack_name() == attack_name:
available_attacks.append(attack)
break
# Add attack suites to the available attacks
for attack_suite in attack_suites:
available_attacks.append(attack_suite)
return available_attacks
def get_captured_packet_files():
"""
Retrieves the files containing saved captured packets
"""
# Names of the files
file_names = []
# Search files in the src.captured_packets package
path_to_package = os.path.dirname(os.path.abspath(__file__))[:-4] + "/captured_packets"
for root, dirs, files in os.walk(path_to_package):
for filename in files:
# Only get .txt files
if filename.endswith(".pcap") or filename.endswith(".txt"):
file_names.append(filename)
return file_names
def change_frame(old_frame, new_frame):
"""
This function is used to change the frame.
Firstly, we have to delete the old frame. Then, we start to use new one.
"""
# Destroy old frame
old_frame.grid_forget()
old_frame.destroy()
# New frame
new_frame.tkraise()
def create_root():
"""
It creates the root window.
"""
# Create the root window
root = Tk()
# Root window related settings
root.title(project_title)
root.geometry(window_size)
root.configure(background=window_background_color)
root.resizable(False, False)
# Center the window
center_widget(root)
startup_calls()
root.protocol("WM_DELETE_WINDOW", lambda: shutdown_calls(root))
return root
def center_widget(window):
"""
Used to center the given window on the screen
"""
# Render the window to get correct width and height
window.update()
# Make window invisible so that we will have a smooth transition from upper left side to center
window.withdraw()
# Get window size settings
width_of_window = window.winfo_width()
height_of_window = window.winfo_height()
# Get screen size settings
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
# Calculate the x and y coordinates
x_coordinate = (screen_width / 2) - (width_of_window / 2)
y_coordinate = (screen_height / 2) - (height_of_window / 2)
# Set the geometry
window.geometry("%dx%d+%d+%d" % (width_of_window, height_of_window, x_coordinate, y_coordinate))
# Make the window visible
window.deiconify()
def startup_calls():
"""
Initialize program dependent modules to make program prepared for all operations
"""
ImportUtil.startup()
def shutdown_calls(root):
"""
Register method callback to call necessary ending operations
"""
ImportUtil.shutdown()
root.destroy()
================================================
FILE: src/Utils/CommonUtil/__init__.py
================================================
"""
Common Utilities
It contains necessary functionalities used commonly in project.
"""
import datetime
def get_current_datetime_for_filename_format():
return datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
def get_current_datetime_for_report_format():
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def get_boolean_value(bool_str):
bool_str = str(bool_str)
true_list = ["1", "true", "yes", "t", "y"]
if bool_str.lower() in true_list:
return True
false_list = ["0", "false", "no", "f", "n"]
if bool_str.lower() in false_list:
return False
raise TypeError("Invalid input for bool type!")
================================================
FILE: src/Utils/ExtendUtil/__init__.py
================================================
"""
Extendability Utilities
It contains necessary functionality used for importing and exporting scripts.
"""
================================================
FILE: src/Utils/ExtendUtil/export_attack_suite_template.py
================================================
#################################################################################
# IMPORTANT WARNING #
# This file is prepared to be guidance for you while implementing your protocol #
# attack or attack suite. You can extend PENIOT with your implementations by #
# filling necessary fields properly, then you can perform what you have created.#
# To achieve this successfully, fill the following code segment carefully and #
# keep compulsory code fields without changing their signatures so that PENIOT #
# could extend itself with your code and work properly. #
#################################################################################
# Do not change any of the import statements, we will provide their contents to you
# Moreover, you do not need to export any other file than your attack suite
from Entity.attack_suite import AttackSuite
class _ATTACK_SUITE_COMBINED_NAME(AttackSuite):
def __init__(self):
attacks = [
# List the wanted attack here to package them in a single entity
]
# Auto generated attack suite name, you can change attack name to be displayed in graphical user interface
attack_suite_name = "_ATTACK_SUITE_NAME"
AttackSuite.__init__(self, attack_suite_name, attacks)
================================================
FILE: src/Utils/ExtendUtil/export_attack_template.py
================================================
#################################################################################
# IMPORTANT WARNING #
# This file is prepared to be guidance for you while implementing your protocol #
# attack or attack suite. You can extend PENIOT with your implementations by #
# filling necessary fields properly, then you can perform what you have created.#
# To achieve this successfully, fill the following code segment carefully and #
# keep compulsory code fields without changing their signatures so that PENIOT #
# could extend itself with your code and work properly. #
#################################################################################
# Do not change any of the import statements, we will provide their contents to you
# Moreover, you do not need to export any other file than your attack
import logging
from Entity.attack import Attack
class _ATTACK_COMBINED_NAME(Attack):
"""
Input Fields
** Important Note **: Each input must appear in the following lines of code for example, you can have following
configuration in attack input list
* For input format class, you need to fill following fields:
1) Label of input to be displayed in GUI
2) Name of member variable in this class, they need to match with following declarations
3) If exist, default value. You may set it "" or None
4) Type of input value to check/cast
inputs = [
InputFormat("Port Number", "port", self.port, int),
InputFormat("Timeout", "timeout", self.timeout, float)
...
]
* Then your attack class must have following member variables (Values are used for exemplifying)
port = 8080
timeout = 0.01
...
"""
"""
Miscellaneous Members
You can much more of them here to internally use
"""
logger = None
def __init__(self):
inputs = [
# You need to decide inputs to be taken from graphical user interface to conduct attack
]
# Auto generated attack name, you can change attack name to be displayed in graphical user interface
attack_name = "_ATTACK_NAME"
# Auto generated attack description, you can change or add description for the new attack,
# you can browse it from ? button nearby attacks in attack menu
description = "_ATTACK_NAME Description"
Attack.__init__(self, attack_name, inputs, description)
# Simple logger and registration
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
self.logger = logging.getLogger("_ATTACK_NAME")
def pre_attack_init(self):
# You can preliminary processes here such as client initialization, sniffing of packets or similar processes
pass
def run(self):
# DO NOT REMOVE!
# Necessary to initiate obtained input values
super(_ATTACK_COMBINED_NAME, self).run()
# Optional field if the attack needs preliminary procedure to be done
self.pre_attack_init()
# Implement attack here
# The code segment below this line will be executed when you click Run Attack button
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" ||| Attack Content HERE ||| "
" vvv vvv "
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
pass
================================================
FILE: src/Utils/ExtendUtil/export_protocol_template.py
================================================
#################################################################################
# IMPORTANT WARNING #
# This file is prepared to be guidance for you while implementing your protocol #
# attack or attack suite. You can extend PENIOT with your implementations by #
# filling necessary fields properly, then you can perform what you have created.#
# To achieve this successfully, fill the following code segment carefully and #
# keep compulsory code fields without changing their signatures so that PENIOT #
# could extend itself with your code and work properly. #
#################################################################################
# Do not change any of the import statements, we will provide their contents to you
# Moreover, you do not need to export any other file than your protocol
from Entity.protocol import Protocol
"""
Note: You need to put your attack implementations to the attack directory that you
can find in root path of created archive. Do not forget this since we are parsing
that directory to import attack dynamically.
"""
class _PROTOCOL_NAME(Protocol):
def __init__(self):
# Auto generated name with respect to your protocol name input
# If you want, you can change it, it will be showed in protocol menu
protocol_name = "_PROTOCOL_NAME"
# You should write definition of exported protocol
# In case of writing, you can view protocol definition
# by clicking question-mark-icon button while selecting target protocol
protocol_definition = "_PROTOCOL_NAME Definition"
# You need to add your attacks to this list in order to view and instantiate them while performing your attacks
attack_suites = [
# Add attacks or attack suites
]
# Call parent constructor with following parameters
# 1) Attack name to be displayed in GUI
# 2) Attacks or attack suites to perform regression and penetration
# 3) Protocol definition to be displayed in GUI
Protocol.__init__(self, protocol_name, attack_suites, protocol_definition)
================================================
FILE: src/Utils/ExtendUtil/export_util.py
================================================
from enum import Enum
from Utils.RandomUtil import random_generated_names as random_util
import logging
import os
import re
import tarfile
import zipfile
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("Util - Export")
class ExportTypes(Enum):
"""
Enumeration types for export modes
"""
ZIP = 0
TAR_GZ = 1
class ExportOptions(Enum):
"""
Enumeration types for export options such as Protocol, Attack or Attack Suite
"""
PROTOCOL = 0
ATTACK = 1
ATTACK_SUITE = 2
# noinspection PyBroadException
class ExportUtil(object):
# Base path
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
# Export Protocol Constants
EXPORT_PROTOCOL_TEMPLATE_NAME = BASE_PATH + "/export_protocol_template.py"
EXPORT_PROTOCOL_NAME_REGEX = "_PROTOCOL_NAME"
# Export Attack Constants
EXPORT_ATTACK_TEMPLATE_NAME = BASE_PATH + "/export_attack_template.py"
EXPORT_ATTACK_NAME_REGEX = "_ATTACK_NAME"
EXPORT_COMBINED_ATTACK_NAME_REGEX = "_ATTACK_COMBINED_NAME"
# Export Attack Suite Constants
EXPORT_ATTACK_SUITE_TEMPLATE_NAME = BASE_PATH + "/export_attack_suite_template.py"
EXPORT_ATTACK_SUITE_NAME_REGEX = "_ATTACK_SUITE_NAME"
EXPORT_COMBINED_ATTACK_SUITE_NAME_REGEX = "_ATTACK_SUITE_COMBINED_NAME"
@staticmethod
def get_export_texts_and_values():
return [
{"text": ".zip", "value": ExportTypes.ZIP},
{"text": ".tar.gz", "value": ExportTypes.TAR_GZ}
]
@staticmethod
def export_function_factory(export_type):
"""
Export function factory to decide method of archive
:type export_type: ExportTypes
:return: Corresponding export function
"""
if export_type == ExportTypes.TAR_GZ:
return ExportUtil.export_files_with_tar
else:
return ExportUtil.export_files_with_zip
@staticmethod
def export_files_with_zip(output_name, list_of_files, output_path="./"):
if not output_name.endswith(".zip"):
output_name = output_name + ".zip"
zf = zipfile.ZipFile(output_path + output_name, mode='w')
for _file in list_of_files:
try:
logger.info("File {0} is added to {1}".format(_file, output_name))
if len(_file) == 2:
# Create file
zf.write(_file[0], _file[1])
else:
# Create directory
zf.writestr(zipfile.ZipInfo(_file[0]), '')
except RuntimeError as _:
logger.error("Error has occurred while compressing file {0}".format(_file[0]))
zf.close()
@staticmethod
def export_files_with_tar(output_name, list_of_files, output_path="./"):
if not output_name.endswith(".tar.gz"):
output_name = output_name + ".tar.gz"
tar = tarfile.open(output_path + output_name, "w:gz")
for _file in list_of_files:
try:
logger.info("File {0} is added to {1}".format(_file, output_name))
if len(_file) == 2:
# Create file
tar.add(_file[0], _file[1])
else:
# Create directory
t = tarfile.TarInfo(_file[0])
t.type = tarfile.DIRTYPE
tar.addfile(t)
except RuntimeError as _:
logger.error("Error has occurred while compressing file {0}".format(_file[0]))
tar.close()
@staticmethod
def export_protocol(protocol_name, export_path, export_type, output_name):
temporary_file_name = None
try:
logger.info("Exporting protocol is started.")
# Check whether output name has any possible naming
if len(output_name.split(".")[0].strip()) == 0:
output_name = protocol_name
temporary_file_name = ExportUtil._create_temporary_file_and_replace_regex(
template_name=ExportUtil.EXPORT_PROTOCOL_TEMPLATE_NAME,
regex_list=[
(ExportUtil.EXPORT_PROTOCOL_NAME_REGEX, protocol_name)
]
)
# Decide function and export with respect to corresponding archive
export_func = ExportUtil.export_function_factory(export_type)
export_func(
output_name,
[ # [0] represents actual file path and [1] represents the name of file in compressed file
(ExportUtil.BASE_PATH + "/../../Entity/protocol.py", "protocol.py"),
(temporary_file_name, protocol_name + "_protocol.py"),
(temporary_file_name, "__init__.py"),
("attacks/__init__.py",)
],
export_path
)
logger.info("Exporting protocol is finished.")
except Exception as _:
logger.error("Error has occurred while exporting protocol.")
finally:
if temporary_file_name is not None:
# Remove temporary file
os.remove(temporary_file_name)
@staticmethod
def export_attack(protocol_name, attack_name, export_path, export_type, output_name):
temporary_file_name = None
try:
logger.info("Exporting attack is started.")
# Check whether output name has any possible naming
if len(output_name.split(".")[0].strip()) == 0:
output_name = protocol_name + "_" + attack_name
temporary_file_name = ExportUtil._create_temporary_file_and_replace_regex(
template_name=ExportUtil.EXPORT_ATTACK_TEMPLATE_NAME,
regex_list=[
(ExportUtil.EXPORT_ATTACK_NAME_REGEX, protocol_name + " " + attack_name + " Attack"),
(ExportUtil.EXPORT_COMBINED_ATTACK_NAME_REGEX, protocol_name + attack_name + "Attack")
]
)
# Decide function and export with respect to corresponding archive
export_func = ExportUtil.export_function_factory(export_type)
export_func(
output_name,
[ # [0] represents actual file path and [1] represents the name of file in compressed file
(ExportUtil.BASE_PATH + "/../../Entity/attack.py", "attack.py"),
(ExportUtil.BASE_PATH + "/../../Entity/input_format.py", "input_format.py"),
(temporary_file_name, protocol_name + "_" + attack_name + "_attack.py"),
(temporary_file_name, "__init__.py",)
],
export_path
)
logger.info("Exporting attack is finished.")
except Exception as _:
logger.error("Error has occurred while exporting attack.")
finally:
if temporary_file_name is not None:
# Remove temporary file
os.remove(temporary_file_name)
@staticmethod
def export_attack_suite(protocol_name, attack_suite_name, export_path, export_type, output_name):
temporary_file_name = None
try:
logger.info("Exporting attack suite is started.")
# Check whether output name has any possible naming
if len(output_name.split(".")[0].strip()) == 0:
output_name = protocol_name + "_" + attack_suite_name + "_suite"
temporary_file_name = ExportUtil._create_temporary_file_and_replace_regex(
template_name=ExportUtil.EXPORT_ATTACK_SUITE_TEMPLATE_NAME,
regex_list=[
(ExportUtil.EXPORT_ATTACK_SUITE_NAME_REGEX, protocol_name + " "
+ attack_suite_name + " Attack Suite"),
(ExportUtil.EXPORT_COMBINED_ATTACK_SUITE_NAME_REGEX, protocol_name
+ attack_suite_name + "AttackSuite")
]
)
# Decide function and export with respect to corresponding archive
export_func = ExportUtil.export_function_factory(export_type)
export_func(
output_name,
[ # [0] represents actual file path and [1] represents the name of file in compressed file
(ExportUtil.BASE_PATH + "/../../Entity/attack_suite.py", "attack_suite.py"),
(temporary_file_name, protocol_name + "_" + attack_suite_name + "_attack_suite.py"),
(temporary_file_name, "__init__.py",)
],
export_path
)
logger.info("Exporting attack suite is finished.")
except Exception as _:
logger.error("Error has occurred while exporting attack.")
finally:
if temporary_file_name is not None:
# Remove temporary file
os.remove(temporary_file_name)
@staticmethod
def _create_temporary_file_and_replace_regex(template_name=None, regex_list=None):
if regex_list is None:
regex_list = []
# Read template
with open(template_name, "r") as export_template_file:
content = export_template_file.read()
temporary_file_name = random_util.get_random_file_name()
content_replaced = \
ExportUtil._replace_regex(content, regex_list)
# Write template to temporary file
with open(temporary_file_name, "w") as temporary_file:
temporary_file.write(content_replaced)
return temporary_file_name
@staticmethod
def _replace_regex(content, substitution_list_as_tuples):
for pair in substitution_list_as_tuples:
content = re.sub(pair[0], pair[1], content)
return content
@staticmethod
def export_action(protocol_name, attack_name, attack_suite_name, file_path, file_name, extension, option):
file_path = file_path if file_path.endswith("/") else file_path + "/"
if option == ExportOptions.PROTOCOL:
ExportUtil.export_protocol(protocol_name, file_path, extension, file_name)
elif option == ExportOptions.ATTACK:
ExportUtil.export_attack(protocol_name, attack_name, file_path, extension, file_name)
elif option == ExportOptions.ATTACK_SUITE:
ExportUtil.export_attack_suite(protocol_name, attack_suite_name, file_path, extension, file_name)
else:
raise ValueError("Unknown export option!")
if __name__ == '__main__':
ExportUtil.export_protocol("KNX", "./", ExportTypes.ZIP, "hey")
================================================
FILE: src/Utils/ExtendUtil/import_util.py
================================================
from enum import Enum
from os import listdir
from os.path import isfile, join
import logging
import os
import shutil
import tarfile
import zipfile
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("Util - Import")
class ImportOptions(Enum):
"""
Enumeration types for import options such as Protocol, Attack_OR_Attack Suite
If user chooses PROTOCOL, then s/he can directly import without selecting any other input
Otherwise, we need to provide currently loaded protocols to select to which one we will import
"""
PROTOCOL = 0
ATTACK_OR_ATTACK_SUITE = 1
class ImportUtil(object):
# Path related variables
BASE_PATH_OF_TEMP = os.path.dirname(os.path.abspath(__file__))
PROTOCOLS_DIR_NAME = "../../protocols/tmp"
TEMP_FULL_PATH = BASE_PATH_OF_TEMP + "/" + PROTOCOLS_DIR_NAME
TEMP_DIR_NAME = ".tmp"
# Get entities
ENTITY_PATH = BASE_PATH_OF_TEMP + "/../../Entity/"
ENTITIES = [_ for _ in listdir(ENTITY_PATH) if
isfile(join(ENTITY_PATH, _)) and not _.startswith("__") and not _.endswith(".pyc")]
@staticmethod
def startup():
"""
Startup function that will be called program starting point in order to create necessary containers
Currently creates the followings:
* Temporary directory imported files
"""
try:
if os.path.isdir(ImportUtil.TEMP_FULL_PATH):
shutil.rmtree(ImportUtil.TEMP_FULL_PATH)
os.mkdir(ImportUtil.TEMP_FULL_PATH)
# make this directory a package
os.open(ImportUtil.TEMP_FULL_PATH + "/__init__.py", os.O_CREAT)
except OSError:
logger.error("Creation of the directory {0} failed.".format(ImportUtil.TEMP_DIR_NAME))
else:
logger.info("Creation of the directory {0} successfully done.".format(ImportUtil.TEMP_DIR_NAME))
pass
@staticmethod
def shutdown():
"""
Shutdown function that will be exit stage of program in order to clean everything that are already created
"""
try:
if os.path.isdir(ImportUtil.TEMP_FULL_PATH):
shutil.rmtree(ImportUtil.TEMP_FULL_PATH)
except OSError:
logger.error("Deletion of the directory {0} failed.".format(ImportUtil.TEMP_DIR_NAME))
else:
logger.info("Deletion of the directory {0} successfully done.".format(ImportUtil.TEMP_DIR_NAME))
pass
@staticmethod
def trigger_import(input_path, protocol_name=None):
try:
import_action = ImportUtil.import_function_factory(input_path)
dir_name, file_name = os.path.split(input_path)
# If the protocol name is provided, it means that we are importing a attack/attack suite
# Therefore, put the imported files to corresponding attacks directory
if protocol_name is not None:
full_path_to_out_dir = ImportUtil.TEMP_FULL_PATH + "/" + protocol_name + "/attacks/" + \
file_name.split(".", 1)[0]
else:
full_path_to_out_dir = ImportUtil.TEMP_FULL_PATH + "/" + file_name.split(".", 1)[0]
try:
os.mkdir(full_path_to_out_dir)
except OSError:
logger.error("Creation of the directory {0} failed.".format(full_path_to_out_dir))
else:
logger.info("Creation of the directory {0} successfully done.".format(full_path_to_out_dir))
import_action(input_path, full_path_to_out_dir)
except RuntimeError as _:
logger.error(_.message)
@staticmethod
def import_function_factory(input_path):
options = [
(zipfile.is_zipfile, ImportUtil.import_zip),
(tarfile.is_tarfile, ImportUtil.import_tar)
]
for option in options:
try:
if option[0](input_path):
return option[1]
else:
continue
except Exception:
pass
raise RuntimeError("Unknown import extension!")
@staticmethod
def import_zip(input_path, full_out_dir_path):
zf = zipfile.ZipFile(input_path, mode='r')
namelist = zf.namelist()
for _file in namelist:
if ImportUtil._do_not_import_names(_file):
continue
try:
zf.extract(_file, full_out_dir_path)
except RuntimeError as _:
logger.error("Error has occurred while extracting file {0}".format(_file))
zf.close()
@staticmethod
def import_tar(input_path, full_out_dir_path):
tar = tarfile.open(input_path)
namelist = tar.getnames()
for _file in namelist:
if ImportUtil._do_not_import_names(_file):
continue
try:
tar.extract(_file, full_out_dir_path)
except RuntimeError as _:
logger.error("Error has occurred while extracting file {0}".format(_file))
tar.close()
@staticmethod
def import_protocol(file_path):
ImportUtil.trigger_import(file_path)
# Take actions with respect to importing of protocol
@staticmethod
def import_attack_or_attack_suite(file_path, protocol_name):
ImportUtil.trigger_import(file_path, protocol_name)
# Take actions with respect to importing of attack or attack suite
@staticmethod
def _is_file_name(name):
"""
:param name: File name or directory name
:return: Whether name represents file or not
"""
return not name.endswith("/")
@staticmethod
def _do_not_import_names(name):
return name in ImportUtil.ENTITIES
@staticmethod
def import_action(file_path, option, protocol_name=None):
if option == ImportOptions.PROTOCOL:
ImportUtil.import_protocol(file_path)
elif option == ImportOptions.ATTACK_OR_ATTACK_SUITE:
if protocol_name is None or protocol_name is "":
raise ValueError("You need to provide protocol name to bind attack to that protocol!")
ImportUtil.import_attack_or_attack_suite(file_path, protocol_name)
else:
raise ValueError("Unknown export option!")
if __name__ == '__main__':
ImportUtil.startup()
================================================
FILE: src/Utils/FilterUtil/__init__.py
================================================
"""
Filtering Utilities
It contains necessary functionalities used for filtering packets in several attacks
1) PyShark Filterer (used with Generic Sniffer)
"""
================================================
FILE: src/Utils/FilterUtil/pyshark_filter_util.py
================================================
import logging
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("Util - PyShark Filter")
class PySharkFilter:
"""
Container class for internally represented pyshark filter
where filter has layer_name, field_nane and value to be checked while filter
"""
def __init__(self, layer_name, field_name, value):
self.layer_name = layer_name
self.field_name = field_name
self.value = value
def set_layer_name(self, layer_name):
self.layer_name = layer_name
return self
def get_layer_name(self):
return self.layer_name
def set_field_name(self, field_name):
self.field_name = field_name
return self
def get_field_name(self):
return self.field_name
def set_value(self, value):
self.value = value
return self
def get_value(self):
return self.value
def apply_filter_to_packet(self, packet):
"""
Apply filter to packet, if exists check value equality otherwise return False
:param packet: Packet to be filtered
:return: Whether packet is the same value with filter value
"""
try:
return packet[self.layer_name].get_field_value(self.field_name).main_field.raw_value == unicode(self.value)
except KeyError:
logger.error("Given layer name or field name is not defined in packet!")
return False
================================================
FILE: src/Utils/FuzzerUtil/__init__.py
================================================
"""
Fuzzer Utilities
It contains necessary functionalities used for fuzzing attacks
1) Radamsa Random Fuzzing Payload Generator
"""
================================================
FILE: src/Utils/FuzzerUtil/radamsa_util.py
================================================
import logging
import subprocess
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logger = logging.getLogger("Util - Radamsa")
ASCII_DECODE_LIMIT = 128
def radamsa_malformed_input_generator(input_string, output_count=1):
"""
Return test case output from given input string
:param output_count: Number of returned output strings
:param input_string: Any type of variable can be input
:return: Radamsa generated output string for fuzzing
"""
# Create subprocess for both echo and radamsa
echo_process = subprocess.Popen(["echo", input_string], stdout=subprocess.PIPE)
radamsa_process = subprocess.Popen(["radamsa", "-n", str(output_count)],
stdin=echo_process.stdout, stdout=subprocess.PIPE)
echo_process.stdout.close()
# Get values
output_string, error_message = radamsa_process.communicate()
if error_message is None:
if output_count > 1:
# If it are more than one, then split it
return output_string.split("\n")
else:
return output_string
else:
logger.debug(error_message)
def get_ascii_decodable_radamsa_malformed_input(input_string, output_count=1):
def delete_non_ascii_characters(_string):
return "".join([_ for _ in _string if ord(_) < ASCII_DECODE_LIMIT])
returned_strings = radamsa_malformed_input_generator(input_string, output_count)
_type = type(returned_strings)
if _type == list:
return [delete_non_ascii_characters(_returned_string) for _returned_string in returned_strings]
elif _type == str:
return delete_non_ascii_characters(returned_strings)
else:
logger.error("Non-matched type for output value")
================================================
FILE: src/Utils/RandomUtil/__init__.py
================================================
"""
Random Utilities
It contains necessary functionalities that is related to randomized operations.
"""
================================================
FILE: src/Utils/RandomUtil/random_generated_names.py
================================================
import random
import string
import time
def get_random_client_name():
return 'peniot-cli-' + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
for _ in range(16)) + '-' + str(int(time.time()))
def get_random_file_name():
return 'peniot_file_' + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
for _ in range(16)) + '-' + str(int(time.time()))
================================================
FILE: src/Utils/ReportUtil/__init__.py
================================================
"""
Report Generation Utilities
It contains necessary functionalities used for reporting
1) Report Generator
"""
================================================
FILE: src/Utils/ReportUtil/report_generator.py
================================================
from fpdf import FPDF
from Utils.CommonUtil import get_current_datetime_for_report_format, get_current_datetime_for_filename_format
class PeniotPDF(FPDF):
TITLE = 'PENIOT: Penetration Testing Tool for IoT'
COPYRIGHT = 'Copyright ' + chr(169) + ' 2018 - 2019 PENIOT Group. All Rights Reserved.'
def header(self):
self.set_font('Arial', 'B', 16)
# Add an address
self.cell(0, 15, self.TITLE, ln=1, align='C')
# Line break
self.ln(15)
self.line(0, 35, self.w, 35)
def footer(self):
self.set_y(-10)
self.set_font('Arial', size=9)
page = 'Page ' + str(self.page_no())
self.cell(0, 5, self.COPYRIGHT, 0, 0, 'C', 0)
self.cell(0, 5, page, 0, 0, 'R')
def add_title_and_date(self, attack_name):
self.set_font("Arial", size=14, style='B')
self.cell(0, 5, attack_name + ' Summary', 0, 0, 'L')
self.set_font("Arial", size=12)
self.cell(0, 5, 'Date: ' + get_current_datetime_for_report_format(), 0, 0, 'R')
self.ln(10)
def add_attack_logs(self, attack_logs):
self.set_font("Arial", size=12)
self.multi_cell(0, 5, txt=attack_logs)
class GenerateReport(object):
@staticmethod
def generate_pdf_from_text(protocol_name, attack_name, attack_logs, directory):
pdf = PeniotPDF()
pdf.add_page()
pdf.add_title_and_date(attack_name)
pdf.add_attack_logs(attack_logs)
output_name = ('_'.join((protocol_name + ' ' + attack_name).split())).lower()
pdf.output(directory + output_name + '_' + get_current_datetime_for_filename_format())
if __name__ == '__main__':
txt = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras quis lacus varius, tempus odio vitae, tempor enim. Cras ut nibh justo. Ut diam ipsum, interdum commodo orci non, ultrices dictum magna. Curabitur tortor lacus, finibus et mattis nec, malesuada nec nibh. Morbi nec sem a leo tincidunt viverra quis eget leo. Aliquam erat volutpat. In tempor auctor tincidunt. Aliquam lectus dui, semper vel justo a, molestie tristique magna. Mauris nec vulputate sapien, blandit convallis felis. In a orci vel urna vehicula faucibus quis et mi. Duis lacus magna, malesuada eu mattis vestibulum, interdum vitae lectus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Suspendisse a lectus id nibh semper hendrerit non eget nisi. Maecenas massa magna, euismod ac dui et, tristique porta metus. Maecenas sed massa eget leo commodo sagittis iaculis ac nisi. Suspendisse ullamcorper, purus quis faucibus venenatis, metus mauris faucibus turpis, ac posuere magna velit non est. Ut ac odio vitae ante ultricies aliquam. Quisque sapien sem, condimentum at erat nec, luctus facilisis nisl. Sed maximus velit ac pellentesque sagittis. Donec ac sagittis leo, et laoreet sem. Vivamus egestas lectus non bibendum accumsan. Sed tempus risus id odio volutpat, a ullamcorper odio lacinia. In vitae velit nulla. Praesent a venenatis diam, a vestibulum tortor.
Duis tincidunt efficitur faucibus. Praesent eget dui tellus. Vestibulum dapibus aliquam arcu. Donec vulputate sem enim, quis tincidunt diam blandit ut. Curabitur accumsan maximus risus, sed dictum ligula volutpat vitae. Curabitur convallis ac mauris ut consectetur. Quisque tellus arcu, ultrices vel ante quis, aliquet fringilla mauris. Sed ornare eros sed interdum facilisis. Duis dictum augue vel rutrum maximus. Phasellus neque dolor, pretium non risus in, tincidunt feugiat eros. Integer vel odio iaculis, faucibus neque quis, mollis enim. Etiam ac euismod orci. Donec tempor, erat at cursus porta, tortor sem aliquam leo, eget porta erat libero eu enim. Etiam felis elit, consectetur a facilisis id, porta quis nulla. Quisque libero odio, ultrices quis est et, efficitur pellentesque dui.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent semper tempus risus, eu condimentum leo interdum sed. Aenean turpis leo, aliquet non ligula venenatis, fermentum maximus velit. Aliquam aliquam posuere libero, quis cursus nisl gravida quis. Proin ac interdum lorem, vitae varius lacus. Maecenas sit amet convallis leo, sit amet tincidunt enim. Suspendisse sit amet risus sit amet libero aliquam mollis. Vestibulum vehicula lacus condimentum, fermentum turpis id, pretium eros. Cras sagittis sem nec porta dictum. Donec a accumsan dolor. Nam dictum eros at leo viverra, ac mattis elit placerat. Mauris ornare pulvinar massa nec rutrum. Nunc nec erat at est lobortis dictum ut in enim. Donec eu est sit amet lacus feugiat blandit. Praesent a sollicitudin ex, blandit fermentum tellus. Nulla vitae viverra ipsum, in pharetra dolor.
Praesent imperdiet nec nisi aliquam dictum. Nunc ultricies sodales porta. Donec consectetur finibus tellus, porttitor sodales sapien pulvinar in. Duis suscipit suscipit felis eu luctus. Nam in dolor aliquam, laoreet elit a, faucibus ligula. Nulla quis nisl imperdiet dolor molestie rhoncus. Fusce neque tortor, blandit at sapien in, egestas fermentum felis. Curabitur auctor ipsum vitae velit vestibulum ultrices.
Pellentesque eget lectus urna. Aenean commodo semper orci sit amet dictum. Curabitur ultrices vitae ipsum in bibendum. Nunc at justo ut augue mollis aliquam. Sed varius, purus at sagittis condimentum, ex velit elementum neque, at malesuada dui arcu nec orci. Nullam viverra, nisi aliquam porta tempor, ex ex bibendum eros, eu viverra urna turpis eu massa. Vestibulum quam lectus, ullamcorper sit amet imperdiet in, tincidunt quis tortor.
Sed non mollis ligula, non imperdiet nunc. Nam elementum augue sit amet risus pulvinar, id dapibus velit laoreet. Sed commodo arcu ut tellus commodo, sed gravida nisl viverra. Sed non sapien lacus. Etiam nec gravida urna, vitae sodales risus. Donec iaculis vel ex aliquam imperdiet. Maecenas condimentum imperdiet porta. Suspendisse potenti. Donec tincidunt vestibulum libero, ac lobortis nisi interdum ac. Curabitur luctus nisl a lorem ultrices pellentesque. Nam eleifend at ex nec pretium. Nullam id purus eget metus facilisis condimentum quis non urna. Quisque et volutpat purus. Pellentesque facilisis molestie orci, a pharetra dolor aliquet sed.
Vestibulum purus mi, dapibus ac rutrum et, convallis at magna. Nunc leo justo, finibus quis molestie vel, accumsan sit amet diam. Quisque vehicula lacus vitae augue imperdiet vulputate. Phasellus vulputate metus vel ex dapibus, nec pretium sapien eleifend. Cras metus erat, vehicula sed mi ut, eleifend finibus dui. Mauris bibendum, velit vel mollis sodales, libero orci congue dui, non dapibus eros lectus malesuada tortor. Ut dignissim dui turpis, ut faucibus velit consectetur nec. Aenean vestibulum turpis pulvinar egestas fringilla. Suspendisse potenti. Etiam dignissim sapien ac velit molestie, ac blandit augue tempor. Pellentesque laoreet tellus a dui dignissim, eget sagittis lacus pharetra. Sed id elit ac lorem tristique cursus. Nunc vel porta augue. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec at dolor eget arcu dignissim mollis at eget erat. Aenean sodales enim id massa vehicula, ac tempus massa dictum. Praesent facilisis id urna vel scelerisque. Etiam pharetra consequat massa eget molestie. Donec ullamcorper ipsum ut orci aliquet placerat. Quisque sit amet magna quis velit tincidunt placerat. Nulla facilisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis congue est sit amet arcu sollicitudin dapibus. Maecenas tristique venenatis ante, eu elementum leo sollicitudin vel.
Suspendisse at accumsan nulla. Nam blandit auctor purus posuere tempor. Pellentesque molestie pellentesque justo ut condimentum. Aenean non fringilla mi. Nullam elementum nibh orci, eget imperdiet eros elementum hendrerit. Nam vitae volutpat odio. Pellentesque a ligula iaculis odio varius porta at ut ipsum.
Nulla mi augue, malesuada iaculis nibh sed, blandit molestie enim. Donec luctus ipsum sed mollis porta. Nam hendrerit finibus turpis, ac elementum ante mattis vel. Aliquam tincidunt varius tellus sed tempus. Fusce vel tellus sem. Sed suscipit ex in auctor dictum. Duis ullamcorper tortor urna, non ullamcorper justo convallis ac. Nullam at est magna. Nam id erat mattis orci bibendum ultrices et in nisl. Maecenas a fringilla lorem. In facilisis, sapien volutpat posuere consectetur, ligula erat ornare neque, a ornare velit.
"""
GenerateReport.generate_pdf_from_text('CoAP', 'DoS Attack', txt)
================================================
FILE: src/Utils/SnifferUtil/__init__.py
================================================
"""
Sniffer Utilities
It contains necessary functionalities used for sniffers
1) Generic Sniffer with PyShark
"""
================================================
FILE: src/Utils/SnifferUtil/generic_sniffer.py
================================================
import logging
import os
import pyshark
from Utils.FilterUtil import pyshark_filter_util as pyshark_filter_util
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("Generic Sniffer")
DEFAULT_INTERFACE = "any"
DEFAULT_SNIFF_TIMEOUT = 15.
DEFAULT_SAVE = False
DEFAULT_SAVE_DIR = os.path.dirname(os.path.abspath(__file__)) + "/../../captured_packets/"
def filter_packets_by_filter_list(packets, filter_list):
"""
:param packets: Packet list
:param filter_list: Filters with respect to packet field
:type filter_list: list of pyshark_filter_util.PySharkFilter
:return: Filtered packets as list
"""
filtered_packets = [packet for packet in packets
if all(single_filter.apply_filter_to_packet(packet) for single_filter in filter_list)]
return filtered_packets
class GenericSniffer:
"""
Generic sniffer template class
The class can listen specific interface by tshark over pyshark
and filter wanted packets by looking at display filter parameter
with the given timeout amount
"""
def __init__(self, timeout=DEFAULT_SNIFF_TIMEOUT, interface=DEFAULT_INTERFACE, use_json=False, include_raw=False,
output_pcap_filename=None, output_dir=DEFAULT_SAVE_DIR, display_filter=None):
self.captured_packets = None
self.timeout = timeout
self.interface = interface
self.use_json = use_json
self.include_raw = include_raw
# Default value is None and it is important to have it None since it will not produce file in this case
if output_pcap_filename is None:
self.output_pcap_filename = None
else:
self.output_pcap_filename = "{0}{1}{2}".format(output_dir, output_pcap_filename,
("" if output_pcap_filename.endswith(".pcap") else ".pcap"))
self.display_filter = display_filter
def start_live_capture(self):
"""
Start capture procedure of packets over listener
:return: None since captured packets are saved internally
"""
capture = pyshark.LiveCapture(interface=self.interface, use_json=self.use_json, include_raw=self.include_raw,
output_file=self.output_pcap_filename, display_filter=self.display_filter)
capture.sniff(timeout=self.timeout)
self.captured_packets = capture._packets
logger.info("{0} packets are captured.".format(len(self.captured_packets)))
capture.close()
def get_captured_packets(self):
"""
:return: Captured packets as list
"""
return self.captured_packets
def filter_packets_by_protocol(self, protocol=None):
"""
Filtering operation of packets via protocol name
:param protocol: Protocol name which will be used for filtering packets by looking their layers
:return: Filtered packet list
"""
if protocol is None:
return self.captured_packets
else:
return filter(lambda packet: protocol in str(packet.layers), self.captured_packets)
if __name__ == '__main__':
sniffer = GenericSniffer()
sniffer.start_live_capture()
================================================
FILE: src/Utils/__init__.py
================================================
"""
General Utility Module
"""
================================================
FILE: src/__init__.py
================================================
================================================
FILE: src/captured_packets/__init__.py
================================================
"""
This package contains the all captured packets.
The files inside this package follows these rules:
- Name of the file begins with the protocol name which packets belong to.
- Then, the time at which packets are captured is appended to the file name.
- The file extension is .pcap.
Here are some example file names:
MQTT_2014-09-26_16:34:40.pcap, AMQP_2014-09-26_17:25:40.pcap
"""
================================================
FILE: src/module_installer.py
================================================
print "Checking whether we have necessary dependencies installed..."
try:
import paho.mqtt
print "[+] You have paho-mqtt module installed."
except ImportError:
print "[-] You have to install paho.mqtt module"
print "\tHint: sudo -H pip install paho-mqtt"
try:
import bluepy
print "[+] You have bluepy module installed."
except ImportError:
print "[-] You have to install bluepy module"
print "\tHint: sudo -H pip install bluepy"
try:
import coapthon
print "[+] You have coapthon module installed."
except ImportError:
print "[-] You have to install coapthon module"
print "\tHint: sudo -H pip install coapthon"
try:
import Cython
print "[+] You have Cython module installed."
except ImportError:
print "[-] You have to install Cython module"
print "\tHint: sudo -H pip install Cython"
try:
import pygame
print "[+] You have pygame module installed."
except ImportError:
print "[-] You have to install pygame module"
print "\tHint: sudo -H pip install pygame"
try:
import pika
print "[+] You have pika module installed."
except ImportError:
print "[-] You have to install pygame module"
print "\tHint: sudo -H pip install pika"
================================================
FILE: src/peniot.py
================================================
# Run the program driver of tkinter
if __name__ == '__main__':
from GUI.tkinter import run
run()
================================================
FILE: src/protocols/AMQP/__init__.py
================================================
"""
This package contains the following functionalities:
1) Example usage of AMQP.
2) AMQP Scanner
"""
================================================
FILE: src/protocols/AMQP/amqp_protocol.py
================================================
import unittest
from Entity.protocol import Protocol
class AMQP(Protocol):
def __init__(self):
amqp_definition = "AMQP stands for Advanced Message Queuing Protocol and it is an open standard application layer protocol.\n\n" \
"There are a couple of key parts in AMQP:\n" \
"* Broker (Server): An application - implementing the AMQP model - that accepts connections from clients\n" \
" for message routing, queuing etc.\n" \
"* Message: Content of data transferred / routed including information such as payload and message attributes.\n" \
"* Consumer: An application which receives message(s) - put by a producer - from queues.\n" \
"* Producer: An application which puts messages to a queue."
attack_suites = []
Protocol.__init__(self, "AMQP", attack_suites, amqp_definition)
class TestAMQPProtocol(unittest.TestCase):
def setUp(self):
self.amqp = AMQP()
def tearDown(self):
pass
def test_name(self):
self.assertEqual("AMQP", self.amqp.get_protocol_name())
def test_attacks(self):
attack_suites = self.amqp.get_attack_suites()
self.assertIsNotNone(attack_suites)
self.assertEquals(len(attack_suites), 0)
if __name__ == '__main__':
unittest.main()
================================================
FILE: src/protocols/AMQP/amqp_scanner.py
================================================
from Utils.SnifferUtil import generic_sniffer as generic_sniffer
# Capturing via TShark
amqp_layer_filter = "amqp"
class AMQPScanner:
"""
This class is used to scan for a AMQP device.
It captures packets from the network and try to find AMQP devices.
"""
def __init__(self):
pass
@staticmethod
def scan(timeout=generic_sniffer.DEFAULT_SNIFF_TIMEOUT, interface=generic_sniffer.DEFAULT_INTERFACE,
use_json_and_include_raw=False, output_pcap_filename=None):
sniffer = generic_sniffer.GenericSniffer(timeout=timeout, interface=interface,
use_json=use_json_and_include_raw,
include_raw=use_json_and_include_raw,
output_pcap_filename=output_pcap_filename,
display_filter=amqp_layer_filter)
sniffer.start_live_capture()
return sniffer.get_captured_packets()
if __name__ == '__main__':
packets = AMQPScanner().scan()
for packet in packets:
print packet
================================================
FILE: src/protocols/AMQP/attacks/__init__.py
================================================
"""
This is a package that contains attacks to AMQP protocol.
Currently, it supports the following attacks
1) Denial of Service Attack
2) Fuzzing Attack
"""
================================================
FILE: src/protocols/AMQP/attacks/amqp_dos_attack.py
================================================
import logging
import multiprocessing
import signal
import time
import unittest
import pika
from Entity.attack import Attack
from Entity.input_format import InputFormat
class AMQPDoSAttack(Attack):
"""
AMQP Protocol - DoS Attack Module
"""
# Input Fields
host = "localhost"
queue = "peniot-queue"
exchange = "peniot-exchange"
routing_key = "peniot-routing-key"
body = "peniot-body"
exchange_type = "direct"
timeout = 0.01
# Misc Members
connection = None
channel = None
logger = None
sent_message_count = 0
stopped_flag = False
def __init__(self):
default_parameters = ["", "", "", "", "", "", 10.0]
inputs = [
InputFormat("Host Name", "host", "localhost", str, mandatory=True),
InputFormat("Queue Name", "queue", "peniot-queue", str, mandatory=True),
InputFormat("Exchange Name", "exchange", "peniot-exchange", str, mandatory=True),
InputFormat("Routing Key", "routing_key", "peniot-routing-key", str, mandatory=True),
InputFormat("Message Body", "body", "peniot-body", str, mandatory=True),
InputFormat("Exchange Type", "exchange_type", "direct", str, mandatory=True),
InputFormat("Timeout", "timeout", self.timeout, float)
]
Attack.__init__(self, "AMQP DoS Attack", inputs, default_parameters,
" We send AMQP requests to the client.\n"
" The time difference between those requests\n"
" can be specified.")
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
# Signal handler to exit from function
signal.signal(signal.SIGINT, self.signal_handler)
def signal_handler(self, sig, frame):
self.stop_attack()
def stop_attack(self):
self.logger.info("Connection will be closed")
self.stopped_flag = True
if self.connection is not None:
self.connection.close()
time.sleep(2) # Sleep two seconds so the user can see the message
def pre_attack_init(self):
# Get connection and channel
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.host))
self.channel = self.connection.channel()
# Create exchange
self.channel.exchange_declare(exchange=self.exchange, exchange_type=self.exchange_type)
# Define queue to store
self.channel.queue_declare(queue=self.queue)
def run(self):
super(AMQPDoSAttack, self).run()
self.pre_attack_init()
# Start client loop for requests
while self.stopped_flag is True:
self.sent_message_count += 1
self.channel.basic_publish(exchange=self.exchange, routing_key=self.routing_key, body=self.body)
self.logger.info("{0} messages published.".format(str(self.sent_message_count)))
time.sleep(self.timeout)
class TestMQTTDoSAttack(unittest.TestCase):
def setUp(self):
self.amqp_dos_attack = AMQPDoSAttack()
def tearDown(self):
pass
def test_name(self):
self.assertEqual("AMQP DoS Attack", self.amqp_dos_attack.get_attack_name())
def test_inputs(self):
inputs = self.amqp_dos_attack.get_inputs()
self.assertIsNotNone(inputs)
self.assertGreater(len(inputs), 0, "Non inserted inputs")
self.assertEquals(len(inputs), 7)
def test_non_initialized_inputs(self):
inputs = self.amqp_dos_attack.get_inputs()
for _input in inputs:
value = getattr(self.amqp_dos_attack, _input.get_name())
self.assertTrue(value is None or type(value) == _input.get_type())
def test_after_getting_inputs(self):
example_inputs = ["a.b.c.d", "pen-queue", "pen-exchange", "pen-routing-key", "peniot-payload", "pen-exh-type",
13.2]
for index, _input in enumerate(example_inputs):
self.amqp_dos_attack.inputs[index].set_value(_input)
# Previously it should not be set
self.assertIsNone(self.amqp_dos_attack.connection)
super(AMQPDoSAttack, self.amqp_dos_attack).run()
inputs = self.amqp_dos_attack.get_inputs()
for index, _input in enumerate(inputs):
value = getattr(self.amqp_dos_attack, _input.get_name())
self.assertEqual(example_inputs[index], value)
def test_dos_attack(self):
def run_attack():
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body",
"direct", 1]
for index, _input in enumerate(example_inputs):
self.amqp_dos_attack.inputs[index].set_value(_input)
self.amqp_dos_attack.run()
print "* If server is not initialized this test will not execute properly."
p = multiprocessing.Process(target=run_attack, name="DoS Attack")
p.start()
time.sleep(5)
if p.is_alive():
p.terminate()
p.join()
if __name__ == '__main__':
unittest.main()
================================================
FILE: src/protocols/AMQP/attacks/amqp_fuzzing_attack_suite.py
================================================
from amqp_payload_size_fuzzer import *
from amqp_random_payload_fuzzing import *
from Entity.attack_suite import AttackSuite
class AMQPFuzzingAttackSuite(AttackSuite):
def __init__(self):
attacks = [AMQPRandomPayloadFuzzingAttack(), AMQPPayloadSizeFuzzerAttack()]
AttackSuite.__init__(self, "AMQP Fuzzing Attack Suite", attacks)
class TestAMQPFuzzingAttackSuite(unittest.TestCase):
def setUp(self):
self.amqp_fuzzing_attack_suite = AMQPFuzzingAttackSuite()
def tearDown(self):
pass
def test_name(self):
self.assertEqual("AMQP Fuzzing Attack Suite", self.amqp_fuzzing_attack_suite.get_attack_suite_name())
def test_attack_list(self):
attacks = self.amqp_fuzzing_attack_suite.get_attacks()
self.assertIsNotNone(attacks)
self.assertGreater(len(attacks), 0, "Non inserted attacks")
self.assertEquals(len(attacks), 2)
def test_attacks(self):
attacks = self.amqp_fuzzing_attack_suite.get_attacks()
for attack in attacks:
p = multiprocessing.Process(target=attack.run, name=attack.get_attack_name())
p.start()
time.sleep(5)
if p.is_alive():
p.terminate()
p.join()
if __name__ == '__main__':
unittest.main()
================================================
FILE: src/protocols/AMQP/attacks/amqp_payload_size_fuzzer.py
================================================
import logging
import multiprocessing
import random
import signal
import time
import unittest
import pika
from Entity.attack import Attack
from Entity.input_format import InputFormat
class AMQPPayloadSizeFuzzerAttack(Attack):
"""
AMQP Protocol - Payload Size Fuzzer Attack module
It is created to test any AMQP device as black box test with malformed or semi-malformed inputs
"""
# Input Fields
host = "localhost"
queue = "peniot-queue"
exchange = "peniot-exchange"
routing_key = "peniot-routing-key"
payload = None
exchange_type = "direct"
turn = 10
# Misc Members
connection = None
channel = None
logger = None
sent_message_count = 0
max_payload_length = 2 ** 32
stopped_flag = False
def __init__(self):
default_parameters = ["", "", "", "", "", "", 10]
inputs = [
InputFormat("Host Name", "host", "localhost", str, mandatory=True),
InputFormat("Queue Name", "queue", "peniot-queue", str, mandatory=True),
InputFormat("Exchange Name", "exchange", "peniot-exchange", str, mandatory=True),
InputFormat("Routing Key", "routing_key", "peniot-routing-key", str, mandatory=True),
InputFormat("Payload", "payload", "", str, mandatory=True),
InputFormat("Exchange Type", "exchange_type", "direct", str, mandatory=True),
InputFormat("Fuzzing Turn", "turn", 10, int)
]
Attack.__init__(self, "AMQP Payload Size Fuzzer Attack", inputs, default_parameters,
" AMQP Payload size fuzzer attack description")
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
# Signal handler to exit from function
signal.signal(signal.SIGINT, self.signal_handler)
def signal_handler(self, sig, frame):
self.stop_attack()
def stop_attack(self):
self.logger.info("Connection will be closed")
self.stopped_flag = True
if self.connection is not None:
self.connection.close()
time.sleep(2) # Sleep two seconds so the user can see the message
def pre_attack_init(self):
try:
assert self.turn >= 2
except AssertionError as e:
raise
# Get connection and channel
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.host))
self.channel = self.connection.channel()
# Create exchange
self.channel.exchange_declare(exchange=self.exchange, exchange_type=self.exchange_type)
# Define queue to store
self.channel.queue_declare(queue=self.queue)
def run(self):
Attack.run(self)
self.pre_attack_init()
assert self.turn >= 2
# Fill the size list as randomly generated
size_list = [0, self.max_payload_length]
size_list.extend([random.randint(0, self.max_payload_length) for _ in range(self.turn - 2)])
fuzzing = 0
self.logger.info("Size payload fuzzing is started. Please consider it may take some time.")
for payload_size in size_list:
if self.stopped_flag is True:
break
# Create payload and send it
random_strings = "".join([chr(_) for _ in range(65, 91)]) + "".join([chr(_) for _ in range(97, 123)])
random_character = random.choice(random_strings)
sized_payload = random_character * payload_size
self.channel.basic_publish(exchange=self.exchange, routing_key=self.routing_key, body=sized_payload)
# Informative procedures
self.logger.info("Turn {0} is completed".format(fuzzing + 1))
self.sent_message_count += 1
fuzzing += 1
time.sleep(1)
if self.stopped_flag is False:
self.logger.info("Payload size attack is finished.")
class TestCoAPPayloadSizeAttack(unittest.TestCase):
def setUp(self):
self.amqp_payload_size_fuzzer = AMQPPayloadSizeFuzzerAttack()
def tearDown(self):
pass
def test_name(self):
self.assertEqual("AMQP Payload Size Fuzzer Attack", self.amqp_payload_size_fuzzer.get_attack_name())
def test_inputs(self):
inputs = self.amqp_payload_size_fuzzer.get_inputs()
self.assertIsNotNone(inputs)
self.assertGreater(len(inputs), 0, "Non inserted inputs")
self.assertEquals(len(inputs), 7)
def test_non_initialized_inputs(self):
inputs = self.amqp_payload_size_fuzzer.get_inputs()
for _input in inputs:
value = getattr(self.amqp_payload_size_fuzzer, _input.get_name())
self.assertTrue(value is None or type(value) == _input.get_type())
def test_after_getting_inputs(self):
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body", "direct",
5]
for index, _input in enumerate(example_inputs):
self.amqp_payload_size_fuzzer.inputs[index].set_value(_input)
# Previously it should not be set
self.assertIsNone(self.amqp_payload_size_fuzzer.connection)
super(AMQPPayloadSizeFuzzerAttack, self.amqp_payload_size_fuzzer).run()
inputs = self.amqp_payload_size_fuzzer.get_inputs()
for index, _input in enumerate(inputs):
value = getattr(self.amqp_payload_size_fuzzer, _input.get_name())
self.assertEqual(example_inputs[index], value)
def test_invalid_fuzzing_turn(self):
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body", "direct",
1]
for index, _input in enumerate(example_inputs):
self.amqp_payload_size_fuzzer.inputs[index].set_value(_input)
super(AMQPPayloadSizeFuzzerAttack, self.amqp_payload_size_fuzzer).run()
try:
self.amqp_payload_size_fuzzer.pre_attack_init()
except AssertionError as e:
self.assertTrue(True)
def test_payload_size_fuzzing_attack(self):
def run_attack():
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body",
"direct", 3]
for index, _input in enumerate(example_inputs):
self.amqp_payload_size_fuzzer.inputs[index].set_value(_input)
try:
self.amqp_payload_size_fuzzer.run()
except Exception as e:
self.assertTrue(False)
print "* If server is not initialized this test will not execute properly."
p = multiprocessing.Process(target=run_attack, name="DoS Attack")
p.start()
time.sleep(5)
if p.is_alive():
p.terminate()
p.join()
if __name__ == '__main__':
unittest.main()
================================================
FILE: src/protocols/AMQP/attacks/amqp_random_payload_fuzzing.py
================================================
import logging
import multiprocessing
import random
import signal
import time
import unittest
import pika
from Entity.attack import Attack
from Entity.input_format import InputFormat
from Utils.FuzzerUtil import radamsa_util as rdm
class AMQPRandomPayloadFuzzingAttack(Attack):
"""
AMQP Protocol - Random Payload Fuzzing Attack module
"""
# Input Fields
host = "localhost"
queue = "peniot-queue"
exchange = "peniot-exchange"
routing_key = "peniot-routing-key"
payload = None
exchange_type = "direct"
turn = 10
count = 1
# Misc Members
connection = None
channel = None
logger = None
sent_message_count = 0
max_length_of_random_payload = 100
stopped_flag = False
def __init__(self):
default_parameters = ["", "", "", "", "", "", 10, 1]
inputs = [
InputFormat("Host Name", "host", "localhost", str, mandatory=True),
InputFormat("Queue Name", "queue", "peniot-queue", str, mandatory=True),
InputFormat("Exchange Name", "exchange", "peniot-exchange", str, mandatory=True),
InputFormat("Routing Key", "routing_key", "peniot-routing-key", str, mandatory=True),
InputFormat("Payload", "payload", "", str),
InputFormat("Exchange Type", "exchange_type", "direct", str, mandatory=True),
InputFormat("Fuzzing Turn", "turn", 10, int),
InputFormat("Fuzzing Count", "count", 1, int)
]
Attack.__init__(self, "AMQP Random Payload Fuzzing Attack", inputs, default_parameters,
" It creates a random payload and sends \n"
" this payload to the client.")
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
# Signal handler to exit from function
signal.signal(signal.SIGINT, self.signal_handler)
def signal_handler(self, sig, frame):
self.stop_attack()
def stop_attack(self):
self.logger.info("Connection will be closed")
self.stopped_flag = True
if self.connection is not None:
self.connection.close()
time.sleep(2) # Sleep two seconds so the user can see the message
def pre_attack_init(self):
# Get connection and channel
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.host))
self.channel = self.connection.channel()
# Create exchange
self.channel.exchange_declare(exchange=self.exchange, exchange_type=self.exchange_type)
# Define queue to store
self.channel.queue_declare(queue=self.queue)
def run(self):
Attack.run(self)
self.pre_attack_init()
payload = self.payload
if payload is None:
# Create seed with randomly
length = random.randint(1, self.max_length_of_random_payload)
payload = "".join([chr(random.randint(1, 127)) for _ in range(length)])
self.logger.info("Random payload fuzzing is started.")
for fuzzing in range(self.turn):
if self.stopped_flag is True:
break
while True:
try:
returned_strings = rdm.get_ascii_decodable_radamsa_malformed_input(payload, self.count)
if type(returned_strings) == list:
fuzzer_messages = [string.decode("utf-8") for string in returned_strings]
else:
fuzzer_messages = returned_strings.decode("utf-8")
break
except UnicodeDecodeError:
continue
# Check whether result is list or not
if type(fuzzer_messages) == list:
for message in fuzzer_messages:
self.channel.basic_publish(exchange=self.exchange, routing_key=self.routing_key, body=message)
# Increment sent message count
self.sent_message_count += 1
else:
self.channel.basic_publish(exchange=self.exchange, routing_key=self.routing_key, body=fuzzer_messages)
# Increment sent message count
self.sent_message_count += 1
time.sleep(1)
self.logger.info("Turn {0} is completed".format(fuzzing + 1))
if self.stopped_flag is False:
self.logger.info("Random payload fuzzing is finished.")
if self.connection is not None:
self.connection.close()
class TestAMQPRandomPayloadAttack(unittest.TestCase):
def setUp(self):
self.amqp_random_payload_fuzzer = AMQPRandomPayloadFuzzingAttack()
def tearDown(self):
pass
def test_name(self):
self.assertEqual("AMQP Random Payload Fuzzing Attack", self.amqp_random_payload_fuzzer.get_attack_name())
def test_inputs(self):
inputs = self.amqp_random_payload_fuzzer.get_inputs()
self.assertIsNotNone(inputs)
self.assertGreater(len(inputs), 0, "Non inserted inputs")
self.assertEquals(len(inputs), 8)
def test_non_initialized_inputs(self):
inputs = self.amqp_random_payload_fuzzer.get_inputs()
for _input in inputs:
value = getattr(self.amqp_random_payload_fuzzer, _input.get_name())
self.assertTrue(value is None or type(value) == _input.get_type())
def test_after_getting_inputs(self):
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body", "direct",
13, 12]
for index, _input in enumerate(example_inputs):
self.amqp_random_payload_fuzzer.inputs[index].set_value(_input)
# Previously it should not be set
self.assertIsNone(self.amqp_random_payload_fuzzer.connection)
super(AMQPRandomPayloadFuzzingAttack, self.amqp_random_payload_fuzzer).run()
inputs = self.amqp_random_payload_fuzzer.get_inputs()
for index, _input in enumerate(inputs):
value = getattr(self.amqp_random_payload_fuzzer, _input.get_name())
self.assertEqual(example_inputs[index], value)
def test_invalid_fuzzing_turn(self):
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body", "direct",
1, 11]
for index, _input in enumerate(example_inputs):
self.amqp_random_payload_fuzzer.inputs[index].set_value(_input)
super(AMQPRandomPayloadFuzzingAttack, self.amqp_random_payload_fuzzer).run()
try:
self.amqp_random_payload_fuzzer.pre_attack_init()
except AssertionError as e:
self.assertTrue(True)
def test_random_payload_fuzzing_attack(self):
def run_attack():
example_inputs = ["localhost", "peniot-queue", "peniot-exchange", "peniot-routing-key", "peniot-body",
"direct", 5, 1]
for index, _input in enumerate(example_inputs):
self.amqp_random_payload_fuzzer.inputs[index].set_value(_input)
try:
self.amqp_random_payload_fuzzer.run()
except Exception as e:
self.assertTrue(False)
print "* If server is not initialized this test will not execute properly."
p = multiprocessing.Process(target=run_attack, name=self.amqp_random_payload_fuzzer.get_attack_name())
p.start()
time.sleep(15)
if p.is_alive():
p.terminate()
p.join()
if __name__ == '__main__':
unittest.main()
================================================
FILE: src/protocols/AMQP/examples/__init__.py
================================================
"""
This package contains the following functionalities:
1) AMQP Sender Example
2) AMQP Receiver Example
"""
================================================
FILE: src/protocols/AMQP/examples/receiver_example.py
================================================
import pika
import argparse
import logging
import signal
import sys
import time
DEFAULT_BROKER_HOST = "localhost"
DEFAULT_QUEUE_NAME = "peniot-queue"
DEFAULT_EXCHANGE = "peniot-exchange"
DEFAULT_ROUTING_KEY = "peniot-routing-key"
DEFAULT_BODY = "peniot-body"
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("AMQP Receiver Example")
global_connection = None
"""
AMQP Example Receiver
"""
def signal_handler(sig, frame):
global global_connection
logger.info("Connection will be closed")
if global_connection is not None:
global_connection.close()
sys.exit(0)
def callback(ch, method, properties, body):
logger.info("Received %r" % body)
def receive_procedure(channel_to_receive, queue_name=DEFAULT_QUEUE_NAME):
"""
Sending procedure for AMQP protocol
:param channel_to_receive: Channel means which is created given host name
:param queue_name: Queue from which consume message
:return: None
"""
# Signal handler to exit from function
signal.signal(signal.SIGINT, signal_handler)
# Start consuming
channel_to_receive.basic_consume(callback, queue=queue_name, no_ack=True)
channel_to_receive.start_consuming()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-b", "--broker", help="Broker host name or IP address", default=DEFAULT_BROKER_HOST)
parser.add_argument("-q", "--queue", help="Queue name to subscribe", default=DEFAULT_QUEUE_NAME)
parser.add_argument("-e", "--exchange", help="Name of exchange", default=DEFAULT_EXCHANGE)
parser.add_argument("-r", "--routing_key", help="Routing key (endpoint)", default=DEFAULT_ROUTING_KEY)
parser.add_argument("-c", "--content", help="Content of message body", default=DEFAULT_BODY)
args = parser.parse_args()
# Get connection and channel
connection = pika.BlockingConnection(pika.ConnectionParameters(host=args.broker))
global_connection = connection
channel = connection.channel()
channel.queue_bind(queue=args.queue, exchange=args.exchange, routing_key=args.routing_key)
# Start sending procedure
receive_procedure(channel, args.queue)
================================================
FILE: src/protocols/AMQP/examples/sender_example.py
================================================
import pika
import argparse
import logging
import signal
import sys
import time
DEFAULT_BROKER_HOST = "localhost"
DEFAULT_QUEUE_NAME = "peniot-queue"
DEFAULT_EXCHANGE = "peniot-exchange"
DEFAULT_ROUTING_KEY = "peniot-routing-key"
DEFAULT_BODY = "peniot-body"
DEFAULT_EXCHANGE_TYPE = "direct"
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s : %(message)s")
logger = logging.getLogger("AMQP Sender Example")
global_connection = None
"""
AMQP Example Sender
"""
def signal_handler(sig, frame):
global global_connection
logger.info("Connection will be closed")
if global_connection is not None:
global_connection.close()
sys.exit(0)
def send_procedure(channel_to_send, exchange=DEFAULT_EXCHANGE, routing_key=DEFAULT_ROUTING_KEY, body=DEFAULT_BODY):
"""
Sending procedure for AMQP protocol
:param channel_to_send: Channel means which is created given host name
:param exchange: Name of exchange
:param routing_key: Routing key which is similar to endpoint this context
:param body: Body of messages
:return: None
"""
# Signal handler to exit from function
signal.signal(signal.SIGINT, signal_handler)
publish_content = 0
while True:
channel_to_send.basic_publish(exchange=exchange, routing_key=routing_key, body=body + " " + str(publish_content))
time.sleep(2)
publish_content += 1
logger.info("Message {0} is published".format(publish_content))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-b", "--broker", help="Broker host name or IP address", default=DEFAULT_BROKER_HOST)
parser.add_argument("-q", "--queue", help="Queue name to subscribe", default=DEFAULT_QUEUE_NAME)
parser.add_argument("-e", "--exchange", help="Name of exchange", default=DEFAULT_EXCHANGE)
parser.add_argument("-r", "--routing_key", help="Routing key (endpoint)", default=DEFAULT_ROUTING_KEY)
parser.add_argument("-c", "--content", help="Content of message body", default=DEFAULT_BODY)
parser.add_argument("-x", "--exchange_type", help="Type of exchange", default=DEFAULT_EXCHANGE_TYPE)
args = parser.parse_args()
# Get connection and channel
connection = pika.BlockingConnection(pika.ConnectionParameters(host=args.broker))
global_connection = connection
channel = connection.channel()
# Create exchange
channel.exchange_declare(exchange=args.exchange, exchange_type=DEFAULT_EXCHANGE_TYPE)
# Define queue to store
channel.queue_declare(queue=args.queue)
# Start sending procedure
send_procedure(channel, args.exchange, args.routing_key, args.content)
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/.gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.pcap
logs/
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/API Manifest.txt
================================================
API Manifest.txt
documentation.html
example.py
LICENSE.txt
Nordic Semiconductor Sniffer API Guide.pdf
sniffer_uart_protocol.xlsx
wireshark_dissector_source
packet-btle.c
packet-nordic_ble.c
SnifferAPI
CaptureFiles.py
Devices.py
Exceptions.py
Logger.py
myVersion.py
Notifications.py
Packet.py
Sniffer.py
SnifferCollector.py
UART.py
Version.py
__init__.py
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/LICENSE.txt
================================================
All files in this package is released under the license below, except the
Wireshark dissector source files packet-nordic_ble.c and packet-btle.c.
The Wireshark dissector source files are released under the
GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
=
Copyright (c) 2014, Nordic Semiconductor ASA
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/README.md
================================================
# Python API for Bluefruit LE Sniffer
This repository contains the Python API for Adafruit's Bluefruit LE Sniffer, and our easy to use API wrapper.
It has been tested on the following platforms using Python 2.7:
- OSX 10.10
- Windows 7 x64
- Ubuntu 14.04
## Related Links
Bluefruit LE Sniffer product page: https://www.adafruit.com/product/2269
Bluefruit LE Sniffer Learning Guide: https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-sniffer/introduction
# Sniffer Python Wrapper
Running sniffer.py in this folder on the Bluefruit LE Friend Sniffer Edition board will cause the device to scan for Bluetooth LE devices in range, and log any data from the selected device to a libpcap file (in `logs/capture.pcap`) that can be opened in Wireshark.
The current example does not enable live streaming of data directly into Wireshark via named pipes since this would require a pre-compiled utility for each platform, but it should be possible to implement this on your platform if required.
## Using sniffer.py
To use sniffer.py, simply specify the serial port where the sniffer can be found (ex. `COM14` on Windows, `/dev/tty.usbmodem1412311` on OS X, `/dev/ttyACM0` or Linux, etc.):
```
python sniffer.py /dev/tty.usbmodem1412311
```
**Note:** You will need to run python with `sudo` on Linux to allow the log file to be created, so `sudo python sniffer.py /dev/ttyACM0`, etc..
This will create a new log file and start scanning for BLE devices, which should result in the following menu:
```
$ python sniffer.py /dev/tty.usbmodem1412311
Logging data to logs/capture.pcap
Connecting to sniffer on /dev/tty.usbmodem1412311
Scanning for BLE devices (5s) ...
Found 2 BLE devices:
[1] "" (14:99:E2:05:29:CF, RSSI = -85)
[2] "" (E7:0C:E1:BE:87:66, RSSI = -49)
Select a device to sniff, or '0' to scan again
>
```
Simply select the device you wish to sniff, and it will start logging traffic from the specified device.
Type **CTRL+C** to stop sniffing and quit the application, closing the libpcap log file.
**NOTE:** You may need to remove the sniffer and re-insert it before starting a new session if you see any unusual error messages running sniffer.py.
## Requirements
This Python script was written and tested on **Python 2.7.6**, and will require that both Python 2.7 and **pySerial** are installed on your system.
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/CaptureFiles.py
================================================
from __future__ import absolute_import
import time
import os
import logging
from . import Logger
LINKTYPE_BLUETOOTH_LE_LL = 251
LINKTYPE_NORDIC_BLE = 157
MAGIC_NUMBER = 0xa1b2c3d4
VERSION_MAJOR = 2
VERSION_MINOR = 4
THISZONE = 0
SIGFIGS = 0
SNAPLEN = 0xFFFF
NETWORK = LINKTYPE_NORDIC_BLE
globalHeaderString = [
((MAGIC_NUMBER >> 0) & 0xFF),
((MAGIC_NUMBER >> 8) & 0xFF),
((MAGIC_NUMBER >> 16) & 0xFF),
((MAGIC_NUMBER >> 24) & 0xFF),
((VERSION_MAJOR >> 0) & 0xFF),
((VERSION_MAJOR >> 8) & 0xFF),
((VERSION_MINOR >> 0) & 0xFF),
((VERSION_MINOR >> 8) & 0xFF),
((THISZONE >> 0) & 0xFF),
((THISZONE >> 8) & 0xFF),
((THISZONE >> 16) & 0xFF),
((THISZONE >> 24) & 0xFF),
((SIGFIGS >> 0) & 0xFF),
((SIGFIGS >> 8) & 0xFF),
((SIGFIGS >> 16) & 0xFF),
((SIGFIGS >> 24) & 0xFF),
((SNAPLEN >> 0) & 0xFF),
((SNAPLEN >> 8) & 0xFF),
((SNAPLEN >> 16) & 0xFF),
((SNAPLEN >> 24) & 0xFF),
((NETWORK >> 0) & 0xFF),
((NETWORK >> 8) & 0xFF),
((NETWORK >> 16) & 0xFF),
((NETWORK >> 24) & 0xFF)
]
captureFilePath = os.path.join(Logger.logFilePath, "capture.pcap")
class CaptureFileHandler:
def __init__(self, clear=False):
self.filename = captureFilePath
self.backupFilename = self.filename+".1"
if not os.path.isfile(self.filename):
self.startNewFile()
elif os.path.getsize(self.filename) > 20000000:
self.doRollover()
if clear:
# clear file
self.startNewFile()
def startNewFile(self):
with open(self.filename, "wb") as f:
f.write(bytearray(globalHeaderString))
def doRollover(self):
try:
os.remove(self.backupFilename)
except: # noqa: E722
logging.exception("capture file rollover remove backup failed")
try:
os.rename(self.filename, self.backupFilename)
self.startNewFile()
except: # noqa: E722
logging.exception("capture file rollover failed")
def readLine(self, lineNum):
line = ""
with open(self.filename, "r") as f:
f.seek(lineNum)
line = f.readline()
return line
def readAll(self):
text = ""
with open(self.filename, "r") as f:
text = f.read()
return text
def writeString(self, msgString):
with open(self.filename, "ab") as f:
f.write(msgString)
def writeList(self, msgList):
self.writeString(bytearray(msgList))
def writePacketList(self, packetList):
self.writeList(self.makePacketHeader(len(packetList)) + packetList)
def writePacket(self, packet):
self.writePacketList([packet.boardId] + packet.getList())
def makePacketHeader(self, length):
timeNow = time.time()
TS_SEC = int(timeNow)
TS_USEC = int((timeNow-TS_SEC)*1000000)
INCL_LENGTH = length
ORIG_LENGTH = length
headerString = [
((TS_SEC >> 0) & 0xFF),
((TS_SEC >> 8) & 0xFF),
((TS_SEC >> 16) & 0xFF),
((TS_SEC >> 24) & 0xFF),
((TS_USEC >> 0) & 0xFF),
((TS_USEC >> 8) & 0xFF),
((TS_USEC >> 16) & 0xFF),
((TS_USEC >> 24) & 0xFF),
((INCL_LENGTH >> 0) & 0xFF),
((INCL_LENGTH >> 8) & 0xFF),
((INCL_LENGTH >> 16) & 0xFF),
((INCL_LENGTH >> 24) & 0xFF),
((ORIG_LENGTH >> 0) & 0xFF),
((ORIG_LENGTH >> 8) & 0xFF),
((ORIG_LENGTH >> 16) & 0xFF),
((ORIG_LENGTH >> 24) & 0xFF)
]
return headerString
def toList(myString):
myList = []
for c in myString:
myList += [ord(c)]
return myList
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Devices.py
================================================
from __future__ import absolute_import
from . import Notifications
import logging
class DeviceList(Notifications.Notifier):
def __init__(self, *args, **kwargs):
Notifications.Notifier.__init__(self, *args, **kwargs)
logging.info("args: " + str(args))
logging.info("kwargs: " + str(kwargs))
self.devices = []
def __len__(self):
return len(self.devices)
def __repr__(self):
return "Sniffer Device List: "+str(self.asList())
def clear(self):
self.devices = []
def appendOrUpdate(self, newDevice):
existingDevice = self.find(newDevice)
# logging.info("appendOrUpdate")
# Add device to the list of devices being displayed, but only if CRC is OK
if existingDevice is None:
self.append(newDevice)
else:
updated = False
if (newDevice.name != "") and (existingDevice.name == ""):
existingDevice.name = newDevice.name
updated = True
if (newDevice.RSSI < (newDevice.RSSI - 5)) or (existingDevice.RSSI > (newDevice.RSSI+2)): # noqa: E501
existingDevice.RSSI = newDevice.RSSI
updated = True
if updated:
self.notify("DEVICE_UPDATED", existingDevice)
# self.updateDeviceDisplay()
def append(self, device):
self.devices.append(device)
self.notify("DEVICE_ADDED", device)
def find(self, id):
# logging.info("find type: %s" % str(id.__class__.__name__))
if type(id) == list:
for dev in self.devices:
if dev.address == id:
return dev
elif type(id) == int:
return self.devices[id]
elif type(id) == str:
for dev in self.devices:
if dev.name in [id, '"'+id+'"']:
return dev
elif id.__class__.__name__ == "Device":
# logging.info("find Device")
return self.find(id.address)
return None
def remove(self, id):
if type(id) == list: # address
device = self.devices.pop(self.devices.index(self.find(id)))
elif type(id) == int:
device = self.devices.pop(id)
elif type(id) == Device:
device = self.devices.pop(self.devices.index(self.find(id.address)))
self.notify("DEVICE_REMOVED", device)
# self.updateDeviceDisplay()
# def getSelected(self):
# for dev in self.devices:
# if dev.selected:
# return dev
# if len(self.devices) == 1:
# self.devices[0].selected = True
# else:
# return None
def index(self, device):
index = 0
for dev in self.devices:
if dev.address == device.address:
return index
index += 1
return None
# def setSelected(self, device):
# if device in self.devices:
# for dev in self.devices:
# dev.selected = False
# device.selected = True
# self.notify("DEVICE_SELECTED", device)
def setFollowed(self, device):
if device in self.devices:
for dev in self.devices:
dev.followed = False
device.followed = True
self.notify("DEVICE_FOLLOWED", device)
# def incrementSelected(self, step = 1):
# if len(self.devices) > 0:
# self.setSelected(self.find((self.index(self.getSelected())+step)%len(self.devices)))
def asList(self):
return self.devices[:]
class Device:
def __init__(self, address, name, RSSI, txAdd=1):
self.address = address
self.txAdd = txAdd
self.name = name
self.RSSI = RSSI
# self.selected = selected
self.followed = False
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Exceptions.py
================================================
class SnifferTimeout(Exception):
pass
class UARTPacketError(Exception):
pass
class InvalidPacketException(Exception):
pass
# Internal Use
class SnifferWatchDogTimeout(SnifferTimeout):
pass
# Internal Use
class ExitCodeException(Exception):
pass
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Logger.py
================================================
from __future__ import absolute_import
from __future__ import print_function
import time
import os
import logging
import traceback
import threading
import logging.handlers as logHandlers
from six.moves import range
#################################################################
# This file contains the logger. To log a line, simply write #
# 'logging.[level]("whatever you want to log")' #
# [level] is one of {info, debug, warning, error, critical, #
# exception} #
# See python logging documentation #
# As long as Logger.initLogger has been called beforehand, this #
# will result in the line being appended to the log file #
#################################################################
try:
logFilePath = os.path.join(
os.getenv('appdata'), 'Nordic Semiconductor', 'Sniffer', 'logs')
except AttributeError:
logFilePath = "logs"
logFileName = os.path.join(logFilePath, 'log.txt')
logHandler = None
logFlusher = None
myMaxBytes = 1000000
# Ensure that the directory we are writing the log file to exists.
# Create our logfile, and write the timestamp in the first line.
def initLogger():
try:
# First, make sure that the directory exists
if not os.path.isdir(logFilePath):
os.makedirs(logFilePath)
# If the file does not exist, create it, and save the timestamp
if not os.path.isfile(logFileName):
with open(logFileName, "wb") as f:
f.write('{0}{1}'.format(time.time(), os.linesep).encode())
global logHandler
global logFlusher
logHandler = MyRotatingFileHandler(
logFileName, mode='a', maxBytes=myMaxBytes, backupCount=3)
logFormatter = logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s', datefmt='%d-%b-%Y %H:%M:%S (%z)')
logHandler.setFormatter(logFormatter)
logger = logging.getLogger()
logger.addHandler(logHandler)
logger.setLevel(logging.INFO)
logFlusher = LogFlusher(logHandler)
except: # noqa: 722
print("LOGGING FAILED")
print(traceback.format_exc())
raise
def shutdownLogger():
logging.shutdown()
# Clear the log (typically after it has been sent on email)
def clearLog():
try:
logHandler.doRollover()
except: # noqa: 722
print("LOGGING FAILED")
raise
# Returns the timestamp residing on the first line of the logfile.
# Used for checking the time of creation
def getTimestamp():
try:
with open(logFileName, "r") as f:
f.seek(0)
return f.readline()
except: # noqa: 722
print("LOGGING FAILED")
def addTimestamp():
try:
with open(logFileName, "a") as f:
f.write(str(time.time()) + os.linesep)
except: # noqa: 722
print("LOGGING FAILED")
# Returns the entire content of the logfile. Used when sending emails
def readAll():
try:
text = ""
with open(logFileName, "r") as f:
text = f.read()
return text
except: # noqa: 722
print("LOGGING FAILED")
class MyRotatingFileHandler(logHandlers.RotatingFileHandler):
def doRollover(self):
try:
logHandlers.RotatingFileHandler.doRollover(self)
addTimestamp()
self.maxBytes = myMaxBytes
except: # noqa: 722
# There have been permissions issues with the log files.
self.maxBytes += int(myMaxBytes/2)
# logging.exception("log rollover error")
class LogFlusher(threading.Thread):
def __init__(self, logHandler):
threading.Thread.__init__(self)
self.daemon = True
self.handler = logHandler
self.exit = False
self.start()
def run(self):
while not self.exit:
time.sleep(10)
self.doFlush()
def doFlush(self):
self.handler.flush()
os.fsync(self.handler.stream.fileno())
def stop(self):
self.exit = True
if __name__ == '__main__':
initLogger()
for i in range(50):
logging.info("test log no. "+str(i))
print("test log no. ", i)
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Notifications.py
================================================
from __future__ import absolute_import
import threading
class Notification():
def __init__(self, key, msg=None):
if type(key) is not str:
raise TypeError("Invalid notification key: "+str(key))
self.key = key
self.msg = msg
def __repr__(self):
return "Notification (key: %s, msg: %s)" % (str(self.key), str(self.msg))
class Notifier():
def __init__(self, callbacks=[]):
self.callbacks = {}
self.callbackLock = threading.RLock()
# logging.info("callbacks: "+ str(callbacks))
for callback in callbacks:
self.subscribe(*callback)
# logging.info(self.callbacks)
def subscribe(self, key, callback):
with self.callbackLock:
if callback not in self.getCallbacks(key):
self.getCallbacks(key).append(callback)
def getCallbacks(self, key):
with self.callbackLock:
# logging.info(self.callbacks)
if key not in self.callbacks:
self.callbacks[key] = []
return self.callbacks[key]
def notify(self, key=None, msg=None, notification=None):
# logging.info(self.callbacks)
with self.callbackLock:
if notification is None:
notification = Notification(key, msg)
for callback in self.getCallbacks(notification.key):
callback(notification)
for callback in self.getCallbacks("*"):
callback(notification)
# logging.info("sending notification: %s" % str(notification))
def passOnNotification(self, notification):
self.notify(notification=notification)
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Packet.py
================================================
from __future__ import absolute_import
from . import UART, Exceptions, Notifications
import time
import logging
import os
import sys
import serial
from six.moves import range
SLIP_START = 0xAB
SLIP_END = 0xBC
SLIP_ESC = 0xCD
SLIP_ESC_START = SLIP_START+1
SLIP_ESC_END = SLIP_END+1
SLIP_ESC_ESC = SLIP_ESC+1
REQ_FOLLOW = 0x00
RESP_FOLLOW = 0x01
EVENT_DEVICE = 0x02
REQ_SINGLE_PACKET = 0x03
RESP_SINGLE_PACKET = 0x04
EVENT_CONNECT = 0x05
EVENT_PACKET = 0x06
REQ_SCAN_CONT = 0x07
RESP_SCAN_CONT = 0x08
EVENT_DISCONNECT = 0x09
EVENT_ERROR = 0x0A
EVENT_EMPTY_DATA_PACKET = 0x0B
SET_TEMPORARY_KEY = 0x0C
PING_REQ = 0x0D
PING_RESP = 0x0E
TEST_COMMAND_ID = 0x0F
TEST_RESULT_ID = 0x10
UART_TEST_START = 0x11
UART_DUMMY_PACKET = 0x12
SWITCH_BAUD_RATE_REQ = 0x13
SWITCH_BAUD_RATE_RESP = 0x14
UART_OUT_START = 0x15
UART_OUT_STOP = 0x16
SET_ADV_CHANNEL_HOP_SEQ = 0x17
GO_IDLE = 0xFE
ADV_ACCESS_ADDRESS = [0xD6, 0xBE, 0x89, 0x8E]
SYNCWORD_POS = 0
HEADER_LEN_POS = 0
PAYLOAD_LEN_POS = HEADER_LEN_POS+1
PROTOVER_POS = PAYLOAD_LEN_POS+1
PACKETCOUNTER_POS = PROTOVER_POS+1
ID_POS = PACKETCOUNTER_POS+2
BLE_HEADER_LEN_POS = ID_POS+1
FLAGS_POS = BLE_HEADER_LEN_POS+1
CHANNEL_POS = FLAGS_POS+1
RSSI_POS = CHANNEL_POS+1
EVENTCOUNTER_POS = RSSI_POS+1
TIMESTAMP_POS = EVENTCOUNTER_POS+2
BLEPACKET_POS = TIMESTAMP_POS+4
TXADD_POS = BLEPACKET_POS + 4
TXADD_MSK = 0x40
PAYLOAD_POS = BLE_HEADER_LEN_POS
HEADER_LENGTH = 6
BLE_HEADER_LENGTH = 10
PROTOVER = 1
ADV_TYPE_ADV_IND = 0x0
ADV_TYPE_ADV_DIRECT_IND = 0x1
ADV_TYPE_ADV_NONCONN_IND = 0x2
ADV_TYPE_ADV_DISCOVER_IND = 0x6
ADV_TYPE_SCAN_REQ = 0x3
ADV_TYPE_SCAN_RSP = 0x4
ADV_TYPE_CONNECT_REQ = 0x5
VALID_ADV_CHANS = [37, 38, 39]
class PacketReader(Notifications.Notifier):
def __init__(self, portnum=None, callbacks=[]):
Notifications.Notifier.__init__(self, callbacks)
self.portnum = portnum
self.exit = False
try:
self.uart = UART.Uart(portnum)
except serial.SerialException as e:
logging.exception("Error opening UART.")
self.uart = UART.Uart()
self.packetCounter = 0
self.lastReceivedPacketCounter = 0
self.lastReceivedPacket = None
# self.states = {}
def setup(self):
self.findSerialPort()
self.uart.ser.port = self.portnum
self.uart.ser.open
def doExit(self):
self.exit = True
if self.uart.ser is not None:
self.uart.ser.close()
# This function takes a byte list, encode it in SLIP protocol and return the encoded byte list
def encodeToSLIP(self, byteList):
tempSLIPBuffer = []
tempSLIPBuffer.append(SLIP_START)
for i in byteList:
if i == SLIP_START:
tempSLIPBuffer.append(SLIP_ESC)
tempSLIPBuffer.append(SLIP_ESC_START)
elif i == SLIP_END:
tempSLIPBuffer.append(SLIP_ESC)
tempSLIPBuffer.append(SLIP_ESC_END)
elif i == SLIP_ESC:
tempSLIPBuffer.append(SLIP_ESC)
tempSLIPBuffer.append(SLIP_ESC_ESC)
else:
tempSLIPBuffer.append(i)
tempSLIPBuffer.append(SLIP_END)
return tempSLIPBuffer
# This function uses getSerialByte() function to get SLIP encoded bytes from the serial port
# and return a decoded byte list
# Based on https://github.com/mehdix/pyslip/
def decodeFromSLIP(self, timeout=None):
dataBuffer = []
startOfPacket = False
endOfPacket = False
while not startOfPacket:
startOfPacket = (self.getSerialByte(timeout) == SLIP_START)
while not endOfPacket:
serialByte = self.getSerialByte(timeout)
if serialByte == SLIP_END:
endOfPacket = True
elif serialByte == SLIP_ESC:
serialByte = self.getSerialByte()
if serialByte == SLIP_ESC_START:
dataBuffer.append(SLIP_START)
elif serialByte == SLIP_ESC_END:
dataBuffer.append(SLIP_END)
elif serialByte == SLIP_ESC_ESC:
dataBuffer.append(SLIP_ESC)
else:
raise Exceptions.UARTPacketError(
"Unexpected character after SLIP_ESC: %d." % serialByte)
else:
dataBuffer.append(serialByte)
return dataBuffer
# This function read byte chuncks from the serial port and return one byte at a time
# Based on https://github.com/mehdix/pyslip/
def getSerialByte(self, timeout=None):
serialByte = self.uart.readByte(timeout)
if len(serialByte) != 1:
raise Exceptions.SnifferTimeout("Packet read timed out.")
return ord(serialByte)
def handlePacketHistory(self, packet):
# Reads and validates packet counter
if self.lastReceivedPacket and (
packet.packetCounter != (self.lastReceivedPacket.packetCounter+1)) and (
self.lastReceivedPacket.packetCounter != 0):
logging.info("gap in packets, between {} and {}. packet before: {}, packet after: {}"
.format(
self.lastReceivedPacket.packetCounter,
str(packet.packetCounter),
str(self.lastReceivedPacket.packetList),
str(packet.packetList)
))
self.lastReceivedPacket = packet
def getPacket(self, timeout=None):
packetList = []
try:
packetList = self.decodeFromSLIP(timeout)
except Exceptions.UARTPacketError:
logging.exception("")
return None
else:
packet = Packet(packetList)
if packet.valid:
self.handlePacketHistory(packet)
return packet
def useByteQueue(self, useByteQueue=True):
self.uart.useByteQueue = useByteQueue
def getByteQueue(self):
return self.uart.byteQueue
def sendPacket(self, id, payload, timeout=None):
packetList = [HEADER_LENGTH] + [len(payload)] + [PROTOVER] + \
toLittleEndian(self.packetCounter, 2) + [id] + payload
pkt = self.encodeToSLIP(packetList)
self.packetCounter += 1
self.uart.writeList(pkt, timeout)
def sendScan(self, timeout=None):
self.sendPacket(REQ_SCAN_CONT, [], timeout)
def sendFollow(self, addr, txAdd=1, followOnlyAdvertisements=False, timeout=None):
# TxAdd is a single byte (0 or 1) so we just append it to the address.
# addr.append(txAdd)
self.sendPacket(REQ_FOLLOW, addr+[followOnlyAdvertisements], timeout)
def sendPingReq(self, timeout=1):
self.sendPacket(PING_REQ, [], timeout)
def sendTK(self, TK, timeout=None):
if (len(TK) < 16):
TK = [0] * (16-len(TK)) + TK
else:
TK = TK[:16]
self.sendPacket(SET_TEMPORARY_KEY, TK, timeout)
logging.info("Sent key value to sniffer: "+str(TK))
self.notify("TK_SENT", {"TK": TK})
return TK
def sendSwitchBaudRate(self, newBaudRate, timeout=None):
self.sendPacket(SWITCH_BAUD_RATE_REQ, toLittleEndian(newBaudRate, 4), timeout)
def switchBaudRate(self, newBaudRate):
self.uart.switchBaudRate(newBaudRate)
def sendHopSequence(self, hopSequence):
for chan in hopSequence:
if chan not in VALID_ADV_CHANS:
raise Exceptions.InvalidAdvChannel("%s is not an adv channel" % str(chan))
payload = [len(hopSequence)] + hopSequence + [37]*(3-len(hopSequence))
self.sendPacket(SET_ADV_CHANNEL_HOP_SEQ, payload)
self.notify("NEW_ADV_HOP_SEQ", {"hopSequence": hopSequence})
def sendGoIdle(self, timeout=None):
self.sendPacket(GO_IDLE, [], timeout)
def findSerialPort(self):
foundPort = False
iPort = 0 # To avoid COM1 (iPort=0).
nTicks = 0
trials = 10
# comports = self.findSeggerComPorts().keys()
if self.portnum is not None:
self.notify("INFO_PRESET")
else:
self.notify("INFO_NO_PRESET")
readTimeout = 1
iPort = self.portnum if self.portnum is not None else 1
while not foundPort and not self.exit:
try:
self.uart.ser.port = iPort
try:
self.uart.ser.open()
except:
pass
self.sendPingReq()
startTime = time.time()
continueLoop = True
packetCounter = 0
while continueLoop and (time.time() < (startTime+1)):
packet = self.getPacket(timeout=readTimeout)
if packet is None:
continueLoop = False
raise Exception("None packet")
elif packet.id == 0x0E:
continueLoop = False
fwversion = packet.version
self.portnum = self.uart.ser.portstr
self.notify("COMPORT_FOUND", {"comPort": self.portnum})
self.fwversion = fwversion
return
else:
packetCounter += 1
if continueLoop:
raise Exception("No packet with correct id. Received " +
str(packetCounter)+" packets.")
except Exception as e:
if "The system cannot find the file specified." not in str(e):
# logging.exception("Error on COM"+str(iPort+1)+": "+str(e))
logging.info("Error on port " + str(iPort) + ". file: " +
os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename) +
", line " + str(sys.exc_info()[2].tb_lineno) + ": "+str(e))
# logging.exception("error")
trials = trials + 1
if (trials>9):
self.doExit() #Try to open the port for some time, if can't just exit
try:
if self.uart.ser is not None:
self.uart.ser.close()
except: # noqa: E722
logging.exception("could not close UART")
if self.portnum is None:
if type(iPort) != int:
iPort = 0
iPort += 1
iPort = (iPort % 256)
if self.portnum is not None or (iPort % 64) == 0:
nTicks += 1
self.notify("DEVICE_DISCOVERY_TICK", {"tickNumber": nTicks})
if readTimeout < 3:
readTimeout += 0.1
# logging.info("iPort: " +str(iPort))
# logging.info("self.portnum: " +str(self.portnum))
if self.portnum is not None:
time.sleep(0.7)
else:
time.sleep(0.01)
return (None, None)
class Packet:
def __init__(self, packetList):
try:
if packetList == []:
raise Exceptions.InvalidPacketException(
"packet list not valid: %s" % str(packetList))
self.packetList = packetList
self.readStaticHeader(packetList)
self.readDynamicHeader(packetList)
self.readPayload(packetList)
except Exceptions.InvalidPacketException as e:
logging.error("Invalid packet: %s" % str(e))
self.OK = False
self.valid = False
except: # noqa: E722
logging.exception("packet creation error")
logging.info("packetList: " + str(packetList))
self.OK = False
self.valid = False
def __repr__(self):
return "UART packet, type: "+str(self.id)+", PC: "+str(self.packetCounter)
def readStaticHeader(self, packetList):
self.headerLength = packetList[HEADER_LEN_POS]
self.payloadLength = packetList[PAYLOAD_LEN_POS]
self.protover = packetList[PROTOVER_POS]
def readDynamicHeader(self, packetList):
self.header = packetList[0:self.headerLength]
if self.headerLength == HEADER_LENGTH:
self.packetCounter = parseLittleEndian(
packetList[PACKETCOUNTER_POS:PACKETCOUNTER_POS+2])
self.id = packetList[ID_POS]
else:
logging.info("incorrect header length: %d" % self.headerLength)
def readPayload(self, packetList):
self.blePacket = None
self.OK = False
if not self.validatePacketList(packetList):
raise Exceptions.InvalidPacketException("packet list not valid: %s" % str(packetList))
else:
self.valid = True
self.payload = packetList[PAYLOAD_POS:PAYLOAD_POS+self.payloadLength]
if self.id == EVENT_PACKET:
try:
self.bleHeaderLength = packetList[BLE_HEADER_LEN_POS]
if self.bleHeaderLength == BLE_HEADER_LENGTH:
self.flags = packetList[FLAGS_POS]
self.readFlags()
self.channel = packetList[CHANNEL_POS]
self.rawRSSI = packetList[RSSI_POS]
self.RSSI = -self.rawRSSI
self.txAdd = packetList[TXADD_POS] & TXADD_MSK
self.eventCounter = parseLittleEndian(
packetList[EVENTCOUNTER_POS:EVENTCOUNTER_POS+2])
self.timestamp = parseLittleEndian(packetList[TIMESTAMP_POS:TIMESTAMP_POS+2])
# self.payload = packetList[13:(4+self.length)]
# The hardware adds a padding byte which isn't sent on air.
# The following removes it.
self.packetList.pop(BLEPACKET_POS+6)
self.payloadLength -= 1
if packetList[PAYLOAD_LEN_POS] > 0:
packetList[PAYLOAD_LEN_POS] -= 1
if self.OK:
try:
self.blePacket = BlePacket(packetList[BLEPACKET_POS:])
except: # noqa: E722
logging.exception("blePacket error")
except: # noqa: E722
# malformed packet
logging.exception("packet error")
self.OK = False
elif self.id == PING_RESP:
self.version = parseLittleEndian(self.packetList[PAYLOAD_POS:PAYLOAD_POS+2])
elif self.id == SWITCH_BAUD_RATE_RESP or self.id == SWITCH_BAUD_RATE_REQ:
self.baud_rate = parseLittleEndian(packetList[PAYLOAD_POS:PAYLOAD_POS+4])
elif self.id == TEST_RESULT_ID:
self.testId = packetList[PAYLOAD_POS]
self.testLength = packetList[PAYLOAD_POS+1]
self.testPayload = packetList[PAYLOAD_POS+2:]
def readFlags(self):
self.crcOK = not not (self.flags & 1)
self.direction = not not (self.flags & 2)
self.encrypted = not not (self.flags & 4)
self.micOK = not not (self.flags & 8)
self.OK = self.crcOK and (self.micOK or not self.encrypted)
def getList(self):
return self.packetList
def validatePacketList(self, packetList):
try:
if (packetList[PAYLOAD_LEN_POS] + packetList[HEADER_LEN_POS]) == len(packetList):
return True
else:
return False
except: # noqa: E722
logging.exception("Invalid packet: %s" % str(packetList))
return False
class BlePacket():
def __init__(self, packetList):
self.extractAccessAddress(packetList)
if self.accessAddress == ADV_ACCESS_ADDRESS:
self.extractAdvType(packetList)
self.extractAdvAddress(packetList)
self.extractName(packetList)
self.extractLength(packetList)
self.payload = packetList[6:]
def __repr__(self):
return "BLE packet, AAddr: "+str(self.accessAddress)
def extractAccessAddress(self, packetList):
self.accessAddress = packetList[0:4]
def extractAdvType(self, packetList):
self.advType = (packetList[4] & 15)
def extractAdvAddress(self, packetList):
addr = None
if (self.advType == 0 or self.advType == 1 or self.advType == 2 or self.advType == 4
or self.advType == 6):
addrType = not not packetList[4] & 64
addr = packetList[6:12]
addr.reverse()
addr += [addrType]
elif (self.advType == 3 or self.advType == 5):
addrType = not not packetList[4] & 64
addr = packetList[12:18]
addr.reverse()
addr += [addrType]
self.advAddress = addr
def extractName(self, packetList):
name = ""
if (self.advType == 0 or self.advType == 2 or self.advType == 6):
i = 12
while i < len(packetList):
length = packetList[i]
if (i+length+1) > len(packetList) or length == 0:
break
type = packetList[i+1]
if type == 8 or type == 9:
nameList = packetList[i+2:i+length+1]
name = ""
for j in nameList:
name += chr(j)
i += (length+1)
name = '"'+name+'"'
elif (self.advType == 1):
name = "[ADV_DIRECT_IND]"
self.name = name # .decode(encoding="UTF-8")
def extractLength(self, packetList):
length = packetList[5]
self.length = length
def parseLittleEndian(list):
total = 0
for i in range(len(list)):
total += (list[i] << (8*i))
return total
def toLittleEndian(value, size):
list = [0]*size
for i in range(size):
list[i] = (value >> (i*8)) % 256
return list
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Sniffer.py
================================================
from __future__ import absolute_import
import sys
import os
import threading
import logging
from . import SnifferCollector
from . import Logger, Version
def initLog():
Logger.initLogger()
logging.info("--------------------------------------------------------")
logging.info("Software version: " + Version.getReadableVersionString(Version.getRevision()))
initLog()
class Sniffer(threading.Thread, SnifferCollector.SnifferCollector):
# Sniffer constructor. portnum argument is optional. If not provided,
# the software will try to locate the firwmare automatically (may take time).
# NOTE: portnum is 0-indexed, while Windows names are 1-indexed
def __init__(self, portnum=None):
threading.Thread.__init__(self)
SnifferCollector.SnifferCollector.__init__(self, portnum)
self.daemon = True
self.subscribe("COMPORT_FOUND", self.comPortFound)
# API STARTS HERE
# Get [number] number of packets since last fetch (-1 means all)
# Note that the packet buffer is limited to about 80000 packets.
# Returns: A list of Packet objects
def getPackets(self, number=-1):
return self._getPackets(number)
# Get a list of devices which are advertising in range of the Sniffer.
# Returns: A DeviceList object.
def getDevices(self):
return self._devices
# Signal the Sniffer firmware to sniff a specific device.
# "device" argument is of type Device
# if "followOnlyAdvertisements" is True the sniffer will not follow the device into a connection. # noqa: E501
# Returns nothing
def follow(self, device=None, followOnlyAdvertisements=False):
self._startFollowing(device, followOnlyAdvertisements)
# Signal the Sniffer to scan for advertising devices by sending the REQ_SCAN_CONT UART packet.
# This will cause it to stop sniffing any device it is sniffing at the moment.
# Returns nothing.
def scan(self):
self._startScanning()
# Send a temporary key to the sniffer to use when decrypting encrypted communication.
# Returns nothing.
def sendTK(self, TK):
self._packetReader.sendTK(TK)
# Set the preset COM port number. Only use this during startup. Set to None to search all ports.
# Returns nothing.
def setPortnum(self, portnum):
self._portnum = portnum
self._packetReader.portnum = portnum
# Set the order in which the sniffer cycles through adv channels when following a device.
# hopSequence must be a list of length 1, 2, or 3, and each item must be either 37, 38, or 39.
# The same channel cannot occur more than once in the list.
# Returns nothing.
def setAdvHopSequence(self, hopSequence):
self._packetReader.sendHopSequence(hopSequence)
# Gracefully shut down the sniffer threads and connections.
# Returns nothing.
def doExit(self):
return self._doExit()
# NOTE: Methods with decorator @property can be used as (read-only) properties
# Example: mMissedPackets = sniffer.missedPackets
# The number of missed packets over the UART, as determined by the packet counter in the header.
@property
def missedPackets(self):
return self._missedPackets
# The number of packets which were sniffed in the last BLE connection.
# From CONNECT_REQ until link loss/termination.
@property
def packetsInLastConnection(self):
return self._packetsInLastConnection
# The packet counter value of the last received connect request.
@property
def connectEventPacketCounterValue(self):
return self._connectEventPacketCounterValue
# A Packet object containing the last received connect request.
@property
def currentConnectRequest(self):
return self._currentConnectRequest
# A boolean indicating whether the sniffed device is in a connection.
@property
def inConnection(self):
return self._inConnection
# The internal state of the sniffer.
# States are defined in SnifferCollector module. Valid values are 0-2.
@property
def state(self):
return self._state
# The COM port of the sniffer hardware. During initialization, this value is a preset.
@property
def portnum(self):
return self._portnum
# The version number of the API software.
@property
def swversion(self):
return self._swversion
# The version number of the sniffer firmware.
@property
def fwversion(self):
return self._fwversion
# API ENDS HERE
# Private method
def run(self):
try:
self._setup()
self.runSniffer()
except (KeyboardInterrupt) as e:
unused_exc_type, unused_exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
lineno = exc_tb.tb_lineno
logging.info("exiting ("+str(type(e))+" in "+fname+" at "+str(lineno)+"): "+str(e))
self.goodExit = False
except Exception as e:
logging.exception("CRASH")
self.goodExit = False
else:
self.goodExit = True
# Private method
def comPortFound(self, notification):
# logging.info("Com port found")
self._portnum = notification.msg["comPort"]
self._boardId = self._makeBoardId()
# self._packetReader.comport = self.portnum
# Private method
def runSniffer(self):
if not self._exit:
self._continuouslyPipe()
else:
self.goodExit = False
# Private method
def sendTestPacketToSniffer(self, payload):
self._sendTestPacket(payload)
# Private method
def getTestPacketFromSniffer(self):
return self._getTestPacket()
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/SnifferCollector.py
================================================
from __future__ import absolute_import
from . import Packet, Exceptions, CaptureFiles, Devices, Notifications, Version
import threading
import logging
import copy
from serial import SerialException
from six.moves import range
REQ_FOLLOW = 0x00
EVENT_FOLLOW = 0x01
EVENT_DEVICE = 0x02
REQ_SINGLE_PACKET = 0x03
RESP_SINGLE_PACKET = 0x04
EVENT_CONNECT = 0x05
EVENT_PACKET = 0x06
REQ_SCAN_CONT = 0x07
RESP_SCAN_CONT = 0x08
EVENT_DISCONNECT = 0x09
EVENT_ERROR = 0x0A
EVENT_EMPTY_DATA_PACKET = 0x0B
SET_TEMPORARY_KEY = 0x0C
PING_REQ = 0x0D
PING_RESP = 0x0E
TEST_COMMAND_ID = 0x0F
UART_TEST_START = 0x11
UART_DUMMY_PACKET = 0x12
SWITCH_BAUD_RATE_REQ = 0x13
SWITCH_BAUD_RATE_RESP = 0x14
GO_IDLE = 0xFE
STATE_INITIALIZING = 0
STATE_SCANNING = 1
STATE_FOLLOWING = 2
ADV_ACCESS_ADDRESS = [0xD6, 0xBE, 0x89, 0x8E]
class SnifferCollector(Notifications.Notifier):
def __init__(self, portnum=None, *args, **kwargs):
Notifications.Notifier.__init__(self, *args, **kwargs)
self._portnum = portnum
self._swversion = Version.getRevision()
self._fwversion = 0
self._setState(STATE_INITIALIZING)
self._captureHandler = CaptureFiles.CaptureFileHandler()
self._exit = False
self._connectionAccessAddress = None
self._packetListLock = threading.RLock()
with self._packetListLock:
self._packets = []
self._packetReader = Packet.PacketReader(
self._portnum, callbacks=[("*", self.passOnNotification)])
self._devices = Devices.DeviceList(
callbacks=[("*", self.passOnNotification)])
self._missedPackets = 0
self._packetsInLastConnection = None
self._connectEventPacketCounterValue = None
self._inConnection = False
self._currentConnectRequest = None
self._nProcessedPackets = 0
self._switchingBaudRate = False
self._attemptedBaudRates = []
self._boardId = self._makeBoardId()
def __del__(self):
self._doExit()
def _setup(self):
self._packetReader.setup()
if self._exit:
return
if self._packetReader.fwversion < self.swversion:
self.notify("OLD_FW_VERSION", {
"version": self._packetReader.fwversion})
self._fwversion = self._packetReader.fwversion
self._startScanning()
self._setState(STATE_SCANNING)
def _makeBoardId(self):
try:
boardId = int(self._packetReader.uart.ser.name.split("COM")[1])
logging.info("board ID: %d" % boardId)
except (IndexError, AttributeError):
import random
random.seed()
boardId = random.randint(0, 255)
logging.info("board ID (random): %d" % boardId)
return boardId
@property
def state(self):
return self._state
def _setState(self, newState):
self._state = newState
self.notify("STATE_CHANGE", newState)
def _switchBaudRate(self, newBaudRate):
if newBaudRate in self._packetReader.uart.ser.BAUDRATES:
self._packetReader.sendSwitchBaudRate(newBaudRate)
self._switchingBaudRate = True
self._proposedBaudRate = newBaudRate
self._attemptedBaudRates.append(newBaudRate)
def _processBLEPacket(self, packet):
packet.boardId = self._boardId
self._appendPacket(packet)
self.notify("NEW_BLE_PACKET", {"packet": packet})
self._captureHandler.writePacket(packet)
self._nProcessedPackets += 1
if packet.OK:
try:
if packet.blePacket.accessAddress == ADV_ACCESS_ADDRESS:
if self.state == STATE_FOLLOWING and packet.blePacket.advType == 5:
self._connectionAccessAddress = packet.blePacket.accessAddress
if self.state == STATE_SCANNING:
if (packet.blePacket.advType == 0
or packet.blePacket.advType == 1
or packet.blePacket.advType == 2
or packet.blePacket.advType == 4
or packet.blePacket.advType == 6
) and (packet.blePacket.advAddress is not None
) and (packet.crcOK and not packet.direction):
newDevice = Devices.Device(
address=packet.blePacket.advAddress, name=packet.blePacket.name,
RSSI=packet.RSSI, txAdd=packet.txAdd)
self._devices.appendOrUpdate(newDevice)
except Exception as e:
logging.exception("packet processing error")
self.notify("PACKET_PROCESSING_ERROR", {"errorString": str(e)})
def _continuouslyPipe(self):
while not self._exit:
try:
packet = self._packetReader.getPacket(timeout=2)
if not packet.valid:
raise Exceptions.InvalidPacketException("")
except Exceptions.SnifferTimeout as e:
logging.info(str(e))
packet = None
except (SerialException, ValueError):
logging.exception("UART read error")
logging.error("Lost contact with sniffer hardware.")
self._doExit()
except Exceptions.InvalidPacketException:
# logging.error("Continuously pipe: Invalid packet, skipping.")
pass
else:
if packet.id == EVENT_PACKET:
self._processBLEPacket(packet)
elif packet.id == EVENT_FOLLOW:
# This packet has no value for the user.
pass
elif packet.id == EVENT_CONNECT:
self._connectEventPacketCounterValue = packet.packetCounter
self._inConnection = True
# copy it because packets are eventually deleted
self._currentConnectRequest = copy.copy(self._findPacketByPacketCounter(
self._connectEventPacketCounterValue-1))
elif packet.id == EVENT_DISCONNECT:
if self._inConnection:
self._packetsInLastConnection = packet.packetCounter - \
self._connectEventPacketCounterValue
self._inConnection = False
elif packet.id == SWITCH_BAUD_RATE_RESP and self._switchingBaudRate:
self._switchingBaudRate = False
if (packet.baudRate == self._proposedBaudRate):
self._packetReader.switchBaudRate(
self._proposedBaudRate)
else:
self._switchBaudRate(packet.baudRate)
def _findPacketByPacketCounter(self, packetCounterValue):
with self._packetListLock:
for i in range(-1, -1-len(self._packets), -1):
# iterate backwards through packets
if self._packets[i].packetCounter == packetCounterValue:
return self._packets[i]
return None
def _startScanning(self):
logging.info("starting scan")
if self.state == STATE_FOLLOWING:
logging.info("Stopped sniffing device")
self._devices.clear()
self._setState(STATE_SCANNING)
self._packetReader.sendScan()
self._packetReader.sendTK([0])
def _doExit(self):
self._exit = True
self.notify("APP_EXIT")
self._packetReader.doExit()
def _startFollowing(self, device, followOnlyAdvertisements=False):
self._devices.setFollowed(device)
logging.info("Sniffing device " +
str(self._devices.index(device)) + ' - "'+device.name+'"')
self._packetReader.sendFollow(
device.address, device.txAdd, followOnlyAdvertisements)
self._setState(STATE_FOLLOWING)
def _appendPacket(self, packet):
with self._packetListLock:
if len(self._packets) > 100000:
self._packets = self._packets[20000:]
self._packets.append(packet)
def _getPackets(self, number=-1):
with self._packetListLock:
returnList = self._packets[0:number]
self._packets = self._packets[number:]
return returnList
def _sendTestPacket(self, payload):
self._packetReader.sendTestPacket(payload)
def _getTestPacket(self):
return self._packetReader.getPacket()
================================================
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/UART.py
================================================
from __future__ import absolute_import
import logging
import serial
import collections
import serial.tools.list_ports as list_ports
from . import Exceptions
class Uart:
def __init__(self, portnum=None, useByteQueue=False):
self.ser = None
try:
self.ser = serial.Serial(
port=portnum,
baudrate=460800,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=None, # seconds
writeTimeout=None,
rtscts=True
)
except Exception as e:
if self.ser:
self.ser.close()
raise
self.useByteQueue = useByteQueue
self.byteQueue = collections.deque()
# if self.ser.name != None:
# print "UART %s on port %s" % ("open" if self.ser else "closed", self.ser.name)
def __del__(self):
if self.ser:
logging.info("closing UART")
self.ser.close()
def switchBaudRate(self, newBaudRate):
self.ser.baudrate = newBaudRate
def read(self, length, timeout=None):
gitextract_1myw_xe2/
├── .gitignore
├── LICENSE
├── README.md
├── setup.py
└── src/
├── Entity/
│ ├── __init__.py
│ ├── attack.py
│ ├── attack_suite.py
│ ├── input_format.py
│ └── protocol.py
├── GUI/
│ ├── __init__.py
│ ├── custom_widgets.py
│ ├── hard_coded_texts.py
│ ├── tkinter.py
│ └── utils.py
├── Utils/
│ ├── CommonUtil/
│ │ └── __init__.py
│ ├── ExtendUtil/
│ │ ├── __init__.py
│ │ ├── export_attack_suite_template.py
│ │ ├── export_attack_template.py
│ │ ├── export_protocol_template.py
│ │ ├── export_util.py
│ │ └── import_util.py
│ ├── FilterUtil/
│ │ ├── __init__.py
│ │ └── pyshark_filter_util.py
│ ├── FuzzerUtil/
│ │ ├── __init__.py
│ │ └── radamsa_util.py
│ ├── RandomUtil/
│ │ ├── __init__.py
│ │ └── random_generated_names.py
│ ├── ReportUtil/
│ │ ├── __init__.py
│ │ └── report_generator.py
│ ├── SnifferUtil/
│ │ ├── __init__.py
│ │ └── generic_sniffer.py
│ └── __init__.py
├── __init__.py
├── captured_packets/
│ └── __init__.py
├── module_installer.py
├── peniot.py
└── protocols/
├── AMQP/
│ ├── __init__.py
│ ├── amqp_protocol.py
│ ├── amqp_scanner.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── amqp_dos_attack.py
│ │ ├── amqp_fuzzing_attack_suite.py
│ │ ├── amqp_payload_size_fuzzer.py
│ │ └── amqp_random_payload_fuzzing.py
│ └── examples/
│ ├── __init__.py
│ ├── receiver_example.py
│ └── sender_example.py
├── BLE/
│ ├── Adafruit_BLESniffer/
│ │ ├── .gitignore
│ │ ├── API Manifest.txt
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── SnifferAPI/
│ │ │ ├── CaptureFiles.py
│ │ │ ├── Devices.py
│ │ │ ├── Exceptions.py
│ │ │ ├── Logger.py
│ │ │ ├── Notifications.py
│ │ │ ├── Packet.py
│ │ │ ├── Sniffer.py
│ │ │ ├── SnifferCollector.py
│ │ │ ├── UART.py
│ │ │ ├── Version.py
│ │ │ ├── __init__.py
│ │ │ └── myVersion.py
│ │ ├── __init__.py
│ │ ├── documentation.html
│ │ ├── requirements.txt
│ │ ├── setup.cfg
│ │ ├── sniffer.py
│ │ ├── sniffer_uart_protocol.xlsx
│ │ └── wireshark_dissector_source/
│ │ ├── OSX/
│ │ │ └── readme.md
│ │ ├── packet-btle.c
│ │ └── packet-nordic_ble.c
│ ├── BLETest.py
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── ble_replay_attack.py
│ │ └── ble_sniff_attack.py
│ ├── ble_advertiser.py
│ ├── ble_device.py
│ ├── ble_protocol.py
│ ├── ble_replay_attack.py
│ ├── ble_sniff.py
│ └── ble_tools.py
├── CoAP/
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── coap_dos_attack.py
│ │ ├── coap_fuzzing_attack_suite.py
│ │ ├── coap_payload_size_fuzzer.py
│ │ ├── coap_random_payload_fuzzing.py
│ │ ├── coap_replay_attack.py
│ │ └── coap_sniff_attack.py
│ ├── coap_protocol.py
│ ├── coap_scanner.py
│ └── examples/
│ ├── __init__.py
│ ├── client_example.py
│ ├── resource_example.py
│ └── server_example.py
├── MQTT/
│ ├── __init__.py
│ ├── attacks/
│ │ ├── __init__.py
│ │ ├── mqtt_dos_attack.py
│ │ ├── mqtt_fuzzing_attack_suite.py
│ │ ├── mqtt_generation_based_fuzzing.py
│ │ ├── mqtt_payload_size_fuzzer.py
│ │ ├── mqtt_random_payload_fuzzing.py
│ │ ├── mqtt_replay_attack.py
│ │ ├── mqtt_sniff_attack.py
│ │ └── mqtt_topic_name_fuzzing.py
│ ├── examples/
│ │ ├── Demo/
│ │ │ ├── __init__.py
│ │ │ ├── demo_publisher.py
│ │ │ └── demo_subscriber.py
│ │ ├── __init__.py
│ │ ├── publisher_example.py
│ │ └── subscriber_example.py
│ ├── mqtt_protocol.py
│ └── mqtt_scanner.py
└── __init__.py
SYMBOL INDEX (756 symbols across 74 files)
FILE: src/Entity/attack.py
class Attack (line 6) | class Attack(object):
method __init__ (line 11) | def __init__(self, name, inputs, default_parameters, definition, logge...
method get_attack_name (line 24) | def get_attack_name(self):
method set_attack_name (line 27) | def set_attack_name(self, name):
method get_inputs (line 31) | def get_inputs(self):
method set_inputs (line 34) | def set_inputs(self, inputs):
method insert_input (line 38) | def insert_input(self, _input):
method get_default_parameters (line 42) | def get_default_parameters(self):
method set_default_parameters (line 45) | def set_default_parameters(self, default_parameters):
method insert_default_parameters (line 49) | def insert_default_parameters(self, _default_parameter):
method get_definition (line 53) | def get_definition(self):
method set_definition (line 56) | def set_definition(self, definition):
method set_input_value (line 59) | def set_input_value(self, input_name):
method run (line 64) | def run(self):
method stop_attack (line 70) | def stop_attack(self):
method load_default_parameters (line 73) | def load_default_parameters(self):
FILE: src/Entity/attack_suite.py
class AttackSuite (line 1) | class AttackSuite(object):
method __init__ (line 6) | def __init__(self, name, attacks):
method get_attack_suite_name (line 10) | def get_attack_suite_name(self):
method set_attack_suite_name (line 13) | def set_attack_suite_name(self, name):
method get_attacks (line 17) | def get_attacks(self):
method set_attacks (line 20) | def set_attacks(self, attacks):
method insert_attack (line 24) | def insert_attack(self, attack):
method run (line 28) | def run(self):
FILE: src/Entity/input_format.py
class InputFormat (line 1) | class InputFormat(object):
method __init__ (line 3) | def __init__(self, label_name, name, value, _type, default_value=None,...
method get_label_name (line 14) | def get_label_name(self):
method set_label_name (line 17) | def set_label_name(self, label_name):
method get_name (line 21) | def get_name(self):
method set_name (line 24) | def set_name(self, name):
method get_value (line 28) | def get_value(self):
method set_value (line 31) | def set_value(self, value):
method get_type (line 35) | def get_type(self):
method set_type (line 38) | def set_type(self, _type):
method set_mandatory (line 42) | def set_mandatory(self, mandadory):
method is_mandatory (line 46) | def is_mandatory(self):
method set_default_value (line 49) | def set_default_value(self, default_value):
method get_default_value (line 53) | def get_default_value(self):
method is_secret (line 56) | def is_secret(self):
method set_secret (line 59) | def set_secret(self, secret):
method is_from_captured_packets (line 63) | def is_from_captured_packets(self):
method set_from_captured_packets (line 66) | def set_from_captured_packets(self, from_captured_packets):
FILE: src/Entity/protocol.py
class Protocol (line 1) | class Protocol(object):
method __init__ (line 6) | def __init__(self, name, attack_suites, definition):
method get_protocol_name (line 11) | def get_protocol_name(self):
method set_protocol_name (line 14) | def set_protocol_name(self, name):
method get_attack_suites (line 18) | def get_attack_suites(self):
method set_attack_suites (line 21) | def set_attack_suites(self, attack_suites):
method get_definition (line 25) | def get_definition(self):
method set_definition (line 28) | def set_definition(self, new_def):
method insert_attack_suite (line 32) | def insert_attack_suite(self, attack_suite):
FILE: src/GUI/custom_widgets.py
class Header (line 5) | class Header(Frame):
method __init__ (line 10) | def __init__(self, parent_window):
class CustomButton (line 20) | class CustomButton(Button):
method __init__ (line 25) | def __init__(self, parent_window, text, _function, row, columnspan=Non...
class CustomLabel (line 32) | class CustomLabel(Label):
method __init__ (line 37) | def __init__(self, parent_window, text, row, column, rowspan=None, col...
class CustomRadiobutton (line 42) | class CustomRadiobutton(Radiobutton):
method __init__ (line 47) | def __init__(self, parent_window, text, row, column, sticky, variable,...
FILE: src/GUI/hard_coded_texts.py
function get_project_name (line 38) | def get_project_name():
function get_about_us (line 42) | def get_about_us():
function get_help (line 52) | def get_help():
function get_extension_help (line 65) | def get_extension_help():
function get_logger_name (line 71) | def get_logger_name():
FILE: src/GUI/tkinter.py
class HomePage (line 19) | class HomePage(Frame):
method __init__ (line 28) | def __init__(self, parent_window):
class AboutUs (line 52) | class AboutUs(Frame):
method __init__ (line 57) | def __init__(self, parent_window):
class Help (line 74) | class Help(Frame):
method __init__ (line 79) | def __init__(self, parent_window):
class ViewCapturedPackets (line 95) | class ViewCapturedPackets(Frame):
method __init__ (line 101) | def __init__(self, parent_window):
method generate_content (line 108) | def generate_content(self):
method delete_captured_packets_file (line 149) | def delete_captured_packets_file(self, file_name):
method download_file (line 157) | def download_file(self, file_name):
class ProtocolsPage (line 188) | class ProtocolsPage(Frame):
method __init__ (line 193) | def __init__(self, parent_window):
class ExtensionPage (line 226) | class ExtensionPage(Frame):
method __init__ (line 231) | def __init__(self, parent_window):
class ImportPage (line 259) | class ImportPage(Frame):
method __init__ (line 264) | def __init__(self, parent_window):
method import_button_click (line 336) | def import_button_click(self, file_path, option, selected_protocol):
method get_protocol_names (line 349) | def get_protocol_names(self):
class ExportPage (line 357) | class ExportPage(Frame):
method __init__ (line 358) | def __init__(self, parent_window):
class TabFrame (line 383) | class TabFrame(Frame):
method __init__ (line 384) | def __init__(self, parent_window, option):
class ExtensionHelp (line 465) | class ExtensionHelp(Frame):
method __init__ (line 470) | def __init__(self, parent_window):
class AttacksPage (line 486) | class AttacksPage(Frame):
method __init__ (line 491) | def __init__(self, parent_window, protocol):
method delete_protocol (line 535) | def delete_protocol(self):
class AttackSuiteDetailsPage (line 541) | class AttackSuiteDetailsPage(Frame):
method __init__ (line 546) | def __init__(self, parent_window, protocol, attack_suite):
class AttackDetailsPage (line 576) | class AttackDetailsPage(Frame):
method __init__ (line 581) | def __init__(self, parent_window, protocol, attack, attack_suite):
method delete_attack (line 620) | def delete_attack(self):
class InputsPage (line 632) | class InputsPage(Frame):
method __init__ (line 637) | def __init__(self, parent_window, protocol, attack, attack_suite):
method get_file_path (line 704) | def get_file_path(self, entry):
method set_input_values (line 711) | def set_input_values(self):
method navigate_to_attack_reporting_page (line 739) | def navigate_to_attack_reporting_page(self):
method load_default_parameters_to_variables (line 753) | def load_default_parameters_to_variables(self):
method _check_value_type (line 758) | def _check_value_type(_input, _value):
class AttackReportingPage (line 768) | class AttackReportingPage(Frame):
method __init__ (line 773) | def __init__(self, parent_window, protocol, attack, attack_suite):
method write (line 814) | def write(self, text):
method readline (line 821) | def readline(self):
method get_number (line 832) | def get_number(self):
method perform_attack (line 846) | def perform_attack(self):
method attack_stopper (line 855) | def attack_stopper(self):
method report_generator (line 865) | def report_generator(self):
function run (line 882) | def run():
FILE: src/GUI/utils.py
function is_default_protocol (line 16) | def is_default_protocol(protocol_name):
function delete_protocol (line 25) | def delete_protocol(protocol_name):
function delete_attack (line 34) | def delete_attack(attack_name):
function pop_up_window (line 53) | def pop_up_window(root, protocol_name, definition, justify=LEFT):
function get_protocols (line 73) | def get_protocols():
function get_attacks (line 106) | def get_attacks(package_name):
function get_captured_packet_files (line 165) | def get_captured_packet_files():
function change_frame (line 181) | def change_frame(old_frame, new_frame):
function create_root (line 193) | def create_root():
function center_widget (line 213) | def center_widget(window):
function startup_calls (line 236) | def startup_calls():
function shutdown_calls (line 243) | def shutdown_calls(root):
FILE: src/Utils/CommonUtil/__init__.py
function get_current_datetime_for_filename_format (line 9) | def get_current_datetime_for_filename_format():
function get_current_datetime_for_report_format (line 13) | def get_current_datetime_for_report_format():
function get_boolean_value (line 17) | def get_boolean_value(bool_str):
FILE: src/Utils/ExtendUtil/export_attack_suite_template.py
class _ATTACK_SUITE_COMBINED_NAME (line 16) | class _ATTACK_SUITE_COMBINED_NAME(AttackSuite):
method __init__ (line 18) | def __init__(self):
FILE: src/Utils/ExtendUtil/export_attack_template.py
class _ATTACK_COMBINED_NAME (line 18) | class _ATTACK_COMBINED_NAME(Attack):
method __init__ (line 48) | def __init__(self):
method pre_attack_init (line 65) | def pre_attack_init(self):
method run (line 69) | def run(self):
FILE: src/Utils/ExtendUtil/export_protocol_template.py
class _PROTOCOL_NAME (line 21) | class _PROTOCOL_NAME(Protocol):
method __init__ (line 23) | def __init__(self):
FILE: src/Utils/ExtendUtil/export_util.py
class ExportTypes (line 15) | class ExportTypes(Enum):
class ExportOptions (line 23) | class ExportOptions(Enum):
class ExportUtil (line 33) | class ExportUtil(object):
method get_export_texts_and_values (line 52) | def get_export_texts_and_values():
method export_function_factory (line 59) | def export_function_factory(export_type):
method export_files_with_zip (line 71) | def export_files_with_zip(output_name, list_of_files, output_path="./"):
method export_files_with_tar (line 89) | def export_files_with_tar(output_name, list_of_files, output_path="./"):
method export_protocol (line 109) | def export_protocol(protocol_name, export_path, export_type, output_na...
method export_attack (line 147) | def export_attack(protocol_name, attack_name, export_path, export_type...
method export_attack_suite (line 186) | def export_attack_suite(protocol_name, attack_suite_name, export_path,...
method _create_temporary_file_and_replace_regex (line 226) | def _create_temporary_file_and_replace_regex(template_name=None, regex...
method _replace_regex (line 245) | def _replace_regex(content, substitution_list_as_tuples):
method export_action (line 251) | def export_action(protocol_name, attack_name, attack_suite_name, file_...
FILE: src/Utils/ExtendUtil/import_util.py
class ImportOptions (line 15) | class ImportOptions(Enum):
class ImportUtil (line 25) | class ImportUtil(object):
method startup (line 38) | def startup():
method shutdown (line 57) | def shutdown():
method trigger_import (line 71) | def trigger_import(input_path, protocol_name=None):
method import_function_factory (line 97) | def import_function_factory(input_path):
method import_zip (line 113) | def import_zip(input_path, full_out_dir_path):
method import_tar (line 126) | def import_tar(input_path, full_out_dir_path):
method import_protocol (line 139) | def import_protocol(file_path):
method import_attack_or_attack_suite (line 144) | def import_attack_or_attack_suite(file_path, protocol_name):
method _is_file_name (line 149) | def _is_file_name(name):
method _do_not_import_names (line 157) | def _do_not_import_names(name):
method import_action (line 161) | def import_action(file_path, option, protocol_name=None):
FILE: src/Utils/FilterUtil/pyshark_filter_util.py
class PySharkFilter (line 7) | class PySharkFilter:
method __init__ (line 12) | def __init__(self, layer_name, field_name, value):
method set_layer_name (line 17) | def set_layer_name(self, layer_name):
method get_layer_name (line 21) | def get_layer_name(self):
method set_field_name (line 24) | def set_field_name(self, field_name):
method get_field_name (line 28) | def get_field_name(self):
method set_value (line 31) | def set_value(self, value):
method get_value (line 35) | def get_value(self):
method apply_filter_to_packet (line 38) | def apply_filter_to_packet(self, packet):
FILE: src/Utils/FuzzerUtil/radamsa_util.py
function radamsa_malformed_input_generator (line 10) | def radamsa_malformed_input_generator(input_string, output_count=1):
function get_ascii_decodable_radamsa_malformed_input (line 35) | def get_ascii_decodable_radamsa_malformed_input(input_string, output_cou...
FILE: src/Utils/RandomUtil/random_generated_names.py
function get_random_client_name (line 6) | def get_random_client_name():
function get_random_file_name (line 11) | def get_random_file_name():
FILE: src/Utils/ReportUtil/report_generator.py
class PeniotPDF (line 6) | class PeniotPDF(FPDF):
method header (line 11) | def header(self):
method footer (line 20) | def footer(self):
method add_title_and_date (line 27) | def add_title_and_date(self, attack_name):
method add_attack_logs (line 34) | def add_attack_logs(self, attack_logs):
class GenerateReport (line 39) | class GenerateReport(object):
method generate_pdf_from_text (line 42) | def generate_pdf_from_text(protocol_name, attack_name, attack_logs, di...
FILE: src/Utils/SnifferUtil/generic_sniffer.py
function filter_packets_by_filter_list (line 16) | def filter_packets_by_filter_list(packets, filter_list):
class GenericSniffer (line 29) | class GenericSniffer:
method __init__ (line 37) | def __init__(self, timeout=DEFAULT_SNIFF_TIMEOUT, interface=DEFAULT_IN...
method start_live_capture (line 54) | def start_live_capture(self):
method get_captured_packets (line 66) | def get_captured_packets(self):
method filter_packets_by_protocol (line 72) | def filter_packets_by_protocol(self, protocol=None):
FILE: src/protocols/AMQP/amqp_protocol.py
class AMQP (line 6) | class AMQP(Protocol):
method __init__ (line 8) | def __init__(self):
class TestAMQPProtocol (line 20) | class TestAMQPProtocol(unittest.TestCase):
method setUp (line 21) | def setUp(self):
method tearDown (line 24) | def tearDown(self):
method test_name (line 27) | def test_name(self):
method test_attacks (line 30) | def test_attacks(self):
FILE: src/protocols/AMQP/amqp_scanner.py
class AMQPScanner (line 7) | class AMQPScanner:
method __init__ (line 13) | def __init__(self):
method scan (line 17) | def scan(timeout=generic_sniffer.DEFAULT_SNIFF_TIMEOUT, interface=gene...
FILE: src/protocols/AMQP/attacks/amqp_dos_attack.py
class AMQPDoSAttack (line 13) | class AMQPDoSAttack(Attack):
method __init__ (line 33) | def __init__(self):
method signal_handler (line 55) | def signal_handler(self, sig, frame):
method stop_attack (line 58) | def stop_attack(self):
method pre_attack_init (line 65) | def pre_attack_init(self):
method run (line 76) | def run(self):
class TestMQTTDoSAttack (line 88) | class TestMQTTDoSAttack(unittest.TestCase):
method setUp (line 89) | def setUp(self):
method tearDown (line 92) | def tearDown(self):
method test_name (line 95) | def test_name(self):
method test_inputs (line 98) | def test_inputs(self):
method test_non_initialized_inputs (line 104) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 110) | def test_after_getting_inputs(self):
method test_dos_attack (line 126) | def test_dos_attack(self):
FILE: src/protocols/AMQP/attacks/amqp_fuzzing_attack_suite.py
class AMQPFuzzingAttackSuite (line 6) | class AMQPFuzzingAttackSuite(AttackSuite):
method __init__ (line 8) | def __init__(self):
class TestAMQPFuzzingAttackSuite (line 13) | class TestAMQPFuzzingAttackSuite(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method tearDown (line 17) | def tearDown(self):
method test_name (line 20) | def test_name(self):
method test_attack_list (line 23) | def test_attack_list(self):
method test_attacks (line 29) | def test_attacks(self):
FILE: src/protocols/AMQP/attacks/amqp_payload_size_fuzzer.py
class AMQPPayloadSizeFuzzerAttack (line 14) | class AMQPPayloadSizeFuzzerAttack(Attack):
method __init__ (line 36) | def __init__(self):
method signal_handler (line 55) | def signal_handler(self, sig, frame):
method stop_attack (line 58) | def stop_attack(self):
method pre_attack_init (line 65) | def pre_attack_init(self):
method run (line 80) | def run(self):
class TestCoAPPayloadSizeAttack (line 111) | class TestCoAPPayloadSizeAttack(unittest.TestCase):
method setUp (line 112) | def setUp(self):
method tearDown (line 115) | def tearDown(self):
method test_name (line 118) | def test_name(self):
method test_inputs (line 121) | def test_inputs(self):
method test_non_initialized_inputs (line 127) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 133) | def test_after_getting_inputs(self):
method test_invalid_fuzzing_turn (line 149) | def test_invalid_fuzzing_turn(self):
method test_payload_size_fuzzing_attack (line 161) | def test_payload_size_fuzzing_attack(self):
FILE: src/protocols/AMQP/attacks/amqp_random_payload_fuzzing.py
class AMQPRandomPayloadFuzzingAttack (line 15) | class AMQPRandomPayloadFuzzingAttack(Attack):
method __init__ (line 37) | def __init__(self):
method signal_handler (line 59) | def signal_handler(self, sig, frame):
method stop_attack (line 62) | def stop_attack(self):
method pre_attack_init (line 69) | def pre_attack_init(self):
method run (line 80) | def run(self):
class TestAMQPRandomPayloadAttack (line 125) | class TestAMQPRandomPayloadAttack(unittest.TestCase):
method setUp (line 126) | def setUp(self):
method tearDown (line 129) | def tearDown(self):
method test_name (line 132) | def test_name(self):
method test_inputs (line 135) | def test_inputs(self):
method test_non_initialized_inputs (line 141) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 147) | def test_after_getting_inputs(self):
method test_invalid_fuzzing_turn (line 163) | def test_invalid_fuzzing_turn(self):
method test_random_payload_fuzzing_attack (line 175) | def test_random_payload_fuzzing_attack(self):
FILE: src/protocols/AMQP/examples/receiver_example.py
function signal_handler (line 25) | def signal_handler(sig, frame):
function callback (line 33) | def callback(ch, method, properties, body):
function receive_procedure (line 37) | def receive_procedure(channel_to_receive, queue_name=DEFAULT_QUEUE_NAME):
FILE: src/protocols/AMQP/examples/sender_example.py
function signal_handler (line 26) | def signal_handler(sig, frame):
function send_procedure (line 34) | def send_procedure(channel_to_send, exchange=DEFAULT_EXCHANGE, routing_k...
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/CaptureFiles.py
class CaptureFileHandler (line 49) | class CaptureFileHandler:
method __init__ (line 50) | def __init__(self, clear=False):
method startNewFile (line 61) | def startNewFile(self):
method doRollover (line 65) | def doRollover(self):
method readLine (line 76) | def readLine(self, lineNum):
method readAll (line 83) | def readAll(self):
method writeString (line 89) | def writeString(self, msgString):
method writeList (line 93) | def writeList(self, msgList):
method writePacketList (line 96) | def writePacketList(self, packetList):
method writePacket (line 99) | def writePacket(self, packet):
method makePacketHeader (line 102) | def makePacketHeader(self, length):
function toList (line 132) | def toList(myString):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Devices.py
class DeviceList (line 6) | class DeviceList(Notifications.Notifier):
method __init__ (line 7) | def __init__(self, *args, **kwargs):
method __len__ (line 13) | def __len__(self):
method __repr__ (line 16) | def __repr__(self):
method clear (line 19) | def clear(self):
method appendOrUpdate (line 22) | def appendOrUpdate(self, newDevice):
method append (line 44) | def append(self, device):
method find (line 48) | def find(self, id):
method remove (line 65) | def remove(self, id):
method index (line 84) | def index(self, device):
method setFollowed (line 99) | def setFollowed(self, device):
method asList (line 110) | def asList(self):
class Device (line 114) | class Device:
method __init__ (line 115) | def __init__(self, address, name, RSSI, txAdd=1):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Exceptions.py
class SnifferTimeout (line 1) | class SnifferTimeout(Exception):
class UARTPacketError (line 5) | class UARTPacketError(Exception):
class InvalidPacketException (line 9) | class InvalidPacketException(Exception):
class SnifferWatchDogTimeout (line 15) | class SnifferWatchDogTimeout(SnifferTimeout):
class ExitCodeException (line 21) | class ExitCodeException(Exception):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Logger.py
function initLogger (line 38) | def initLogger():
function shutdownLogger (line 68) | def shutdownLogger():
function clearLog (line 74) | def clearLog():
function getTimestamp (line 84) | def getTimestamp():
function addTimestamp (line 93) | def addTimestamp():
function readAll (line 102) | def readAll():
class MyRotatingFileHandler (line 112) | class MyRotatingFileHandler(logHandlers.RotatingFileHandler):
method doRollover (line 113) | def doRollover(self):
class LogFlusher (line 124) | class LogFlusher(threading.Thread):
method __init__ (line 125) | def __init__(self, logHandler):
method run (line 134) | def run(self):
method doFlush (line 139) | def doFlush(self):
method stop (line 143) | def stop(self):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Notifications.py
class Notification (line 5) | class Notification():
method __init__ (line 6) | def __init__(self, key, msg=None):
method __repr__ (line 12) | def __repr__(self):
class Notifier (line 16) | class Notifier():
method __init__ (line 17) | def __init__(self, callbacks=[]):
method subscribe (line 26) | def subscribe(self, key, callback):
method getCallbacks (line 31) | def getCallbacks(self, key):
method notify (line 38) | def notify(self, key=None, msg=None, notification=None):
method passOnNotification (line 52) | def passOnNotification(self, notification):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Packet.py
class PacketReader (line 78) | class PacketReader(Notifications.Notifier):
method __init__ (line 79) | def __init__(self, portnum=None, callbacks=[]):
method setup (line 94) | def setup(self):
method doExit (line 99) | def doExit(self):
method encodeToSLIP (line 105) | def encodeToSLIP(self, byteList):
method decodeFromSLIP (line 126) | def decodeFromSLIP(self, timeout=None):
method getSerialByte (line 155) | def getSerialByte(self, timeout=None):
method handlePacketHistory (line 161) | def handlePacketHistory(self, packet):
method getPacket (line 175) | def getPacket(self, timeout=None):
method useByteQueue (line 188) | def useByteQueue(self, useByteQueue=True):
method getByteQueue (line 191) | def getByteQueue(self):
method sendPacket (line 194) | def sendPacket(self, id, payload, timeout=None):
method sendScan (line 201) | def sendScan(self, timeout=None):
method sendFollow (line 204) | def sendFollow(self, addr, txAdd=1, followOnlyAdvertisements=False, ti...
method sendPingReq (line 209) | def sendPingReq(self, timeout=1):
method sendTK (line 212) | def sendTK(self, TK, timeout=None):
method sendSwitchBaudRate (line 223) | def sendSwitchBaudRate(self, newBaudRate, timeout=None):
method switchBaudRate (line 226) | def switchBaudRate(self, newBaudRate):
method sendHopSequence (line 229) | def sendHopSequence(self, hopSequence):
method sendGoIdle (line 237) | def sendGoIdle(self, timeout=None):
method findSerialPort (line 240) | def findSerialPort(self):
class Packet (line 325) | class Packet:
method __init__ (line 327) | def __init__(self, packetList):
method __repr__ (line 347) | def __repr__(self):
method readStaticHeader (line 350) | def readStaticHeader(self, packetList):
method readDynamicHeader (line 355) | def readDynamicHeader(self, packetList):
method readPayload (line 364) | def readPayload(self, packetList):
method readFlags (line 414) | def readFlags(self):
method getList (line 421) | def getList(self):
method validatePacketList (line 424) | def validatePacketList(self, packetList):
class BlePacket (line 435) | class BlePacket():
method __init__ (line 436) | def __init__(self, packetList):
method __repr__ (line 445) | def __repr__(self):
method extractAccessAddress (line 448) | def extractAccessAddress(self, packetList):
method extractAdvType (line 451) | def extractAdvType(self, packetList):
method extractAdvAddress (line 454) | def extractAdvAddress(self, packetList):
method extractName (line 470) | def extractName(self, packetList):
method extractLength (line 491) | def extractLength(self, packetList):
function parseLittleEndian (line 496) | def parseLittleEndian(list):
function toLittleEndian (line 503) | def toLittleEndian(value, size):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Sniffer.py
function initLog (line 10) | def initLog():
class Sniffer (line 20) | class Sniffer(threading.Thread, SnifferCollector.SnifferCollector):
method __init__ (line 25) | def __init__(self, portnum=None):
method getPackets (line 37) | def getPackets(self, number=-1):
method getDevices (line 42) | def getDevices(self):
method follow (line 49) | def follow(self, device=None, followOnlyAdvertisements=False):
method scan (line 55) | def scan(self):
method sendTK (line 60) | def sendTK(self, TK):
method setPortnum (line 65) | def setPortnum(self, portnum):
method setAdvHopSequence (line 73) | def setAdvHopSequence(self, hopSequence):
method doExit (line 78) | def doExit(self):
method missedPackets (line 86) | def missedPackets(self):
method packetsInLastConnection (line 92) | def packetsInLastConnection(self):
method connectEventPacketCounterValue (line 97) | def connectEventPacketCounterValue(self):
method currentConnectRequest (line 102) | def currentConnectRequest(self):
method inConnection (line 107) | def inConnection(self):
method state (line 113) | def state(self):
method portnum (line 118) | def portnum(self):
method swversion (line 123) | def swversion(self):
method fwversion (line 128) | def fwversion(self):
method run (line 134) | def run(self):
method comPortFound (line 151) | def comPortFound(self, notification):
method runSniffer (line 158) | def runSniffer(self):
method sendTestPacketToSniffer (line 165) | def sendTestPacketToSniffer(self, payload):
method getTestPacketFromSniffer (line 169) | def getTestPacketFromSniffer(self):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/SnifferCollector.py
class SnifferCollector (line 39) | class SnifferCollector(Notifications.Notifier):
method __init__ (line 40) | def __init__(self, portnum=None, *args, **kwargs):
method __del__ (line 72) | def __del__(self):
method _setup (line 75) | def _setup(self):
method _makeBoardId (line 90) | def _makeBoardId(self):
method state (line 103) | def state(self):
method _setState (line 106) | def _setState(self, newState):
method _switchBaudRate (line 110) | def _switchBaudRate(self, newBaudRate):
method _processBLEPacket (line 117) | def _processBLEPacket(self, packet):
method _continuouslyPipe (line 150) | def _continuouslyPipe(self):
method _findPacketByPacketCounter (line 193) | def _findPacketByPacketCounter(self, packetCounterValue):
method _startScanning (line 201) | def _startScanning(self):
method _doExit (line 212) | def _doExit(self):
method _startFollowing (line 217) | def _startFollowing(self, device, followOnlyAdvertisements=False):
method _appendPacket (line 226) | def _appendPacket(self, packet):
method _getPackets (line 232) | def _getPackets(self, number=-1):
method _sendTestPacket (line 238) | def _sendTestPacket(self, payload):
method _getTestPacket (line 241) | def _getTestPacket(self):
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/UART.py
class Uart (line 9) | class Uart:
method __init__ (line 10) | def __init__(self, portnum=None, useByteQueue=False):
method __del__ (line 35) | def __del__(self):
method switchBaudRate (line 40) | def switchBaudRate(self, newBaudRate):
method read (line 43) | def read(self, length, timeout=None):
method readByte (line 59) | def readByte(self, timeout=None):
method readList (line 66) | def readList(self, size, timeout=None):
method writeList (line 69) | def writeList(self, array, timeout=None):
function list_serial_ports (line 85) | def list_serial_ports():
FILE: src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Version.py
function getRevision (line 7) | def getRevision():
function getVersionString (line 11) | def getVersionString(mRevision=getRevision()):
function getPureVersionString (line 25) | def getPureVersionString(mRevision=getRevision()):
function getUserGuideFileName (line 29) | def getUserGuideFileName(version=pdfVersion, platformName="win", deliver...
function getReadableVersionString (line 34) | def getReadableVersionString(mRevision=getRevision()):
function getFileNameVersionString (line 38) | def getFileNameVersionString(mRevision=getRevision(), itemName="", platf...
FILE: src/protocols/BLE/Adafruit_BLESniffer/sniffer.py
function setup (line 24) | def setup(serport, delay=6):
function scanForDevices (line 43) | def scanForDevices(scantime=5):
function selectDevice (line 59) | def selectDevice(devlist):
function dumpPackets (line 100) | def dumpPackets():
FILE: src/protocols/BLE/Adafruit_BLESniffer/wireshark_dissector_source/packet-btle.c
function reverse_byte_order (line 457) | void
function reverse_byte_order_inplace (line 467) | void
function dissect_feature_set (line 480) | void
function dissect_channel_map (line 506) | void
function proto_tree (line 537) | proto_tree* add_adv_data_attr(proto_tree* tree, tvbuff_t* tvb, const int...
function dissect_adv_data_attr (line 566) | void
function dissect_adv_data (line 751) | void
function dissect_adv_ind_or_nonconn_or_scan (line 774) | void
function dissect_adv_direct_ind (line 807) | void
function dissect_scan_req (line 833) | void
function dissect_scan_rsp (line 861) | void
function dissect_connect_req (line 892) | void
function dissect_ll_enc_req (line 943) | void
function dissect_ll_enc_rsp (line 962) | void
function dissect_ll_control (line 1058) | void
function dissect_btle (line 1137) | static void
function proto_register_btle (line 1344) | void
function proto_reg_handoff_btle (line 1883) | void
FILE: src/protocols/BLE/Adafruit_BLESniffer/wireshark_dissector_source/packet-nordic_ble.c
function guint8 (line 220) | static guint8
function guint8 (line 226) | static guint8
function guint8 (line 232) | static guint8
function guint8 (line 238) | static guint8
function guint8 (line 244) | static guint8
function guint8 (line 250) | static guint8
function guint8 (line 256) | static guint8
function guint8 (line 262) | static guint8
function guint8 (line 268) | static guint8
function guint8 (line 274) | static guint8
function guint8 (line 280) | static guint8
function guint8 (line 286) | static guint8
function guint8 (line 292) | static guint8
function gboolean (line 307) | static gboolean
function array_copy (line 322) | static void array_copy(void* dst, const void* src, int len)
function tvbuff_t (line 332) | static tvbuff_t *
function gboolean (line 339) | static gboolean
function dissect_packet_counter (line 409) | static void
function dissect_id (line 415) | static void
function gboolean (line 423) | static gboolean
function dissect_channel (line 484) | static void
function dissect_rssi (line 492) | static void
function dissect_event_counter (line 500) | static void
function dissect_ble_delta_time (line 511) | static void
function dissect_ble_hlen (line 532) | static void
function dissect_protover (line 540) | static void
function guint32 (line 550) | static guint32
function dissect_header_0_9_7 (line 566) | static void
function dissect_header_1_0_0 (line 592) | static void
function dissect_nordic_ble (line 632) | static int
function proto_register_nordic_ble (line 688) | void
function proto_reg_handoff_nordic_ble (line 829) | void
FILE: src/protocols/BLE/BLETest.py
class BLETest (line 7) | class BLETest:
method run_test (line 10) | def run_test(attack_name):
FILE: src/protocols/BLE/attacks/ble_replay_attack.py
class BLEReplayAttack (line 8) | class BLEReplayAttack(Attack):
method __init__ (line 15) | def __init__(self):
method run (line 25) | def run(self):
method stop_attack (line 29) | def stop_attack(self):
FILE: src/protocols/BLE/attacks/ble_sniff_attack.py
class BLESniffAttack (line 8) | class BLESniffAttack(Attack):
method __init__ (line 16) | def __init__(self):
method run (line 26) | def run(self):
method signal_handler (line 32) | def signal_handler(self, sig, frame):
method stop_attack (line 35) | def stop_attack(self):
FILE: src/protocols/BLE/ble_device.py
class BLEDevice (line 4) | class BLEDevice:
method __init__ (line 10) | def __init__(self, address):
method connect (line 16) | def connect(self):
method writecmd (line 32) | def writecmd(self, handle, value):
FILE: src/protocols/BLE/ble_protocol.py
class BLE (line 4) | class BLE(Protocol):
method __init__ (line 6) | def __init__(self):
FILE: src/protocols/BLE/ble_replay_attack.py
class BLEReplayAttackHelper (line 5) | class BLEReplayAttackHelper:
method __init__ (line 10) | def __init__(self, file_path):
method run (line 15) | def run(self):
method create_tmp_file (line 21) | def create_tmp_file(self):
method get_write_requests (line 29) | def get_write_requests(self):
method replay_write_requests (line 75) | def replay_write_requests(self):
method delete_tmp_file (line 90) | def delete_tmp_file(self):
FILE: src/protocols/BLE/ble_sniff.py
class BLESniffer (line 10) | class BLESniffer:
method __init__ (line 14) | def __init__(self, serial_portt):
method run (line 33) | def run(self):
method stop_attack (line 93) | def stop_attack(self):
method create_file_name (line 99) | def create_file_name():
FILE: src/protocols/BLE/ble_tools.py
class BLEScanner (line 8) | class BLEScanner:
method scan (line 17) | def scan(interface, timeout):
class BLEPeripheral (line 30) | class BLEPeripheral:
method __init__ (line 37) | def __init__(self, address, address_type, interface):
method getServices (line 40) | def getServices(self):
method getCharacteristics (line 46) | def getCharacteristics(self):
method getAddress (line 52) | def getAddress(self):
method getAddressType (line 58) | def getAddressType(self):
method getInterface (line 61) | def getInterface(self):
FILE: src/protocols/CoAP/__init__.py
class CoAPMethods (line 24) | class CoAPMethods(enum.Enum):
function does_method_have_payload (line 32) | def does_method_have_payload(method):
function make_request (line 41) | def make_request(client, _path, _method_type, _payload=None):
function get_coap_methods_by_name (line 64) | def get_coap_methods_by_name(method_string):
function get_coap_methods_as_string (line 81) | def get_coap_methods_as_string(method):
FILE: src/protocols/CoAP/attacks/coap_dos_attack.py
class CoAPDoSAttack (line 14) | class CoAPDoSAttack(Attack):
method __init__ (line 35) | def __init__(self):
method signal_handler (line 56) | def signal_handler(self, sig, frame):
method stop_attack (line 59) | def stop_attack(self):
method pre_attack_init (line 66) | def pre_attack_init(self):
method run (line 70) | def run(self):
class TestCoAPDoSAttack (line 82) | class TestCoAPDoSAttack(unittest.TestCase):
method setUp (line 83) | def setUp(self):
method tearDown (line 86) | def tearDown(self):
method test_name (line 89) | def test_name(self):
method test_inputs (line 92) | def test_inputs(self):
method test_non_initialized_inputs (line 98) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 104) | def test_after_getting_inputs(self):
method test_dos_attack (line 119) | def test_dos_attack(self):
FILE: src/protocols/CoAP/attacks/coap_fuzzing_attack_suite.py
class CoAPFuzzingAttackSuite (line 9) | class CoAPFuzzingAttackSuite(AttackSuite):
method __init__ (line 11) | def __init__(self):
class TestCoAPFuzzingAttackSuite (line 16) | class TestCoAPFuzzingAttackSuite(unittest.TestCase):
method setUp (line 17) | def setUp(self):
method tearDown (line 20) | def tearDown(self):
method test_name (line 23) | def test_name(self):
method test_attack_list (line 26) | def test_attack_list(self):
method test_attacks (line 32) | def test_attacks(self):
FILE: src/protocols/CoAP/attacks/coap_payload_size_fuzzer.py
class CoAPPayloadSizeFuzzerAttack (line 15) | class CoAPPayloadSizeFuzzerAttack(Attack):
method __init__ (line 36) | def __init__(self):
method signal_handler (line 55) | def signal_handler(self, sig, frame):
method stop_attack (line 58) | def stop_attack(self):
method pre_attack_init (line 66) | def pre_attack_init(self):
method run (line 74) | def run(self):
class TestCoAPPayloadSizeAttack (line 111) | class TestCoAPPayloadSizeAttack(unittest.TestCase):
method setUp (line 112) | def setUp(self):
method tearDown (line 115) | def tearDown(self):
method test_name (line 118) | def test_name(self):
method test_inputs (line 121) | def test_inputs(self):
method test_non_initialized_inputs (line 127) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 133) | def test_after_getting_inputs(self):
method test_invalid_method (line 148) | def test_invalid_method(self):
method test_invalid_fuzzing_turn (line 159) | def test_invalid_fuzzing_turn(self):
method test_payload_size_fuzzing_attack (line 170) | def test_payload_size_fuzzing_attack(self):
FILE: src/protocols/CoAP/attacks/coap_random_payload_fuzzing.py
class CoAPRandomPayloadFuzzingAttack (line 16) | class CoAPRandomPayloadFuzzingAttack(Attack):
method __init__ (line 39) | def __init__(self):
method signal_handler (line 61) | def signal_handler(self, sig, frame):
method stop_attack (line 64) | def stop_attack(self):
method pre_attack_init (line 72) | def pre_attack_init(self):
method run (line 80) | def run(self):
class TestCoAPRandomPayloadAttack (line 126) | class TestCoAPRandomPayloadAttack(unittest.TestCase):
method setUp (line 127) | def setUp(self):
method tearDown (line 130) | def tearDown(self):
method test_name (line 133) | def test_name(self):
method test_inputs (line 136) | def test_inputs(self):
method test_non_initialized_inputs (line 142) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 148) | def test_after_getting_inputs(self):
method test_invalid_method (line 163) | def test_invalid_method(self):
method test_invalid_fuzzing_turn (line 174) | def test_invalid_fuzzing_turn(self):
method test_random_payload_fuzzing_attack (line 185) | def test_random_payload_fuzzing_attack(self):
FILE: src/protocols/CoAP/attacks/coap_replay_attack.py
class CoAPReplayAttack (line 13) | class CoAPReplayAttack(Attack):
method __init__ (line 28) | def __init__(self):
method signal_handler (line 45) | def signal_handler(self, sig, frame):
method stop_attack (line 48) | def stop_attack(self):
method pre_attack_init (line 52) | def pre_attack_init(self):
method run (line 59) | def run(self):
method pre_attack_process (line 72) | def pre_attack_process(self):
class TestCoAPReplayAttack (line 85) | class TestCoAPReplayAttack(unittest.TestCase):
method setUp (line 86) | def setUp(self):
method tearDown (line 89) | def tearDown(self):
method test_name (line 92) | def test_name(self):
method test_non_initialized_inputs (line 95) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 101) | def test_after_getting_inputs(self):
method test_replay_attack (line 113) | def test_replay_attack(self):
FILE: src/protocols/CoAP/attacks/coap_sniff_attack.py
class CoAPSniffAttack (line 13) | class CoAPSniffAttack(Attack):
method __init__ (line 26) | def __init__(self):
method signal_handler (line 43) | def signal_handler(self, sig, frame):
method stop_attack (line 46) | def stop_attack(self):
method run (line 50) | def run(self):
class TestCoAPSniffAttack (line 61) | class TestCoAPSniffAttack(unittest.TestCase):
method setUp (line 62) | def setUp(self):
method tearDown (line 65) | def tearDown(self):
method test_name (line 68) | def test_name(self):
method test_non_initialized_inputs (line 71) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 77) | def test_after_getting_inputs(self):
method test_sniff_attack (line 89) | def test_sniff_attack(self):
FILE: src/protocols/CoAP/coap_protocol.py
class CoAP (line 6) | class CoAP(Protocol):
method __init__ (line 8) | def __init__(self):
class TestCoAPProtocol (line 31) | class TestCoAPProtocol(unittest.TestCase):
method setUp (line 32) | def setUp(self):
method tearDown (line 35) | def tearDown(self):
method test_name (line 38) | def test_name(self):
method test_attacks (line 41) | def test_attacks(self):
FILE: src/protocols/CoAP/coap_scanner.py
class CoAPScanner (line 9) | class CoAPScanner:
method __init__ (line 15) | def __init__(self):
method scan (line 19) | def scan(timeout=generic_sniffer.DEFAULT_SNIFF_TIMEOUT, interface=gene...
method get_raw_udp_payload_as_bytes (line 30) | def get_raw_udp_payload_as_bytes(packet):
method get_raw_frame_as_bytes (line 34) | def get_raw_frame_as_bytes(packet):
FILE: src/protocols/CoAP/examples/client_example.py
function signal_handler (line 23) | def signal_handler(sig, frame):
function client_procedure (line 31) | def client_procedure(host, port, path):
FILE: src/protocols/CoAP/examples/resource_example.py
class BasicResource (line 4) | class BasicResource(Resource):
method __init__ (line 6) | def __init__(self, name="BasicResource", coap_server=None):
method render_GET (line 11) | def render_GET(self, request):
method render_PUT (line 14) | def render_PUT(self, request):
method render_POST (line 18) | def render_POST(self, request):
method render_DELETE (line 24) | def render_DELETE(self, request):
method render_GET_advanced (line 27) | def render_GET_advanced(self, request, response):
method render_PUT_advanced (line 30) | def render_PUT_advanced(self, request, response):
method render_POST_advanced (line 33) | def render_POST_advanced(self, request, response):
method render_DELETE_advanced (line 36) | def render_DELETE_advanced(self, request, response):
FILE: src/protocols/CoAP/examples/server_example.py
class CoAPServer (line 20) | class CoAPServer(CoAP):
method __init__ (line 21) | def __init__(self, host, port, path):
function server_procedure (line 26) | def server_procedure(host, port, path):
FILE: src/protocols/MQTT/attacks/mqtt_dos_attack.py
class MQTTDoSAttack (line 17) | class MQTTDoSAttack(Attack):
method __init__ (line 37) | def __init__(self):
method signal_handler (line 58) | def signal_handler(self, sig, frame):
method stop_attack (line 61) | def stop_attack(self):
method pre_attack_init (line 71) | def pre_attack_init(self):
method run (line 75) | def run(self):
class TestMQTTDoSAttack (line 107) | class TestMQTTDoSAttack(unittest.TestCase):
method setUp (line 108) | def setUp(self):
method tearDown (line 111) | def tearDown(self):
method test_name (line 114) | def test_name(self):
method test_inputs (line 117) | def test_inputs(self):
method test_non_initialized_inputs (line 123) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 129) | def test_after_getting_inputs(self):
method test_dos_attack (line 144) | def test_dos_attack(self):
FILE: src/protocols/MQTT/attacks/mqtt_fuzzing_attack_suite.py
class MQTTFuzzingAttackSuite (line 8) | class MQTTFuzzingAttackSuite(AttackSuite):
method __init__ (line 10) | def __init__(self):
class TestMQTTFuzzingAttackSuite (line 15) | class TestMQTTFuzzingAttackSuite(unittest.TestCase):
method setUp (line 16) | def setUp(self):
method tearDown (line 19) | def tearDown(self):
method test_name (line 22) | def test_name(self):
method test_attack_list (line 25) | def test_attack_list(self):
method test_attacks (line 31) | def test_attacks(self):
FILE: src/protocols/MQTT/attacks/mqtt_generation_based_fuzzing.py
class MQTTGenerationBasedFuzzingAttack (line 17) | class MQTTGenerationBasedFuzzingAttack(Attack):
method __init__ (line 35) | def __init__(self):
method signal_handler (line 50) | def signal_handler(self, sig, frame):
method stop_attack (line 53) | def stop_attack(self):
method pre_attack_init (line 61) | def pre_attack_init(self):
method send_subscribe_or_unsubscribe (line 68) | def send_subscribe_or_unsubscribe(self, fuzz_client, message_type, top...
method random_topic_generator (line 107) | def random_topic_generator(self, message_type, possible_characters, po...
method run (line 124) | def run(self):
class TestMQTTGenerationBasedFuzzingAttack (line 183) | class TestMQTTGenerationBasedFuzzingAttack(unittest.TestCase):
method setUp (line 184) | def setUp(self):
method tearDown (line 187) | def tearDown(self):
method test_name (line 190) | def test_name(self):
method test_inputs (line 193) | def test_inputs(self):
method test_non_initialized_inputs (line 199) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 205) | def test_after_getting_inputs(self):
method testGenerationBasedFuzzingAttack (line 220) | def testGenerationBasedFuzzingAttack(self):
FILE: src/protocols/MQTT/attacks/mqtt_payload_size_fuzzer.py
class MQTTPayloadSizeFuzzerAttack (line 15) | class MQTTPayloadSizeFuzzerAttack(Attack):
method __init__ (line 33) | def __init__(self):
method signal_handler (line 49) | def signal_handler(self, sig, frame):
method stop_attack (line 52) | def stop_attack(self):
method pre_attack_init (line 60) | def pre_attack_init(self):
method run (line 71) | def run(self):
class TestMQTTPayloadSizeAttack (line 101) | class TestMQTTPayloadSizeAttack(unittest.TestCase):
method setUp (line 102) | def setUp(self):
method tearDown (line 105) | def tearDown(self):
method test_name (line 108) | def test_name(self):
method test_inputs (line 111) | def test_inputs(self):
method test_non_initialized_inputs (line 117) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 123) | def test_after_getting_inputs(self):
method test_invalid_fuzzing_turn (line 138) | def test_invalid_fuzzing_turn(self):
method test_payload_size_fuzzing_attack (line 149) | def test_payload_size_fuzzing_attack(self):
FILE: src/protocols/MQTT/attacks/mqtt_random_payload_fuzzing.py
class MQTTRandomPayloadFuzzingAttack (line 17) | class MQTTRandomPayloadFuzzingAttack(Attack):
method __init__ (line 37) | def __init__(self):
method signal_handler (line 56) | def signal_handler(self, sig, frame):
method stop_attack (line 59) | def stop_attack(self):
method pre_attack_init (line 67) | def pre_attack_init(self):
method run (line 74) | def run(self):
class TestMQTTRandomPayloadAttack (line 118) | class TestMQTTRandomPayloadAttack(unittest.TestCase):
method setUp (line 119) | def setUp(self):
method tearDown (line 122) | def tearDown(self):
method test_name (line 125) | def test_name(self):
method test_inputs (line 128) | def test_inputs(self):
method test_non_initialized_inputs (line 134) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 140) | def test_after_getting_inputs(self):
method test_invalid_fuzzing_turn (line 155) | def test_invalid_fuzzing_turn(self):
method test_random_payload_fuzzing_attack (line 166) | def test_random_payload_fuzzing_attack(self):
FILE: src/protocols/MQTT/attacks/mqtt_replay_attack.py
class MQTTReplayAttack (line 15) | class MQTTReplayAttack(Attack):
method __init__ (line 31) | def __init__(self):
method signal_handler (line 47) | def signal_handler(self, sig, frame):
method stop_attack (line 50) | def stop_attack(self):
method pre_attack_init (line 57) | def pre_attack_init(self):
method run (line 70) | def run(self):
method pre_attack_process (line 86) | def pre_attack_process(self):
class TestMQTTReplayAttack (line 100) | class TestMQTTReplayAttack(unittest.TestCase):
method setUp (line 101) | def setUp(self):
method tearDown (line 104) | def tearDown(self):
method test_name (line 107) | def test_name(self):
method test_non_initialized_inputs (line 110) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 116) | def test_after_getting_inputs(self):
method test_replay_attack (line 128) | def test_replay_attack(self):
FILE: src/protocols/MQTT/attacks/mqtt_sniff_attack.py
class MQTTSniffAttack (line 13) | class MQTTSniffAttack(Attack):
method __init__ (line 26) | def __init__(self):
method signal_handler (line 45) | def signal_handler(self, sig, frame):
method stop_attack (line 48) | def stop_attack(self):
method input_check (line 53) | def input_check(self):
method run (line 59) | def run(self):
class TestMQTTSniffAttack (line 71) | class TestMQTTSniffAttack(unittest.TestCase):
method setUp (line 72) | def setUp(self):
method tearDown (line 75) | def tearDown(self):
method test_name (line 78) | def test_name(self):
method test_non_initialized_inputs (line 81) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 87) | def test_after_getting_inputs(self):
method test_sniff_attack (line 99) | def test_sniff_attack(self):
FILE: src/protocols/MQTT/attacks/mqtt_topic_name_fuzzing.py
class MQTTTopicNameFuzzingAttack (line 14) | class MQTTTopicNameFuzzingAttack(Attack):
method __init__ (line 28) | def __init__(self):
method signal_handler (line 43) | def signal_handler(self, sig, frame):
method stop_attack (line 46) | def stop_attack(self):
method pre_attack_init (line 53) | def pre_attack_init(self):
method run (line 60) | def run(self):
class TestMQTTTopicNameFuzzingAttack (line 83) | class TestMQTTTopicNameFuzzingAttack(unittest.TestCase):
method setUp (line 84) | def setUp(self):
method tearDown (line 87) | def tearDown(self):
method test_name (line 90) | def test_name(self):
method test_inputs (line 93) | def test_inputs(self):
method test_non_initialized_inputs (line 99) | def test_non_initialized_inputs(self):
method test_after_getting_inputs (line 105) | def test_after_getting_inputs(self):
method test_payload_size_fuzzing_attack (line 120) | def test_payload_size_fuzzing_attack(self):
FILE: src/protocols/MQTT/examples/Demo/demo_publisher.py
function signal_handler (line 21) | def signal_handler(sig, frame):
function publish_procedure (line 30) | def publish_procedure(publisher_client, broker_host_name=DEFAULT_BROKER_...
function data_generator (line 56) | def data_generator():
FILE: src/protocols/MQTT/examples/Demo/demo_subscriber.py
class DemoSubscriber (line 21) | class DemoSubscriber(object):
method __init__ (line 25) | def __init__(self):
method on_message (line 29) | def on_message(self, client, userdata, message):
method on_message_append (line 36) | def on_message_append(self, message):
method start_processing_of_temperatures (line 45) | def start_processing_of_temperatures(self):
class TemperatureData (line 52) | class TemperatureData(object):
method __init__ (line 56) | def __init__(self, temperature_string):
method get_date (line 64) | def get_date(self):
method set_date (line 67) | def set_date(self, date):
method get_temperature (line 70) | def get_temperature(self):
method set_temperature (line 73) | def set_temperature(self, temperature):
method __repr__ (line 76) | def __repr__(self):
function signal_handler (line 80) | def signal_handler(sig, frame):
function subscribe_procedure (line 89) | def subscribe_procedure(subscriber_client, broker_host_name=DEFAULT_BROK...
FILE: src/protocols/MQTT/examples/publisher_example.py
function signal_handler (line 23) | def signal_handler(sig, frame):
function on_message (line 32) | def on_message(client, userdata, message):
function on_connect (line 36) | def on_connect(client, userdata, flags, rc):
function publish_procedure (line 40) | def publish_procedure(publisher_client, broker_host_name=DEFAULT_BROKER_...
FILE: src/protocols/MQTT/examples/subscriber_example.py
function signal_handler (line 23) | def signal_handler(sig, frame):
function on_message (line 32) | def on_message(client, userdata, message):
function on_connect (line 36) | def on_connect(client, userdata, flags, rc):
function subscribe_procedure (line 40) | def subscribe_procedure(subscriber_client, broker_host_name=DEFAULT_BROK...
FILE: src/protocols/MQTT/mqtt_protocol.py
class MQTT (line 6) | class MQTT(Protocol):
method __init__ (line 8) | def __init__(self):
class TestMQTTProtocol (line 31) | class TestMQTTProtocol(unittest.TestCase):
method setUp (line 32) | def setUp(self):
method tearDown (line 35) | def tearDown(self):
method test_name (line 38) | def test_name(self):
method test_attacks (line 41) | def test_attacks(self):
FILE: src/protocols/MQTT/mqtt_scanner.py
class MQTTScanner (line 15) | class MQTTScanner:
method __init__ (line 21) | def __init__(self):
method scan (line 25) | def scan(timeout=generic_sniffer.DEFAULT_SNIFF_TIMEOUT, interface=gene...
method get_raw_tcp_payload_as_bytes (line 36) | def get_raw_tcp_payload_as_bytes(packet):
method get_raw_frame_as_bytes (line 40) | def get_raw_frame_as_bytes(packet):
Condensed preview — 116 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (458K chars).
[
{
"path": ".gitignore",
"chars": 1275,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE",
"chars": 1118,
"preview": "MIT License\n\nCopyright (c) 2018 Berat Cankar, Bigehan Bingöl, Doğukan Çavdaroğlu, Ebru Çelebi\n\nPermission is hereby gran"
},
{
"path": "README.md",
"chars": 7835,
"preview": "# PENIOT: Penetration Testing Tool for IoT\n\n#### Table of Contents\n* [Project Description](#Project-Description)\n * ["
},
{
"path": "setup.py",
"chars": 824,
"preview": "from os import path\nfrom setuptools import setup, find_packages\nimport sys\n\nsys.path.insert(0, \"src\")\n\nwith open(path.jo"
},
{
"path": "src/Entity/__init__.py",
"chars": 475,
"preview": "\"\"\"\n This package contains the following entities:\n\n 1) Protocol\n 2) Attack Suite\n 3) Attack\n 4) Input Fo"
},
{
"path": "src/Entity/attack.py",
"chars": 2216,
"preview": "import logging\n\nfrom GUI import hard_coded_texts as hct\n\n\nclass Attack(object):\n name = None\n inputs = []\n defa"
},
{
"path": "src/Entity/attack_suite.py",
"chars": 649,
"preview": "class AttackSuite(object):\n\n name = None\n attacks = []\n\n def __init__(self, name, attacks):\n self.name ="
},
{
"path": "src/Entity/input_format.py",
"chars": 1709,
"preview": "class InputFormat(object):\n\n def __init__(self, label_name, name, value, _type, default_value=None, mandatory=False, "
},
{
"path": "src/Entity/protocol.py",
"chars": 852,
"preview": "class Protocol(object):\n\n name = None\n attack_suites = []\n\n def __init__(self, name, attack_suites, definition)"
},
{
"path": "src/GUI/__init__.py",
"chars": 68,
"preview": "\"\"\"\n This package includes graphical user interface of PENIOT\n\"\"\""
},
{
"path": "src/GUI/custom_widgets.py",
"chars": 1855,
"preview": "from Tkinter import *\nfrom hard_coded_texts import get_project_name\n\n\nclass Header(Frame):\n \"\"\"\n Generic header te"
},
{
"path": "src/GUI/hard_coded_texts.py",
"chars": 2621,
"preview": "\"\"\"\n This file contains some methods which return hard-coded texts and constant texts\n\"\"\"\n\n\n# Window title, size a"
},
{
"path": "src/GUI/tkinter.py",
"chars": 37326,
"preview": "import logging\nimport tkFileDialog\nimport ttk\nfrom threading import Timer\n\nfrom custom_widgets import *\nfrom hard_coded_"
},
{
"path": "src/GUI/utils.py",
"chars": 8741,
"preview": "# This file contains methods which are used in the GUI.\nimport importlib\nimport inspect\nimport os\nimport pkgutil\nimport "
},
{
"path": "src/Utils/CommonUtil/__init__.py",
"chars": 672,
"preview": "\"\"\"\n Common Utilities\n It contains necessary functionalities used commonly in project.\n\"\"\"\n\nimport datetime\n\n\ndef "
},
{
"path": "src/Utils/ExtendUtil/__init__.py",
"chars": 117,
"preview": "\"\"\"\n Extendability Utilities\n It contains necessary functionality used for importing and exporting scripts.\n\"\"\""
},
{
"path": "src/Utils/ExtendUtil/export_attack_suite_template.py",
"chars": 1354,
"preview": "#################################################################################\n# IMPORT"
},
{
"path": "src/Utils/ExtendUtil/export_attack_template.py",
"chars": 3569,
"preview": "#################################################################################\n# IMPORT"
},
{
"path": "src/Utils/ExtendUtil/export_protocol_template.py",
"chars": 2184,
"preview": "#################################################################################\n# IMPORT"
},
{
"path": "src/Utils/ExtendUtil/export_util.py",
"chars": 10663,
"preview": "from enum import Enum\nfrom Utils.RandomUtil import random_generated_names as random_util\n\nimport logging\nimport os\nimpor"
},
{
"path": "src/Utils/ExtendUtil/import_util.py",
"chars": 6462,
"preview": "from enum import Enum\nfrom os import listdir\nfrom os.path import isfile, join\n\nimport logging\nimport os\nimport shutil\nim"
},
{
"path": "src/Utils/FilterUtil/__init__.py",
"chars": 172,
"preview": "\"\"\"\n Filtering Utilities\n It contains necessary functionalities used for filtering packets in several attacks\n\n "
},
{
"path": "src/Utils/FilterUtil/pyshark_filter_util.py",
"chars": 1501,
"preview": "import logging\n\nlogging.basicConfig(level=logging.DEBUG, format=\"%(asctime)s:%(levelname)s:%(name)s : %(message)s\")\nlogg"
},
{
"path": "src/Utils/FuzzerUtil/__init__.py",
"chars": 144,
"preview": "\"\"\"\n Fuzzer Utilities\n It contains necessary functionalities used for fuzzing attacks\n\n 1) Radamsa Random Fuzzi"
},
{
"path": "src/Utils/FuzzerUtil/radamsa_util.py",
"chars": 1785,
"preview": "import logging\nimport subprocess\n\nlogging.basicConfig(level=logging.DEBUG, format=\"%(asctime)s:%(levelname)s:%(name)s:%("
},
{
"path": "src/Utils/RandomUtil/__init__.py",
"chars": 112,
"preview": "\"\"\"\n Random Utilities\n It contains necessary functionalities that is related to randomized operations.\n\"\"\""
},
{
"path": "src/Utils/RandomUtil/random_generated_names.py",
"chars": 502,
"preview": "import random\nimport string\nimport time\n\n\ndef get_random_client_name():\n return 'peniot-cli-' + ''.join(random.choice"
},
{
"path": "src/Utils/ReportUtil/__init__.py",
"chars": 125,
"preview": "\"\"\"\n Report Generation Utilities\n It contains necessary functionalities used for reporting\n\n 1) Report Generato"
},
{
"path": "src/Utils/ReportUtil/report_generator.py",
"chars": 8573,
"preview": "from fpdf import FPDF\n\nfrom Utils.CommonUtil import get_current_datetime_for_report_format, get_current_datetime_for_fil"
},
{
"path": "src/Utils/SnifferUtil/__init__.py",
"chars": 126,
"preview": "\"\"\"\n Sniffer Utilities\n It contains necessary functionalities used for sniffers\n\n 1) Generic Sniffer with PySha"
},
{
"path": "src/Utils/SnifferUtil/generic_sniffer.py",
"chars": 3305,
"preview": "import logging\nimport os\n\nimport pyshark\nfrom Utils.FilterUtil import pyshark_filter_util as pyshark_filter_util\n\nloggin"
},
{
"path": "src/Utils/__init__.py",
"chars": 34,
"preview": "\"\"\"\n General Utility Module\n\"\"\""
},
{
"path": "src/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/captured_packets/__init__.py",
"chars": 427,
"preview": "\"\"\"\n This package contains the all captured packets.\n The files inside this package follows these rules:\n -"
},
{
"path": "src/module_installer.py",
"chars": 1235,
"preview": "print \"Checking whether we have necessary dependencies installed...\"\n\ntry:\n import paho.mqtt\n\n print \"[+] You have"
},
{
"path": "src/peniot.py",
"chars": 106,
"preview": "# Run the program driver of tkinter\n\nif __name__ == '__main__':\n from GUI.tkinter import run\n run()\n"
},
{
"path": "src/protocols/AMQP/__init__.py",
"chars": 116,
"preview": "\"\"\"\n This package contains the following functionalities:\n\n 1) Example usage of AMQP.\n 2) AMQP Scanner\n\"\"\"\n"
},
{
"path": "src/protocols/AMQP/amqp_protocol.py",
"chars": 1412,
"preview": "import unittest\n\nfrom Entity.protocol import Protocol\n\n\nclass AMQP(Protocol):\n\n def __init__(self):\n amqp_defi"
},
{
"path": "src/protocols/AMQP/amqp_scanner.py",
"chars": 1137,
"preview": "from Utils.SnifferUtil import generic_sniffer as generic_sniffer\n\n# Capturing via TShark\namqp_layer_filter = \"amqp\"\n\n\ncl"
},
{
"path": "src/protocols/AMQP/attacks/__init__.py",
"chars": 181,
"preview": "\"\"\"\n This is a package that contains attacks to AMQP protocol.\n Currently, it supports the following attacks\n\n "
},
{
"path": "src/protocols/AMQP/attacks/amqp_dos_attack.py",
"chars": 5175,
"preview": "import logging\nimport multiprocessing\nimport signal\nimport time\nimport unittest\n\nimport pika\n\nfrom Entity.attack import "
},
{
"path": "src/protocols/AMQP/attacks/amqp_fuzzing_attack_suite.py",
"chars": 1307,
"preview": "from amqp_payload_size_fuzzer import *\nfrom amqp_random_payload_fuzzing import *\nfrom Entity.attack_suite import AttackS"
},
{
"path": "src/protocols/AMQP/attacks/amqp_payload_size_fuzzer.py",
"chars": 6907,
"preview": "import logging\nimport multiprocessing\nimport random\nimport signal\nimport time\nimport unittest\n\nimport pika\n\nfrom Entity."
},
{
"path": "src/protocols/AMQP/attacks/amqp_random_payload_fuzzing.py",
"chars": 7633,
"preview": "import logging\nimport multiprocessing\nimport random\nimport signal\nimport time\nimport unittest\n\nimport pika\n\nfrom Entity."
},
{
"path": "src/protocols/AMQP/examples/__init__.py",
"chars": 122,
"preview": "\"\"\"\n This package contains the following functionalities:\n\n 1) AMQP Sender Example\n 2) AMQP Receiver Example\n\"\""
},
{
"path": "src/protocols/AMQP/examples/receiver_example.py",
"chars": 2242,
"preview": "import pika\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport time\n\nDEFAULT_BROKER_HOST = \"localhost\"\nDEFA"
},
{
"path": "src/protocols/AMQP/examples/sender_example.py",
"chars": 2691,
"preview": "import pika\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport time\n\nDEFAULT_BROKER_HOST = \"localhost\"\nDEFA"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/.gitignore",
"chars": 77,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n*.pcap\nlogs/\n"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/API Manifest.txt",
"chars": 370,
"preview": "API Manifest.txt\ndocumentation.html\nexample.py\nLICENSE.txt\nNordic Semiconductor Sniffer API Guide.pdf\nsniffer_uart_proto"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/LICENSE.txt",
"chars": 1427,
"preview": "All files in this package is released under the license below, except the \nWireshark dissector source files packet-nordi"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/README.md",
"chars": 2354,
"preview": "# Python API for Bluefruit LE Sniffer \n\nThis repository contains the Python API for Adafruit's Bluefruit LE Sniffer, and"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/CaptureFiles.py",
"chars": 3775,
"preview": "from __future__ import absolute_import\nimport time\nimport os\nimport logging\nfrom . import Logger\n\nLINKTYPE_BLUETOOTH_LE_"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Devices.py",
"chars": 3814,
"preview": "from __future__ import absolute_import\nfrom . import Notifications\nimport logging\n\n\nclass DeviceList(Notifications.Notif"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Exceptions.py",
"chars": 275,
"preview": "class SnifferTimeout(Exception):\n pass\n\n\nclass UARTPacketError(Exception):\n pass\n\n\nclass InvalidPacketException(Ex"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Logger.py",
"chars": 4265,
"preview": "from __future__ import absolute_import\nfrom __future__ import print_function\nimport time\nimport os\nimport logging\nimport"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Notifications.py",
"chars": 1676,
"preview": "from __future__ import absolute_import\nimport threading\n\n\nclass Notification():\n def __init__(self, key, msg=None):\n "
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Packet.py",
"chars": 18040,
"preview": "from __future__ import absolute_import\nfrom . import UART, Exceptions, Notifications\nimport time\nimport logging\nimport o"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Sniffer.py",
"chars": 5788,
"preview": "from __future__ import absolute_import\nimport sys\nimport os\nimport threading\nimport logging\nfrom . import SnifferCollect"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/SnifferCollector.py",
"chars": 8650,
"preview": "from __future__ import absolute_import\nfrom . import Packet, Exceptions, CaptureFiles, Devices, Notifications, Version\ni"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/UART.py",
"chars": 2440,
"preview": "from __future__ import absolute_import\nimport logging\nimport serial\nimport collections\nimport serial.tools.list_ports as"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/Version.py",
"chars": 1343,
"preview": "from __future__ import absolute_import\nfrom . import myVersion\n\npdfVersion = \"1.2\"\n\n\ndef getRevision():\n return myVer"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/SnifferAPI/myVersion.py",
"chars": 69,
"preview": "version = 1111\nversionString = \"1.0.1\"\nversionNameAppendix = \"_1111\"\n"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/documentation.html",
"chars": 10957,
"preview": "<html>\n<style>\ntable\n{\nwidth:850px;\n}\ntable,th,td\n{\nborder:1px solid black;\nborder-collapse:collapse\n}\n\ndiv\n{\nwidth:auto"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/requirements.txt",
"chars": 26,
"preview": "six>=1.11.0\npyserial>=3.4\n"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/setup.cfg",
"chars": 30,
"preview": "[flake8]\n\nmax-line-length=100\n"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/sniffer.py",
"chars": 8214,
"preview": "from __future__ import absolute_import\nfrom __future__ import print_function\nfrom six.moves import input\n\nfrom protocols"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/sniffer_uart_protocol.xlsx",
"chars": 0,
"preview": ""
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/wireshark_dissector_source/OSX/readme.md",
"chars": 497,
"preview": "This file should be place in the ~/.wireshark/plugins folder on your OS X development machine, so \n`~/.wireshark/plugins"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/wireshark_dissector_source/packet-btle.c",
"chars": 66157,
"preview": "/* packet-btle.c\n * Routines for Bluetooth Low Energy dissection\n * Copyright 2013, Mike Ryan, mikeryan /at/ isecpartner"
},
{
"path": "src/protocols/BLE/Adafruit_BLESniffer/wireshark_dissector_source/packet-nordic_ble.c",
"chars": 27135,
"preview": "/* packet-nordic_ble.c\n * Routines for nordic ble sniffer dissection\n * Copyright 201x, YOUR_NAME <YOUR_EMAIL_ADDRESS>\n "
},
{
"path": "src/protocols/BLE/BLETest.py",
"chars": 187,
"preview": "\"\"\"\n BLE (Bluetooth Low Energy) Testing Class\n Call necessary tests from this class\n\"\"\"\n\n\nclass BLETest:\n\n @sta"
},
{
"path": "src/protocols/BLE/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/protocols/BLE/attacks/__init__.py",
"chars": 117,
"preview": "\"\"\"\n This package contains the following BLE attacks:\n 1) BLE Sniff attack\n 2) BLE Replay attack\n\"\"\""
},
{
"path": "src/protocols/BLE/attacks/ble_replay_attack.py",
"chars": 922,
"preview": "import logging\n\nfrom Entity.attack import Attack\nfrom Entity.input_format import InputFormat\nfrom protocols.BLE.ble_repl"
},
{
"path": "src/protocols/BLE/attacks/ble_sniff_attack.py",
"chars": 1042,
"preview": "import logging\n\nfrom Entity.attack import Attack\nfrom Entity.input_format import InputFormat\nfrom protocols.BLE.ble_snif"
},
{
"path": "src/protocols/BLE/ble_advertiser.py",
"chars": 714,
"preview": "from bluetooth.ble import BeaconService\nimport time\nimport argparse\n\n# This one uses pybluez library!!!\n\nDEFAULT_ADVERTI"
},
{
"path": "src/protocols/BLE/ble_device.py",
"chars": 979,
"preview": "import pexpect\n\n\nclass BLEDevice:\n \"\"\"\n Represents a BLE device.\n It uses `gatttool` to connect a BLE device.\n "
},
{
"path": "src/protocols/BLE/ble_protocol.py",
"chars": 210,
"preview": "from Entity.protocol import Protocol\n\n\nclass BLE(Protocol):\n\n def __init__(self):\n ble_definition = \"\"\n "
},
{
"path": "src/protocols/BLE/ble_replay_attack.py",
"chars": 3382,
"preview": "import os\nfrom protocols.BLE.ble_device import BLEDevice\n\n\nclass BLEReplayAttackHelper:\n \"\"\"\n This is the helper c"
},
{
"path": "src/protocols/BLE/ble_sniff.py",
"chars": 3916,
"preview": "import os\nimport sys\nimport time\n\nfrom Utils import CommonUtil\nfrom protocols.BLE.Adafruit_BLESniffer import sniffer\nfro"
},
{
"path": "src/protocols/BLE/ble_tools.py",
"chars": 1759,
"preview": "from bluepy import btle\n\n\"\"\"\n This class enables us to scan for BLE devices. \n\"\"\"\n\n\nclass BLEScanner:\n \"\"\"\n Sca"
},
{
"path": "src/protocols/CoAP/__init__.py",
"chars": 2691,
"preview": "\"\"\"\n This package contains the following functionalities:\n\n 1) Example usage of CoAP.\n 2) Attacks that is done "
},
{
"path": "src/protocols/CoAP/attacks/__init__.py",
"chars": 287,
"preview": "\"\"\"\n This is a package that contains attacks to CoAP protocol.\n Currently, it supports the following attacks\n\n "
},
{
"path": "src/protocols/CoAP/attacks/coap_dos_attack.py",
"chars": 4852,
"preview": "import logging\nimport multiprocessing\nimport signal\nimport time\nimport unittest\n\nfrom coapthon.client.helperclient impor"
},
{
"path": "src/protocols/CoAP/attacks/coap_fuzzing_attack_suite.py",
"chars": 1347,
"preview": "from Entity.attack_suite import AttackSuite\nfrom coap_payload_size_fuzzer import *\nfrom coap_random_payload_fuzzing impo"
},
{
"path": "src/protocols/CoAP/attacks/coap_payload_size_fuzzer.py",
"chars": 7249,
"preview": "import logging\nimport multiprocessing\nimport random\nimport signal\nimport time\nimport unittest\n\nfrom coapthon.client.help"
},
{
"path": "src/protocols/CoAP/attacks/coap_random_payload_fuzzing.py",
"chars": 8245,
"preview": "import logging\nimport multiprocessing\nimport random\nimport signal\nimport time\nimport unittest\n\nfrom coapthon.client.help"
},
{
"path": "src/protocols/CoAP/attacks/coap_replay_attack.py",
"chars": 4841,
"preview": "import logging\nimport signal\nimport socket\nimport time\nimport unittest\n\nfrom Entity.attack import Attack\nfrom Entity.inp"
},
{
"path": "src/protocols/CoAP/attacks/coap_sniff_attack.py",
"chars": 3532,
"preview": "import logging\nimport signal\nimport time\nimport unittest\n\nfrom Entity.attack import Attack\nfrom Entity.input_format impo"
},
{
"path": "src/protocols/CoAP/coap_protocol.py",
"chars": 2521,
"preview": "from Entity.protocol import Protocol\n\nimport unittest\n\n\nclass CoAP(Protocol):\n\n def __init__(self):\n co_ap_def"
},
{
"path": "src/protocols/CoAP/coap_scanner.py",
"chars": 1751,
"preview": "from Utils.SnifferUtil import generic_sniffer as generic_sniffer\n\nimport socket\n\n# Capturing via TShark\ncoap_layer_filte"
},
{
"path": "src/protocols/CoAP/examples/__init__.py",
"chars": 149,
"preview": "\"\"\"\n This package contains the following functionalities:\n\n 1) CoAP Server Example\n 2) CoAP Client Example\n "
},
{
"path": "src/protocols/CoAP/examples/client_example.py",
"chars": 1694,
"preview": "from coapthon.client.helperclient import HelperClient\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport ti"
},
{
"path": "src/protocols/CoAP/examples/resource_example.py",
"chars": 1003,
"preview": "from coapthon.resources.resource import Resource\n\n\nclass BasicResource(Resource):\n\n def __init__(self, name=\"BasicRes"
},
{
"path": "src/protocols/CoAP/examples/server_example.py",
"chars": 1431,
"preview": "from coapthon.server.coap import CoAP\nfrom resource_example import BasicResource\n\nimport argparse\n# import logging\n\nDEFA"
},
{
"path": "src/protocols/MQTT/__init__.py",
"chars": 253,
"preview": "\"\"\"\n This package includes the following functionalities\n\n 1) Attacks to perform on MQTT protocol\n 2) MQTT subs"
},
{
"path": "src/protocols/MQTT/attacks/__init__.py",
"chars": 230,
"preview": "\"\"\"\n This is a package that contains attacks to MQTT protocol.\n Currently, it supports the following attacks\n\n "
},
{
"path": "src/protocols/MQTT/attacks/mqtt_dos_attack.py",
"chars": 5970,
"preview": "import multiprocessing\nimport random\nimport signal\nimport string\nimport sys\nimport logging\nimport time\nimport unittest\n\n"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_fuzzing_attack_suite.py",
"chars": 1480,
"preview": "from mqtt_generation_based_fuzzing import *\nfrom mqtt_payload_size_fuzzer import *\nfrom mqtt_random_payload_fuzzing impo"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_generation_based_fuzzing.py",
"chars": 10860,
"preview": "import multiprocessing\nimport unittest\n\nimport paho.mqtt.client as paho\n\nimport logging\nimport random\nimport signal\nimpo"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_payload_size_fuzzer.py",
"chars": 6265,
"preview": "import paho.mqtt.client as paho\n\nimport multiprocessing\nimport logging\nimport random\nimport time\nimport signal\nimport un"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_random_payload_fuzzing.py",
"chars": 7033,
"preview": "import multiprocessing\nimport unittest\n\nimport paho.mqtt.client as paho\n\nimport logging\nimport random\nimport signal\nimpo"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_replay_attack.py",
"chars": 5407,
"preview": "import logging\nimport signal\nimport time\nimport unittest\n\nimport paho.mqtt.client as paho\n\nfrom protocols.MQTT.mqtt_scan"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_sniff_attack.py",
"chars": 3827,
"preview": "import logging\nimport signal\nimport time\nimport unittest\n\nfrom protocols.MQTT.mqtt_scanner import MQTTScanner\nfrom Entit"
},
{
"path": "src/protocols/MQTT/attacks/mqtt_topic_name_fuzzing.py",
"chars": 5173,
"preview": "import logging\nimport multiprocessing\nimport signal\nimport time\nimport unittest\n\nimport paho.mqtt.client as paho\n\nfrom E"
},
{
"path": "src/protocols/MQTT/examples/Demo/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/protocols/MQTT/examples/Demo/demo_publisher.py",
"chars": 2552,
"preview": "import paho.mqtt.client as paho\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport time\n\nfrom Utils.RandomU"
},
{
"path": "src/protocols/MQTT/examples/Demo/demo_subscriber.py",
"chars": 4129,
"preview": "import paho.mqtt.client as paho\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport threading\n\nfrom Utils.Ra"
},
{
"path": "src/protocols/MQTT/examples/__init__.py",
"chars": 203,
"preview": "\"\"\"\n This package is written to understand basic connection and communication mechanisms by local broker servers.\n "
},
{
"path": "src/protocols/MQTT/examples/publisher_example.py",
"chars": 2528,
"preview": "import paho.mqtt.client as paho\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport time\n\nDEFAULT_BROKER_HOS"
},
{
"path": "src/protocols/MQTT/examples/subscriber_example.py",
"chars": 2391,
"preview": "import paho.mqtt.client as paho\n\nimport argparse\nimport logging\nimport signal\nimport sys\nimport time\n\nDEFAULT_BROKER_HOS"
},
{
"path": "src/protocols/MQTT/mqtt_protocol.py",
"chars": 2762,
"preview": "from Entity.protocol import Protocol\n\nimport unittest\n\n\nclass MQTT(Protocol):\n\n def __init__(self):\n mqtt_defi"
},
{
"path": "src/protocols/MQTT/mqtt_scanner.py",
"chars": 5437,
"preview": "from Utils.SnifferUtil import generic_sniffer as generic_sniffer\n\nfrom scapy.all import *\n\n# Since MQTT runs on TCP/IP, "
},
{
"path": "src/protocols/__init__.py",
"chars": 58,
"preview": "\"\"\"\n This package contains all available protocols.\n\"\"\""
}
]
About this extraction
This page contains the full source code of the yakuza8/peniot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 116 files (418.4 KB), approximately 108.8k tokens, and a symbol index with 756 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.