How to Make a Bluetooth Device Scanner in Python

Master Bluetooth device scanning with Python: A concise tutorial on using PyBluez for discovering and analyzing nearby Bluetooth devices, essential for cybersecurity and ethical hacking.
  · · 7 min read · Updated jul 2024 · Ethical Hacking

Struggling with multiple programming languages? No worries. Our Code Converter has got you covered. Give it a go!

In this tutorial, we'll explore the exciting world of Bluetooth device discovery using Python. Our focus will be on writing a script that scans for nearby Bluetooth devices and retrieves valuable information about them. This skill is not only valuable for understanding Bluetooth technology but also has practical applications in cybersecurity and ethical hacking.

Bluetooth, being a widely used wireless communication protocol, presents both opportunities and challenges for security enthusiasts. By learning how to scan and gather information about nearby devices programmatically, you'll be equipped with a fundamental skill set that can be applied to various scenarios, from identifying potential security risks to conducting ethical hacking assessments.

The Significance in Cybersecurity and Ethical Hacking

Understanding Bluetooth device discovery is a crucial aspect of networking, ethical hacking, and cybersecurity in general. This script serves as a foundation for exploring the security implications of Bluetooth technology.

Ethical hackers often use similar techniques to identify vulnerable devices, assess security postures, and conduct penetration testing. By scanning for active Bluetooth devices and obtaining details such as device names, classes, and even MAC (Media Access Control) addresses, security professionals can identify potential targets for further analysis.

Additionally, this knowledge is essential for recognizing and addressing security risks associated with Bluetooth, such as unauthorized device connections and vulnerabilities that malicious actors may exploit. 

By learning to scan Bluetooth devices, hackers could perform malicious activities like device impersonation, man-in-the-middle attacks, and Bluetooth profile weaknesses. This knowledge may lead to unauthorized access, data interception, or even denial-of-service attacks if proper security measures are not in place.

Let’s see how to implement this in Python. We’ll be making use of the PyBluez module. PyBluez is a Python module that provides Bluetooth functionality, allowing developers to implement Bluetooth communication and control Bluetooth-enabled devices. We’ll also be writing this program in Python 3.

Install PyBluez by running the following command on your cmd/Terminal:

$ pip install pybluez2

One very important thing to note is that the success of running the provided code may vary on virtual machines due to differences in Bluetooth compatibility. For a more reliable assessment, testing the code on a physical machine with native Bluetooth support is recommended.

Now, let’s get to the code. Open up a Python file, name it meaningfully (like bluetooth_scanner.py) and follow along:

import bluetooth

# Major and Minor Device Class definitions based on Bluetooth specifications
MAJOR_CLASSES = {
    0: "Miscellaneous",
    1: "Computer",
    2: "Phone",
    3: "LAN/Network Access",
    4: "Audio/Video",
    5: "Peripheral",
    6: "Imaging",
    7: "Wearable",
    8: "Toy",
    9: "Health",
    10: "Uncategorized"
}

MINOR_CLASSES = {
    # Computer Major Class
    (1, 0): "Uncategorized Computer", (1, 1): "Desktop Workstation",
    (1, 2): "Server-class Computer", (1, 3): "Laptop", (1, 4): "Handheld PC/PDA",
    (1, 5): "Palm-sized PC/PDA", (1, 6): "Wearable computer",
    # Phone Major Class
    (2, 0): "Uncategorized Phone", (2, 1): "Cellular", (2, 2): "Cordless",
    (2, 3): "Smartphone", (2, 4): "Wired modem or voice gateway",
    (2, 5): "Common ISDN Access",
    # LAN/Network Access Major Class
    (3, 0): "Fully available", (3, 1): "1% to 17% utilized",
    (3, 2): "17% to 33% utilized", (3, 3): "33% to 50% utilized",
    (3, 4): "50% to 67% utilized", (3, 5): "67% to 83% utilized",
    (3, 6): "83% to 99% utilized", (3, 7): "No service available",
    # Audio/Video Major Class
    (4, 0): "Uncategorized A/V", (4, 1): "Wearable Headset", (4, 2): "Hands-free Device",
    (4, 3): "Microphone", (4, 4): "Loudspeaker", (4, 5): "Headphones", (4, 6): "Portable Audio",
    (4, 7): "Car audio", (4, 8): "Set-top box", (4, 9): "HiFi Audio Device",
    (4, 10): "VCR", (4, 11): "Video Camera", (4, 12): "Camcorder",
    (4, 13): "Video Monitor", (4, 14): "Video Display and Loudspeaker",
    (4, 15): "Video Conferencing", (4, 16): "Gaming/Toy",
    # Peripheral Major Class
    (5, 0): "Not Keyboard/Not Pointing Device", (5, 1): "Keyboard",
    (5, 2): "Pointing device", (5, 3): "Combo Keyboard/Pointing device",
    # Imaging Major Class
    (6, 0): "Display", (6, 1): "Camera", (6, 2): "Scanner", (6, 3): "Printer",
    # Wearable Major Class
    (7, 0): "Wristwatch", (7, 1): "Pager", (7, 2): "Jacket",
    (7, 3): "Helmet", (7, 4): "Glasses",
    # Toy Major Class
    (8, 0): "Robot", (8, 1): "Vehicle",
    (8, 2): "Doll / Action figure",
    (8, 3): "Controller", (8, 4): "Game",
    # Health Major Class
    (9, 0): "Undefined", (9, 1): "Blood Pressure Monitor",
    (9, 2): "Thermometer", (9, 3): "Weighing Scale",
    (9, 4): "Glucose Meter", (9, 5): "Pulse Oximeter",
    (9, 6): "Heart/Pulse Rate Monitor", (9, 7): "Health Data Display",
    (9, 8): "Step Counter", (9, 9): "Body Composition Analyzer",
    (9, 10): "Peak Flow Monitor", (9, 11): "Medication Monitor",
    (9, 12): "Knee Prosthesis", (9, 13): "Ankle Prosthesis",
    # More specific definitions can be added if needed
}

