Merge branch 'main' into requirements
This commit is contained in:
commit
5c4101340e
127
BlueDucky.py
127
BlueDucky.py
|
@ -1,7 +1,9 @@
|
|||
import binascii, bluetooth, sys, time, datetime, logging
|
||||
import binascii, bluetooth, sys, time, datetime, logging, argparse
|
||||
from multiprocessing import Process
|
||||
from pydbus import SystemBus
|
||||
from enum import Enum
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
from utils.menu_functions import (main_menu, read_duckyscript, run, restart_bluetooth_daemon, get_target_address)
|
||||
from utils.register_device import register_hid_profile, agent_loop
|
||||
|
@ -14,8 +16,6 @@ class AnsiColorCode:
|
|||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
BLUE = '\033[94m'
|
||||
MAGENTA = '\033[95m'
|
||||
CYAN = '\033[96m'
|
||||
WHITE = '\033[97m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
|
@ -29,8 +29,8 @@ class ColorLogFormatter(logging.Formatter):
|
|||
logging.INFO: AnsiColorCode.GREEN,
|
||||
logging.WARNING: AnsiColorCode.YELLOW,
|
||||
logging.ERROR: AnsiColorCode.RED,
|
||||
logging.CRITICAL: AnsiColorCode.MAGENTA,
|
||||
NOTICE_LEVEL: AnsiColorCode.CYAN, # Color for NOTICE level
|
||||
logging.CRITICAL: AnsiColorCode.RED,
|
||||
NOTICE_LEVEL: AnsiColorCode.BLUE, # Color for NOTICE level
|
||||
}
|
||||
|
||||
def format(self, record):
|
||||
|
@ -267,9 +267,20 @@ class L2CAPClient:
|
|||
self.connected = True
|
||||
log.debug("SUCCESS! connected on port %d" % self.port)
|
||||
except Exception as ex:
|
||||
# Color Definition Again just to avoid errors I should've made a class for this.
|
||||
red = "\033[91m"
|
||||
blue = "\033[94m"
|
||||
reset = "\033[0m"
|
||||
|
||||
error = True
|
||||
self.connected = False
|
||||
log.error("ERROR connecting on port %d: %s" % (self.port, ex))
|
||||
raise ConnectionFailureException(f"Connection failure on port {self.port}")
|
||||
if (error == True & self.port == 14):
|
||||
print("{reset}[{red}!{reset}] {red}CRITICAL ERROR{reset}: {reset}Attempted Connection to {red}{target_address} {reset}was {red}denied{reset}.")
|
||||
return self.connected
|
||||
|
||||
|
||||
|
||||
return self.connected
|
||||
|
||||
|
@ -593,13 +604,14 @@ def terminate_child_processes():
|
|||
if proc.is_alive():
|
||||
proc.terminate()
|
||||
proc.join()
|
||||
|
||||
|
||||
def setup_bluetooth(target_address):
|
||||
def setup_bluetooth(target_address, adapter_id):
|
||||
restart_bluetooth_daemon()
|
||||
profile_proc = Process(target=register_hid_profile, args=('hci0', target_address))
|
||||
profile_proc = Process(target=register_hid_profile, args=(adapter_id, target_address))
|
||||
profile_proc.start()
|
||||
child_processes.append(profile_proc)
|
||||
adapter = Adapter('hci0')
|
||||
adapter = Adapter(adapter_id)
|
||||
adapter.set_property("name", "Robot POC")
|
||||
adapter.set_property("class", 0x002540)
|
||||
adapter.power(True)
|
||||
|
@ -617,28 +629,94 @@ def establish_connections(connection_manager):
|
|||
if not connection_manager.connect_all():
|
||||
raise ConnectionFailureException("Failed to connect to all required ports")
|
||||
|
||||
def setup_and_connect(connection_manager, target_address):
|
||||
def setup_and_connect(connection_manager, target_address, adapter_id):
|
||||
connection_manager.create_connection(1) # SDP
|
||||
connection_manager.create_connection(17) # HID Control
|
||||
connection_manager.create_connection(19) # HID Interrupt
|
||||
initialize_pairing('hci0', target_address)
|
||||
initialize_pairing(adapter_id, target_address)
|
||||
establish_connections(connection_manager)
|
||||
return connection_manager.clients[19]
|
||||
|
||||
def troubleshoot_bluetooth():
|
||||
# Added this function to troubleshoot common issues before access to the application is granted
|
||||
|
||||
blue = "\033[0m"
|
||||
red = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
# Check if bluetoothctl is available
|
||||
try:
|
||||
subprocess.run(['bluetoothctl', '--version'], check=True, stdout=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError:
|
||||
print("{reset}[{red}!{reset}] {red}CRITICAL{reset}: {blue}bluetoothctl {reset}is not installed or not working properly.")
|
||||
return False
|
||||
|
||||
# Check for Bluetooth adapters
|
||||
result = subprocess.run(['bluetoothctl', 'list'], capture_output=True, text=True)
|
||||
if "Controller" not in result.stdout:
|
||||
print("{reset}[{red}!{reset}] {red}CRITICAL{reset}: No {blue}Bluetooth adapters{reset} have been detected.")
|
||||
return False
|
||||
|
||||
# List devices to see if any are connected
|
||||
result = subprocess.run(['bluetoothctl', 'devices'], capture_output=True, text=True)
|
||||
if "Device" not in result.stdout:
|
||||
print("{reset}[{red}!{reset}] {red}CRITICAL{reset}: No Compatible {blue}Bluetooth devices{reset} are connected.")
|
||||
return False
|
||||
|
||||
# if no issues are found then continue
|
||||
return True
|
||||
|
||||
# Main function
|
||||
def main():
|
||||
blue = "\033[0m"
|
||||
red = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
parser = argparse.ArgumentParser(description="Bluetooth HID Attack Tool")
|
||||
parser.add_argument('--adapter', type=str, default='hci0', help='Specify the Bluetooth adapter to use (default: hci0)')
|
||||
args = parser.parse_args()
|
||||
adapter_id = args.adapter
|
||||
|
||||
main_menu()
|
||||
target_address = get_target_address()
|
||||
if not target_address:
|
||||
log.info("No target address provided. Exiting.")
|
||||
log.info("No target address provided. Exiting..")
|
||||
return
|
||||
|
||||
script_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
payload_folder = os.path.join(script_directory, 'payloads/') # Specify the relative path to the payloads folder.
|
||||
payloads = os.listdir(payload_folder)
|
||||
|
||||
duckyscript = read_duckyscript()
|
||||
blue = "\033[0m"
|
||||
red = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
print(f"\nAvailable payloads{blue}:")
|
||||
for idx, payload_file in enumerate(payloads, 1): # Check and enumerate the files inside the payload folder.
|
||||
print(f"{reset}[{blue}{idx}{reset}]{blue}: {blue}{payload_file}")
|
||||
|
||||
blue = "\033[0m"
|
||||
red = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
payload_choice = input(f"\n{blue}Enter the number that represents the payload you would like to load{reset}: {blue}")
|
||||
selected_payload = None
|
||||
|
||||
try:
|
||||
payload_index = int(payload_choice) - 1
|
||||
selected_payload = os.path.join(payload_folder, payloads[payload_index])
|
||||
except (ValueError, IndexError):
|
||||
print(f"Invalid payload choice. No payload selected.")
|
||||
|
||||
if selected_payload is not None:
|
||||
print(f"{blue}Selected payload{reset}: {blue}{selected_payload}")
|
||||
duckyscript = read_duckyscript(selected_payload)
|
||||
else:
|
||||
print(f"{red}No payload selected.")
|
||||
|
||||
|
||||
|
||||
if not duckyscript:
|
||||
log.info("Payload file not found. Exiting.")
|
||||
return
|
||||
|
||||
adapter = setup_bluetooth(target_address)
|
||||
adapter = setup_bluetooth(target_address, adapter_id)
|
||||
adapter.enable_ssp()
|
||||
|
||||
current_line = 0
|
||||
|
@ -647,24 +725,35 @@ def main():
|
|||
|
||||
while True:
|
||||
try:
|
||||
hid_interrupt_client = setup_and_connect(connection_manager, target_address)
|
||||
hid_interrupt_client = setup_and_connect(connection_manager, target_address, adapter_id)
|
||||
process_duckyscript(hid_interrupt_client, duckyscript, current_line, current_position)
|
||||
time.sleep(2)
|
||||
break # Exit loop if successful
|
||||
|
||||
except ReconnectionRequiredException as e:
|
||||
log.info("Reconnection required. Attempting to reconnect...")
|
||||
log.info(f"{reset}Reconnection required. Attempting to reconnect{blue}...")
|
||||
current_line = e.current_line
|
||||
current_position = e.current_position
|
||||
connection_manager.close_all()
|
||||
# Sleep before retrying to avoid rapid reconnection attempts
|
||||
time.sleep(2)
|
||||
|
||||
#process_duckyscript(hid_interrupt_client, duckyscript)
|
||||
|
||||
finally:
|
||||
# unpair the target device
|
||||
blue = "\033[94m"
|
||||
reset = "\033[0m"
|
||||
|
||||
command = f'echo -e "remove {target_address}\n" | bluetoothctl'
|
||||
subprocess.run(command, shell=True)
|
||||
print(f"{blue}Successfully Removed device{reset}: {blue}{target_address}{reset}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup_logging()
|
||||
log = logging.getLogger(__name__)
|
||||
try:
|
||||
main()
|
||||
if troubleshoot_bluetooth():
|
||||
main()
|
||||
else:
|
||||
sys.exit(0)
|
||||
finally:
|
||||
terminate_child_processes()
|
||||
terminate_child_processes()
|
||||
|
|
49
README.md
49
README.md
|
@ -1,10 +1,13 @@
|
|||
# BlueDucky (Android) 🦆
|
||||
# BlueDucky Ver 2.1 (Android) 🦆
|
||||
|
||||
Thanks to all the people at OWLSec. Make sure you come join us on VC !
|
||||
https://discord.gg/owlsec
|
||||
Thanks to all the people at HackNexus. Make sure you come join us on VC !
|
||||
https://discord.gg/HackNexus
|
||||
|
||||
NOTES: I will not be able to run this on a laptop or other device outside of a raspberry pi for testing. Due to this, any issues you have will need to be resolved amonsgt each other as I do not have the spare funds to buy an adapter.
|
||||
|
||||
1. [saad0x1's GitHub](https://github.com/saad0x1)
|
||||
2. [spicydll's GitHub](https://github.com/spicydll)
|
||||
3. [lamentomori's GitHub](https://github.com/lamentomori)
|
||||
|
||||
<p align="center">
|
||||
<img src="./images/duckmenu.png">
|
||||
|
@ -31,7 +34,7 @@ I've successfully run this on a Raspberry Pi 4 using the default Bluetooth modul
|
|||
|
||||
## Installation and Usage 🛠️
|
||||
|
||||
### Setup Instructions
|
||||
### Setup Instructions for Debian-based
|
||||
|
||||
```bash
|
||||
# update apt
|
||||
|
@ -48,6 +51,29 @@ git clone https://github.com/pybluez/pybluez.git
|
|||
cd pybluez
|
||||
sudo python3 setup.py install
|
||||
|
||||
# build bdaddr from the bluez source
|
||||
cd ~/
|
||||
git clone --depth=1 https://github.com/bluez/bluez.git
|
||||
gcc -o bdaddr ~/bluez/tools/bdaddr.c ~/bluez/src/oui.c -I ~/bluez -lbluetooth
|
||||
sudo cp bdaddr /usr/local/bin/
|
||||
```
|
||||
### Setup Instructions for Arch-based
|
||||
|
||||
```bash
|
||||
# update pacman & packages
|
||||
sudo pacman -Syyu
|
||||
|
||||
# install dependencies
|
||||
# since arch doesn't separate lib packages: libbluetooth-dev included in bluez package
|
||||
sudo pacman -S bluez-tools bluez-utils bluez-deprecated-tools \
|
||||
python-setuptools python-pydbus python-dbus
|
||||
git gcc python-pip \
|
||||
|
||||
# install pybluez from source
|
||||
git clone https://github.com/pybluez/pybluez.git
|
||||
cd pybluez
|
||||
sudo python3 setup.py install
|
||||
|
||||
# build bdaddr from the bluez source
|
||||
cd ~/
|
||||
git clone --depth=1 https://github.com/bluez/bluez.git
|
||||
|
@ -63,6 +89,12 @@ sudo hciconfig hci0 up
|
|||
python3 BlueDucky.py
|
||||
```
|
||||
|
||||
alternatively,
|
||||
|
||||
```bash
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
## Operational Steps 🕹️
|
||||
1. On running, it prompts for the target MAC address.
|
||||
2. Pressing nothing triggers an automatic scan for devices.
|
||||
|
@ -75,6 +107,15 @@ python3 BlueDucky.py
|
|||
🚧 Work in Progress:
|
||||
- Suggest me ideas
|
||||
|
||||
## Version 2.1 🐛
|
||||
- Updated UI
|
||||
- Improved User Experience
|
||||
- Bluetooth Debugger; Checks your bluetooth adapters, and installed dependancies before allowing access to the application, this is to prevent devices that are not supported.
|
||||
- Please Note: Numerous Changes have been made,please reference the commit history for specific changes.
|
||||
|
||||
## What's Planned for the Next Release?
|
||||
- Integrated DuckyScript Console for attacks that want to maintain persistance, after a payload has been ran
|
||||
- Suggest What Should be added next! Join https://discord.gg/HackNexus
|
||||
|
||||
#### 📝 Example payload.txt:
|
||||
```bash
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 18 KiB |
|
@ -1,2 +0,0 @@
|
|||
REM This is a comment and will not run
|
||||
STRING hello there 123
|
|
@ -0,0 +1,16 @@
|
|||
REM Opens a private browser to hackertyper.net
|
||||
DELAY 200
|
||||
ESCAPE
|
||||
GUI d
|
||||
ALT ESCAPE
|
||||
GUI b
|
||||
DELAY 700
|
||||
REM PRIVATE_BROWSER is equal to CTRL + SHIFT + N
|
||||
PRIVATE_BROWSER
|
||||
DELAY 700
|
||||
CTRL l
|
||||
DELAY 300
|
||||
STRING hackertyper.net
|
||||
DELAY 300
|
||||
ENTER
|
||||
DELAY 300
|
|
@ -0,0 +1,4 @@
|
|||
REM This is a comment and will not run
|
||||
STRING hello opening messages here
|
||||
DELAY 200
|
||||
GUI s
|
|
@ -0,0 +1,48 @@
|
|||
REM Opens a browser to https://wa.me/<+number>
|
||||
DELAY 200
|
||||
ESCAPE
|
||||
GUI d
|
||||
ALT ESCAPE
|
||||
GUI b
|
||||
DELAY 700
|
||||
REM BROWSER is equal to CTRL + SHIFT + N
|
||||
BROWSER
|
||||
DELAY 700
|
||||
CTRL l
|
||||
DELAY 300
|
||||
STRING https://wa.me/<+NUMBER>
|
||||
DELAY 500
|
||||
ENTER
|
||||
DELAY 3000
|
||||
TAB
|
||||
TAB
|
||||
TAB
|
||||
TAB
|
||||
TAB
|
||||
ENTER
|
||||
DELAY 7000
|
||||
REM # Enter your message here
|
||||
STRING get clapped by 4ngel6uard
|
||||
DELAY 500
|
||||
TAB
|
||||
TAB
|
||||
ENTER
|
||||
DELAY 2000
|
||||
REM # Enter your another message here
|
||||
STRING hehehe
|
||||
DELAY 300
|
||||
TAB
|
||||
TAB
|
||||
ENTER
|
||||
DELAY 2000
|
||||
REM # Enter your another message here
|
||||
STRING blueducky was there
|
||||
DELAY 300
|
||||
TAB
|
||||
TAB
|
||||
ENTER
|
||||
DELAY 2000
|
||||
REM # Enter your another message here (doesn't send, leaves in a box)
|
||||
STRING good luck =)
|
||||
|
||||
|
|
@ -3,3 +3,6 @@ PyBluez==0.30
|
|||
pycairo==1.26.0
|
||||
pydbus==0.6.0
|
||||
PyGObject==3.48.1
|
||||
pyobjc
|
||||
pybluez
|
||||
setuptools==57.5.0
|
|
@ -1,7 +1,15 @@
|
|||
import os, bluetooth,re, subprocess, time, curses
|
||||
import os, bluetooth, re, subprocess, time, curses
|
||||
import logging as log
|
||||
|
||||
##########################
|
||||
# UI Redesign by Lamento #
|
||||
##########################
|
||||
|
||||
def get_target_address():
|
||||
target_address = input("\nWhat is the target address? Leave blank and we will scan for you: ")
|
||||
blue = "\033[94m"
|
||||
reset = "\033[0m"
|
||||
print(f"\n What is the target address{blue}? {reset}Leave blank and we will scan for you{blue}!{reset}")
|
||||
target_address = input(f"\n {blue}> ")
|
||||
|
||||
if target_address == "":
|
||||
devices = scan_for_devices()
|
||||
|
@ -9,12 +17,17 @@ def get_target_address():
|
|||
# Check if the returned list is from known devices or scanned devices
|
||||
if len(devices) == 1 and isinstance(devices[0], tuple) and len(devices[0]) == 2:
|
||||
# A single known device was chosen, no need to ask for selection
|
||||
target_address = devices[0][0]
|
||||
# I think it would be better to ask, as sometimes I do not want to chose this device and actually need solely to scan for actual devices.
|
||||
confirm = input(f"\n Would you like to register this device{blue}:\n{reset}{devices[0][1]} {devices[0][0]}{blue}? {blue}({reset}y{blue}/{reset}n{blue}) {blue}").strip().lower()
|
||||
if confirm == 'y' or confirm == 'yes':
|
||||
return devices[0][0]
|
||||
elif confirm != 'y' or 'yes':
|
||||
return
|
||||
else:
|
||||
# Show list of scanned devices for user selection
|
||||
for idx, (addr, name) in enumerate(devices):
|
||||
print(f"{idx + 1}: Device Name: {name}, Address: {addr}")
|
||||
selection = int(input("\nSelect a device by number: ")) - 1
|
||||
print(f"{reset}[{blue}{idx + 1}{reset}] {blue}Device Name{reset}: {blue}{name}, {blue}Address{reset}: {blue}{addr}")
|
||||
selection = int(input(f"\n{reset}Select a device by number{blue}: {blue}")) - 1
|
||||
if 0 <= selection < len(devices):
|
||||
target_address = devices[selection][0]
|
||||
else:
|
||||
|
@ -41,38 +54,30 @@ def run(command):
|
|||
def print_fancy_ascii_art():
|
||||
|
||||
ascii_art = """
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣄⣤⣤⣄⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⡶⠟⠛⠉⠉⠉⠉⠉⠉⠉⠉⠉⠙⠛⠷⢶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢷⣤⡀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣧⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣠⣤⣤⣤⣤⣤⣄⣀⡀⠀⠀⢹⣧⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣶⣿⣷⣶⠶⠛⠛⠛⠛⠳⢶⣦⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣯⠉⠉⠉⠉⠉⠛⣷⠀⠀⢿⡄⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⢀⣠⣿⣀⡀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⠀⢀⣀⣀⣤⣴⠟⠀⠀⠸⣧⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⣙⣿⣿⣿⣿⣿⣿⠶⠶⠶⠿⠛⠛⠛⠛⠛⠛⢷⣦⡀⠉⠙⠛⠛⠛⠛⠛⠛⠛⠋⠉⠁⠀⠀⠀⠀⠀⣿⠀⠀⠀
|
||||
⠀⢀⣠⣴⠶⠾⠛⠛⠛⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡀⠀⠀
|
||||
⢠⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀
|
||||
⠈⢿⣦⣄⣀⣀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣤⣤⣤⣄⣀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀
|
||||
⠀⠀⠈⠉⠛⠛⠛⢻⣟⠛⠛⠛⠛⠛⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠻⠷⠀⢀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠛⠷⢶⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣴⠶⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⢹⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡇⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣇⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣆⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⢶
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣴⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⢀⣤⣤⡀⢀⣤⣤⡀⠀⣤⠀⠀⢀⣤⣄⢀⣤⣤⡀⠀⠀⣤⠀⠀⣠⠀⢀⣄⠀⠀⣠⣤⡀⠀⠀⠀⡀⠀⣠⡀⣠⣤⣤⣠⡀⠀⣤⢀⣤⣤⡀⣤⣤⡀
|
||||
⢸⣯⣹⡗⣿⣿⡏⠀⣼⣿⣇⢰⡿⠉⠃⣿⣿⡍⠀⠀⠀⢿⣤⣦⣿⠀⣾⢿⡆⢾⣯⣝⡃⠀⠀⢰⣿⣆⣿⡧⣿⣽⡍⠘⣷⣸⡏⣾⣿⡯⢸⣯⣩⡿
|
||||
⢸⡟⠉⠀⢿⣶⣶⢰⡿⠟⢻⡾⢷⣴⡆⢿⣶⣶⠄⠀⠀⠸⡿⠻⡿⣼⡿⠟⢿⢤⣭⣿⠟⠀⠀⢸⡇⠻⣿⠃⣿⣼⣶⠀⢻⡟⠀⢿⣧⣶⠸⣿⠻⣧
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⢀⡀⠀⠀⠀⠀⣀⠀⠀⠀⠀⣀⡀⠈⢀⣀⣀⠀⣁⣀⣀⢀⡀⠀⢀⣀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⠀⢠⣧⡀⣿⠀⠀⠀⣼⡿⢿⣄⣼⡟⢿⡿⠿⣿⠿⢻⣧⢠⡿⠿⣧⣀⣿⡄⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣧⣾⡟⣷⣿⠀⠀⠘⣿⣀⣸⡟⢹⡿⠟⠁⠀⣿⡀⢸⣏⢿⣇⣠⣿⢻⣏⢿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠁⠀⠙⠙⠁⠘⠋⠀⠀⠀⠈⠉⠉⠀⠘⠁⠀⠀⠀⠉⠁⠈⠁⠀⠉⠉⠁⠈⠋⠈⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"""
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠤⠄⠒⠒⠒⠒⠒⠒⠂⠠⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠴⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⠁⠀⠀⠀⠀⣀⡤⠴⠒⠒⠒⠒⠦⠤⣀⠀⠀⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⢰⠋⠀⠀⠀⣠⠖⠋⢀⣄⣀⡀⠀⠀⠀⠀⠀⠀⠉⠲⣄⠀⠈⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⢀⡼⠁⠀⣴⣿⡛⠻⣿⣧⡀⠀⠀⠀⠀⠀⠀⠈⠳⡄⡿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⣼⣀⣀⣀⡜⠀⠀⠀⣿⣿⣿⣿⣿⣿⡧⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⣀⡤⠟⠁⠀⠈⠙⡶⣄⡀⠈⠻⢿⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠇⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⣤⣤⠖⠖⠛⠉⠈⣀⣀⠀⠴⠊⠀⠀⣹⣷⣶⡏⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⣀⡀⠀⠀
|
||||
⠘⠿⣿⣷⣶⣶⣶⣶⣤⣶⣶⣶⣿⣿⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⠤⠖⠒⠋⠉⠁⠙⣆⠀
|
||||
⠀⠀⠀⠀⠉⠉⠉⠉⠙⠿⣍⣩⠟⠋⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣖⣶⣶⢾⠯⠽⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡄
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⠚⠁⠀⠀⠀⠀⠈⠓⠤⠀⠀⠀⠀⠀⠀⠐⠒⠚⠉⠉⠁⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⣀⢀⠀⠀⠀⠀⠀⠀⠀⣇
|
||||
⠀⠀⠀⠀⠀⠀⠀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠤⠤⠖⠒⠚⠉⠉⠁⠀⠀⠀⢸⢸⣦⠀⠀⠀⠀⠀⠀⢸
|
||||
⠀⠀⠀⠀⠀⢠⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⡠⠤⠴⠒⠒⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡏⣸⡏⠇⠀⠀⠀⠀⠀⢸
|
||||
⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠞⢠⡿⠀⠀⠀⠀⠀⠀⠀⢸
|
||||
⠀⠀⠀⠀⣾⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠊⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⡏
|
||||
⠀⠀⠀⠀⡏⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠖⠉⢀⣴⠏⠠⠀⠀⠀⠀⠀⠀⠀⣸⠁
|
||||
⠀⠀⠀⠀⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠒⠒⠢⠤⠄⠀⠀⠀⠀⠀⠈⠁⠀⣠⣶⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⢠⠃⠀
|
||||
⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⠿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠃⠀⠀
|
||||
⠀⠀⠀⠀⠀⠈⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⡶⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠃⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠳⣄⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠤⠖⣪⡵⠋⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠈⠑⠫⠭⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣭⣭⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⡴⠶⠛⠉⠀⠀⠀⠀⠀⠀⠀
|
||||
"""
|
||||
|
||||
print("\033[1;36m" + ascii_art + "\033[0m") # Cyan color
|
||||
print("\033[94m" + ascii_art + "\033[0m") # Blue color
|
||||
|
||||
def clear_screen():
|
||||
os.system('clear')
|
||||
|
@ -83,45 +88,44 @@ def save_devices_to_file(devices, filename='known_devices.txt'):
|
|||
for addr, name in devices:
|
||||
file.write(f"{addr},{name}\n")
|
||||
|
||||
def get_yes_no():
|
||||
stdscr = curses.initscr()
|
||||
curses.cbreak()
|
||||
stdscr.keypad(1)
|
||||
|
||||
while True:
|
||||
key = stdscr.getch()
|
||||
if key == ord('y'):
|
||||
response = 'yes'
|
||||
break
|
||||
elif key == ord('n'):
|
||||
response = 'no'
|
||||
break
|
||||
|
||||
curses.endwin()
|
||||
return response
|
||||
|
||||
# Function to scan for devices
|
||||
def scan_for_devices():
|
||||
main_menu()
|
||||
|
||||
blue = "\033[94m"
|
||||
error = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
|
||||
# Load known devices
|
||||
known_devices = load_known_devices()
|
||||
if known_devices:
|
||||
print("\nKnown devices:")
|
||||
blue = "\033[94m"
|
||||
error = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
print(f"\n{reset}Known devices{blue}:")
|
||||
for idx, (addr, name) in enumerate(known_devices):
|
||||
print(f"{idx + 1}: Device Name: {name}, Address: {addr}")
|
||||
blue = "\033[94m"
|
||||
error = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
print(f"{blue}{idx + 1}{reset}: Device Name: {blue}{name}, Address: {blue}{addr}")
|
||||
|
||||
use_known_device = input("\nDo you want to use one of these known devices? (yes/no): ")
|
||||
blue = "\033[94m"
|
||||
error = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
use_known_device = input(f"\n{reset}Do you want to use one of these known devices{blue}? {blue}({reset}yes{blue}/{reset}no{blue}): ")
|
||||
if use_known_device.lower() == 'yes':
|
||||
device_choice = int(input("Enter the number of the device: "))
|
||||
device_choice = int(input(f"{reset}Enter the index number of the device to attack{blue}: "))
|
||||
return [known_devices[device_choice - 1]]
|
||||
|
||||
# Normal Bluetooth scan
|
||||
print("\nAttempting to scan now...")
|
||||
blue = "\033[94m"
|
||||
error = "\033[91m"
|
||||
reset = "\033[0m"
|
||||
print(f"\n{reset}Attempting to scan now{blue}...")
|
||||
nearby_devices = bluetooth.discover_devices(duration=8, lookup_names=True, flush_cache=True, lookup_class=True)
|
||||
device_list = []
|
||||
if len(nearby_devices) == 0:
|
||||
print("\nNo nearby devices found.")
|
||||
print(f"\n{reset}[{error}+{reset}] No nearby devices found.")
|
||||
else:
|
||||
print("\nFound {} nearby device(s):".format(len(nearby_devices)))
|
||||
for idx, (addr, name, _) in enumerate(nearby_devices):
|
||||
|
@ -133,31 +137,45 @@ def scan_for_devices():
|
|||
known_devices += new_devices
|
||||
save_devices_to_file(known_devices)
|
||||
for idx, (addr, name) in enumerate(new_devices):
|
||||
print(f"{idx + 1}: Device Name: {name}, Address: {addr}")
|
||||
print(f"{reset}{idx + 1}{blue}: {blue}Device Name{reset}: {blue}{name}{reset}, {blue}Address{reset}: {blue}{addr}")
|
||||
return device_list
|
||||
|
||||
def getterm():
|
||||
size = os.get_terminal_size()
|
||||
return size.columns
|
||||
|
||||
|
||||
def print_menu():
|
||||
blue = '\033[94m'
|
||||
reset = "\033[0m"
|
||||
title = "BlueDucky - Bluetooth Device Attacker"
|
||||
separator = "=" * 70
|
||||
print("\033[1;35m" + separator) # Purple color for separator
|
||||
print("\033[1;33m" + title.center(len(separator))) # Yellow color for title
|
||||
print("\033[1;35m" + separator + "\033[0m") # Purple color for separator
|
||||
print("\033[1;32m" + "Remember, you can still attack devices without visibility..." + "\033[0m")
|
||||
print("\033[1;32m" + "If you have their MAC address" + "\033[0m")
|
||||
print("\033[1;35m" + separator + "\033[0m") # Purple color for separator
|
||||
vertext = "Ver 2.1"
|
||||
motd1 = f"Remember, you can still attack devices without visibility.."
|
||||
motd2 = f"If you have their MAC address.."
|
||||
terminal_width = getterm()
|
||||
separator = "=" * terminal_width
|
||||
|
||||
print(blue + separator) # Blue color for separator
|
||||
print(reset + title.center(len(separator))) # Centered Title in blue
|
||||
print(blue + vertext.center(len(separator))) # Centered Version
|
||||
print(blue + separator + reset) # Blue color for separator
|
||||
print(motd1.center(len(separator)))# used the same method for centering
|
||||
print(motd2.center(len(separator)))# used the same method for centering
|
||||
print(blue + separator + reset) # Blue color for separator
|
||||
|
||||
def main_menu():
|
||||
clear_screen()
|
||||
print_fancy_ascii_art()
|
||||
print_menu()
|
||||
|
||||
|
||||
def is_valid_mac_address(mac_address):
|
||||
# Regular expression to match a MAC address in the form XX:XX:XX:XX:XX:XX
|
||||
mac_address_pattern = re.compile(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$')
|
||||
return mac_address_pattern.match(mac_address) is not None
|
||||
|
||||
# Function to read DuckyScript from file
|
||||
def read_duckyscript(filename='payload.txt'):
|
||||
def read_duckyscript(filename):
|
||||
if os.path.exists(filename):
|
||||
with open(filename, 'r') as file:
|
||||
return [line.strip() for line in file.readlines()]
|
||||
|
@ -172,3 +190,19 @@ def load_known_devices(filename='known_devices.txt'):
|
|||
return [tuple(line.strip().split(',')) for line in file]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
title = "BlueDucky - Bluetooth Device Attacker"
|
||||
vertext = "Ver 2.1"
|
||||
terminal_width = getterm()
|
||||
separator = "=" * terminal_width
|
||||
blue = "\033[0m"
|
||||
reset = "\033[0m"
|
||||
|
||||
print(blue + separator) # Blue color for separator
|
||||
print(reset + title.center(len(separator))) # White color for title
|
||||
print(blue + vertext.center(len(separator))) # White blue for version number
|
||||
print(blue + separator + reset) # Blue color for separator
|
||||
print(f"{reset}Remember, you can still attack devices without visibility{blue}.." + reset)
|
||||
print(f"{blue}If you have their {reset}MAC address{blue}.." + reset)
|
||||
print(blue + separator + reset) # Blue color for separator
|
||||
|
|
Loading…
Reference in New Issue