diff --git a/BlueDucky.py b/BlueDucky.py index e18e171..f5b0465 100644 --- a/BlueDucky.py +++ b/BlueDucky.py @@ -2,6 +2,7 @@ import binascii, bluetooth, sys, time, datetime, logging, argparse from multiprocessing import Process from pydbus import SystemBus from enum import Enum +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 @@ -637,8 +638,31 @@ def main(): if not target_address: 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() + print("\nAvailable payloads:") + for idx, payload_file in enumerate(payloads, 1): # Check and enumerate the files inside the payload folder. + print(f"{idx}: {payload_file}") + + payload_choice = input("\nEnter the number of the payload you want to load: ") + selected_payload = None + + try: + payload_index = int(payload_choice) - 1 + selected_payload = os.path.join(payload_folder, payloads[payload_index]) + except (ValueError, IndexError): + print("Invalid payload choice. No payload selected.") + + if selected_payload is not None: + print(f"Selected payload: {selected_payload}") + duckyscript = read_duckyscript(selected_payload) + else: + print("No payload selected.") + + if not duckyscript: log.info("Payload file not found. Exiting.") return @@ -672,4 +696,4 @@ if __name__ == "__main__": try: main() finally: - terminate_child_processes() \ No newline at end of file + terminate_child_processes() diff --git a/payload.txt b/payload.txt deleted file mode 100644 index 67f064b..0000000 --- a/payload.txt +++ /dev/null @@ -1,2 +0,0 @@ -REM This is a comment and will not run -STRING hello there 123 diff --git a/payloads/payload_example_1.txt b/payloads/payload_example_1.txt new file mode 100644 index 0000000..6fbc51f --- /dev/null +++ b/payloads/payload_example_1.txt @@ -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 diff --git a/payloads/payload_example_2.txt b/payloads/payload_example_2.txt new file mode 100644 index 0000000..345c8f5 --- /dev/null +++ b/payloads/payload_example_2.txt @@ -0,0 +1,4 @@ +REM This is a comment and will not run +STRING hello opening messages here +DELAY 200 +GUI s diff --git a/utils/menu_functions.py b/utils/menu_functions.py index 2501b55..2affe1b 100644 --- a/utils/menu_functions.py +++ b/utils/menu_functions.py @@ -9,7 +9,12 @@ 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"Would you like to enter this device :\n{devices[0][1]} {devices[0][0]} ? (y/n)\n").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): @@ -151,13 +156,14 @@ def main_menu(): 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()]