def parse_device_class(device_class):
    major = (device_class >> 8) & 0x1F # divide by 2**8 and mask with 0x1F (take the last 5 bits)
    minor = (device_class >> 2) & 0x3F # divide by 2**2 and mask with 0x3F (take the last 6 bits)
    major_class_name = MAJOR_CLASSES.get(major, "Unknown Major Class")
    minor_class_key = (major, minor)
    minor_class_name = MINOR_CLASSES.get(minor_class_key, "Unknown Minor Class")
    return major_class_name, minor_class_name

def scan_bluetooth_devices():
    try:
        discovered_devices = bluetooth.discover_devices(duration=8, lookup_names=True, lookup_class=True)
        print('[!] Scanning for Bluetooth devices...')
        print(f"[!] Found {len(discovered_devices)} Devices")
        for addr, name, device_class in discovered_devices:
            major_class, minor_class = parse_device_class(device_class)
            print(f"[+] Device Name: {name}")
            print(f"    Address: {addr}")
            print(f"    Device Class: {device_class} ({major_class}, {minor_class})")
    except Exception as e:
        print(f"[ERROR] An error occurred: {e}")

if __name__ == "__main__":
    scan_bluetooth_devices()

This Python script utilizes the bluetooth module to scan for nearby Bluetooth devices and retrieve information about them.

The scan_bluetooth_devices() function attempts to discover Bluetooth devices by using the discover_devices() function from the bluetooth module with the parameters lookup_names=True and lookup_class=True to retrieve both device names and classes.

The script then prints a message indicating the start of the scanning process and the number of devices found. It iterates through the list of discovered devices, extracting and displaying details such as the device name, address, and device class. Any exceptions that might occur during the device discovery process are caught and handled, with an error message printed to inform the user. Finally, the function is called to execute the Bluetooth device scanning when the script is run.

Let's run it:

$ python bluetooth_scanner.py
[!] Scanning for Bluetooth devices...
[!] Found 4 Devices
[+] Device Name: Lightspeaker L2+
    Address: 11:B2:5B:8E:13:8B
    Device Class: 2360324 (Audio/Video, Wearable Headset)
[+] Device Name: AirDots
    Address: 54:67:55:AF:BA:C9
    Device Class: 2360324 (Audio/Video, Wearable Headset)
[+] Device Name: LV2016
    Address: 2C:F0:AC:F1:1F:45
    Device Class: 2360324 (Audio/Video, Wearable Headset)
[+] Device Name: Abdou's phone
    Address: FC:08:AF:99:78:31
    Device Class: 5898764 (Phone, Smartphone)

The result shows us the available Bluetooth devices around us, including their names, MAC Addresses, and Device classes.

Related: How to Make a MAC Address Changer in Python.

By obtaining MAC addresses from Bluetooth device discovery results, hackers can potentially manipulate or spoof their device's MAC address to impersonate legitimate devices. This could lead to unauthorized access, data interception, and security breaches, highlighting the importance of implementing strong security measures to prevent MAC address spoofing.

The function parse_device_class(device_class) plays a pivotal role in decoding the numeric class of a device into meaningful descriptions. Here’s how it works:

  • Extracting Major and Minor Classes: The Bluetooth device class is a field that combines information about the device’s major and minor classes into a single integer. To interpret this integer:
    • The major class is extracted by shifting the device class right by 8 bits and masking it with 0x1F (binary 11111), which isolates the last five bits.
    • The minor class is extracted by shifting the device class right by 2 bits and masking it with 0x3F (binary 111111), isolating the last six bits.
  • Mapping to Descriptions: These extracted values are then used as keys to look up descriptions from predefined dictionaries (MAJOR_CLASSES and MINOR_CLASSES) that map these keys to human-readable class name.

Let’s take an example of my phone’s device class, which has the number 5898764 in decimal:

  1. Convert this to binary: 00000000 01011010 00000010 00001100
  2. For the major class, shift the device class right by 8 bits, resulting to: 00000000 00000000 01011010 00000010
  3. Extract the last five bits: 00010 -> Decimal of 2, indicating a Phone device.
  4. For the minor class, shift the device class right by 2 bits, resulting in: 00000000 00010110 10000000 10000011
  5. Extract the last six bits: 000011 -> Decimal of 3, indicating a Smartphone.

These interpretations are based on the Bluetooth Core Specification documents provided by the Bluetooth Special Interest Group. Feel free to check it out here. Even if hackers don’t fully understand the class concept, they can still do much damage with the device name and MAC address.

Learn also: How to Build a WiFi Scanner in Python using Scapy.

I hope you enjoyed this tutorial. Happy coding!

Why juggle between languages when you can convert? Check out our Code Converter. Try it out today!

View Full Code Analyze My Code
Sharing is caring!



Read Also



Comment panel

    Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!