IVI Simulator¶
Work in Progress
The IVI Simulator is currently broken and under active development. Expect incomplete functionality and potential issues. This page documents the intended design.
The Vulnerable IVI Simulator is an intentionally insecure Bluetooth car head unit
that ships in the target/ directory. It creates a real Bluetooth target (not a mock)
on any Linux machine, behaving like a car infotainment system with known vulnerabilities
for safe, repeatable testing.
Unlike demo mode, which uses simulated data, the IVI simulator creates a live Bluetooth device that responds to real over-the-air connections. Blue-Tap's discovery, reconnaissance, exploitation, and data extraction modules all interact with it exactly as they would with a real car head unit -- making it the ideal training and validation environment.
Purpose¶
- Practice Blue-Tap commands against a real Bluetooth target without needing a vehicle
- Demonstrate all attack vectors in a controlled environment where mistakes have no consequences
- Validate tool functionality after installation or updates
- Train operators on the full Bluetooth assessment workflow before field engagements
- Develop and test new Blue-Tap modules against a known-good target
Requirements¶
Hardware¶
- 2 Bluetooth adapters -- one for the IVI simulator, one for Blue-Tap (can be on the same machine using two USB dongles), OR
- 1 adapter + 1 phone -- run the IVI on a Linux machine, attack from a phone or second machine
- Any adapter supporting Classic Bluetooth (CSR 8510, Intel, Broadcom, RTL8761B)
Same-Machine Two-Adapter Setup
The most convenient setup uses two USB Bluetooth dongles on the same laptop. One
runs the IVI simulator (e.g., hci1), the other runs Blue-Tap (e.g., hci0).
This way you only need a single machine for the entire training environment.
See Hardware Setup -- Two-Adapter Setup
for adapter recommendations.
Software¶
- Linux (Kali, Ubuntu 22.04+, Raspberry Pi OS)
- Python 3.10+
- BlueZ 5.x with compatibility mode enabled for
sdptool
Platform Notes¶
| Platform | Notes |
|---|---|
| Kali Linux | All tools pre-installed, recommended |
| Ubuntu / Debian | Install bluez, bluez-tools; enable compat mode |
| Raspberry Pi | Built-in BT adapter works; install bluez |
Architecture¶
The IVI simulator consists of four processes that together emulate a car infotainment system's Bluetooth stack. The setup script configures the adapter identity and SDP records, the PIN agent handles pairing, the IVI daemon listens for connections on multiple channels, and the optional BLE GATT server exposes BLE services.
graph TB
subgraph "IVI Simulator (Adapter: hci1)"
SETUP["setup_ivi.sh<br/><small>Adapter config + SDP</small>"]
PIN["pin_agent.py<br/><small>Legacy PIN: 1234</small>"]
DAEMON["ivi_daemon.py<br/><small>RFCOMM + L2CAP listeners</small>"]
BLE["ble_gatt.py<br/><small>BLE GATT server</small>"]
subgraph "Protocol Engines"
AT["at_engine.py<br/><small>HFP/SPP AT commands</small>"]
OBEX["obex_servers.py<br/><small>PBAP, MAP, OPP</small>"]
end
DAEMON --> AT
DAEMON --> OBEX
end
subgraph "Blue-Tap (Adapter: hci0)"
BT["blue-tap CLI"]
end
BT -- "Classic BT<br/>over the air" --> DAEMON
BT -- "BLE<br/>over the air" --> BLE
BT -- "Pairing" --> PIN
style SETUP fill:#546e7a,color:#fff
style PIN fill:#e65100,color:#fff
style DAEMON fill:#00897b,color:#fff
style BLE fill:#3f51b5,color:#fff
style BT fill:#5c6bc0,color:#fff
Components¶
| Component | File | Role |
|---|---|---|
| Setup script | setup_ivi.sh |
Configures adapter name, class, SDP records, pairing mode |
| IVI daemon | ivi_daemon.py |
Listens on RFCOMM channels and L2CAP PSMs, dispatches connections to protocol engines |
| PIN agent | pin_agent.py |
Responds to pairing requests with legacy PIN "1234" |
| BLE GATT server | ble_gatt.py |
Exposes Device Info, Battery, and custom IVI BLE services |
| Configuration | ivi_config.py |
Shared constants: channel map, UUIDs, device identity, protocol constants |
| OBEX engines | obex_servers.py |
PBAP, MAP, OPP protocol handlers serving fake contacts, messages, and file push |
| AT engine | at_engine.py |
HFP and SPP AT command responder returning fake IMEI, IMSI, battery, signal strength |
| Data generator | obex_servers.py |
Generates fake contacts, messages, call history for PBAP/MAP |
Default Identity¶
The simulator presents itself as a Ford SYNC head unit by default:
| Property | Value | Why This Matters |
|---|---|---|
| Device name | SYNC | Common IVI name that triggers automatic pairing on many phones |
| Device class | 0x200408 (Audio/Video: Car Audio) |
Identifies the device as a car audio system in Bluetooth discovery |
| Default PIN | 1234 | Deliberately weak -- the most common legacy Bluetooth PIN |
| Pre-paired phone | AA:BB:CC:DD:EE:FF ("Galaxy S24") | Simulates a phone that was previously paired to the IVI |
Installation¶
System Dependencies¶
Enable BlueZ Compatibility Mode¶
sdptool requires the BlueZ compatibility plugin to register SDP service records. Without it, the IVI simulator cannot advertise its services and Blue-Tap's SDP enumeration will find nothing.
sudo sed -i 's|ExecStart=/usr/lib/bluetooth/bluetoothd|ExecStart=/usr/lib/bluetooth/bluetoothd --compat|' \
/lib/systemd/system/bluetooth.service
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
Verify compatibility mode is active:
Expected output (abbreviated)
If this returns service records instead of an error like Failed to connect to SDP server, compatibility mode is active.
Compatibility Mode Security Note
The --compat flag enables the legacy SDP server interface, which is disabled by
default in modern BlueZ because it allows any local process to register SDP records.
This is fine for a test environment but should not be left enabled on production
systems.
Generate Test Data¶
The simulator includes pre-generated test data in target/data/. To regenerate
or customize:
This creates vCard contacts (50 entries), SMS messages (20 entries), and call history entries used by the PBAP and MAP services. The generated data uses realistic but fake names, numbers, and content.
Quick Start¶
The simulator requires three components running in separate terminals (four if using BLE). All must run as root.
Configure the adapter identity and register SDP service records:
$ cd target/
$ sudo ./setup_ivi.sh
[*] Using adapter: hci1
[*] Setting device name: SYNC
[*] Setting device class: 0x200408 (Car Audio)
[*] Registering SDP services...
SPP (RFCOMM 1) .................. registered
Hidden Debug (RFCOMM 2) ......... registered (no SDP)
OPP (RFCOMM 9) .................. registered
HFP (RFCOMM 10) ................. registered
PBAP (RFCOMM 15) ................ registered
MAP (RFCOMM 16) ................. registered
[*] Setting pairing mode: auto (legacy PIN)
[*] Adding pre-paired device: AA:BB:CC:DD:EE:FF (Galaxy S24)
[+] IVI adapter configured. Start pin_agent.py and ivi_daemon.py next.
Start the pairing agent that responds to pairing requests with PIN "1234":
$ cd target/
$ sudo python3 pin_agent.py
[*] PIN Agent started
[*] Waiting for pairing requests...
[*] Default PIN: 1234
When a device pairs, you will see:
Start the main IVI daemon that listens for connections:
$ cd target/
$ sudo python3 ivi_daemon.py
[*] IVI Daemon started on hci1 (SYNC)
[*] Listening on:
RFCOMM 1 (SPP) ............... ready
RFCOMM 2 (Hidden Debug) ...... ready
RFCOMM 9 (OPP) ............... ready
RFCOMM 10 (HFP) ............... ready
RFCOMM 15 (PBAP) .............. ready
RFCOMM 16 (MAP) ............... ready
L2CAP 7 (BNEP) .............. ready
L2CAP 23 (AVCTP) ............. ready
L2CAP 25 (AVDTP) ............. ready
[*] Waiting for connections...
Start the BLE GATT server for BLE testing:
To stop the simulator:
Exposed Services¶
The IVI simulator exposes a realistic set of Bluetooth services that mirror what you would find on an actual car head unit. Each service is deliberately configured with security weaknesses to create a comprehensive practice target.
Classic Bluetooth (RFCOMM + L2CAP)¶
| Service | Protocol | Channel/PSM | What It Does | Why It's Vulnerable |
|---|---|---|---|---|
| SPP (Serial Port) | RFCOMM | 1 | AT command responder | Accepts connections without authentication; returns device identifiers (IMEI, IMSI) via AT commands |
| Hidden Debug | RFCOMM | 2 | Not registered in SDP | Channel exists but is not advertised -- tests whether the assessment tool probes beyond SDP |
| OPP (Object Push) | RFCOMM | 9 | Accepts any file | No authentication, no file type filtering -- any file can be pushed to the IVI |
| HFP (Hands-Free) | RFCOMM | 10 | Full SLC handshake, AT command set | Full hands-free profile with AT command access, enabling call control and device information extraction |
| PBAP (Phonebook) | RFCOMM | 15 | 50 contacts, call history (OBEX) | Phonebook exposed without authentication -- contacts, call logs, and favorites are freely accessible |
| MAP (Messages) | RFCOMM | 16 | 20 SMS messages (OBEX) | Message store exposed without authentication -- full SMS content, timestamps, and phone numbers |
| BNEP (PAN) | L2CAP | 7 | Fuzz absorber | Accepts and logs malformed BNEP packets without crashing -- tests fuzzer stability |
| AVCTP (AVRCP) | L2CAP | 23 | Fuzz absorber | Accepts and logs malformed AVCTP packets |
| AVDTP (A2DP) | L2CAP | 25 | Fuzz absorber | Accepts and logs malformed AVDTP packets |
BLE (GATT)¶
| Service | UUID | Characteristics | Vulnerability |
|---|---|---|---|
| Device Information | 0x180A |
Manufacturer, Model, Firmware Rev, Software Rev, PnP ID | Exposes detailed firmware version information useful for fingerprinting |
| Battery | 0x180F |
Battery Level (read/notify) | None (informational) |
| Custom IVI | 12345678-... |
Vehicle Speed (read), Diag Data (read), OTA Update (write, no auth) | OTA Update characteristic is writable without authentication -- could allow firmware injection |
Built-in Vulnerabilities¶
Each vulnerability below maps to a specific Blue-Tap command that detects or exploits it. This makes the simulator a practical training tool: run the command, observe the finding, understand why it matters.
| Vulnerability | Severity | How Blue-Tap Finds It | Real-World Impact |
|---|---|---|---|
| Legacy PIN pairing ("1234") | HIGH | blue-tap exploit pin-brute |
Attacker can pair to the IVI by brute-forcing the 4-digit PIN (10,000 combinations, often under 30 seconds) |
| Unauthenticated OBEX (PBAP/MAP/OPP) | CRITICAL | blue-tap vulnscan |
Contacts, messages, and call history can be extracted without pairing -- the most common real-world IVI vulnerability |
| Just Works pairing (SSP mode) | HIGH | blue-tap vulnscan |
SSP with "Just Works" association requires no user confirmation on many devices, enabling silent pairing |
| No PIN rate limiting | MEDIUM | blue-tap vulnscan |
No lockout after failed PIN attempts, making brute force trivially fast |
| Hidden RFCOMM channel (ch 2) | MEDIUM | blue-tap vulnscan |
Debug interface accessible but not advertised in SDP -- missed by tools that only check SDP records |
| Permissive AT commands | MEDIUM | blue-tap extract at |
AT commands return IMEI, IMSI, and subscriber info -- device identity information useful for tracking |
| Writable BLE GATT (OTA, no auth) | HIGH | blue-tap recon gatt |
Unauthenticated write access to OTA update characteristic could allow firmware modification |
| Hijack-vulnerable bond | CRITICAL | blue-tap exploit hijack |
Bond can be stolen by spoofing a previously-paired device's MAC address |
| No encryption enforcement | HIGH | blue-tap vulnscan |
Services accept unencrypted connections, enabling passive eavesdropping |
Testing Workflows¶
Discovery and Reconnaissance¶
# Discover the IVI
$ sudo blue-tap discover classic --hci hci0
# Look for "SYNC" with class "Car Audio"
# Full SDP enumeration
$ sudo blue-tap recon <IVI_MAC> sdp
# Expect: 7 registered services + 1 hidden channel
# BLE GATT enumeration (if ble_gatt.py running)
$ sudo blue-tap recon <IVI_MAC> gatt
# Expect: 3 GATT services including writable OTA characteristic
Vulnerability Scanning¶
Runs all assessment checks. Expect findings for unauthenticated OBEX, weak pairing, hidden channels, and missing encryption. The IVI simulator is designed to produce at least 9 findings (2 CRITICAL, 4 HIGH, 3 MEDIUM) on a clean scan.
Data Extraction¶
# Pull phonebook (PBAP) -- expect 50 contacts
$ sudo blue-tap extract <IVI_MAC> contacts
# Pull messages (MAP) -- expect 20 SMS messages
$ sudo blue-tap extract <IVI_MAC> messages
# Push a file (OPP) -- IVI accepts anything
$ sudo blue-tap extract <IVI_MAC> push --file test.vcf
Data Extraction Without Pairing
On the IVI simulator, PBAP, MAP, and OPP all work without pairing. This mirrors real-world IVI vulnerabilities where OBEX services are exposed without authentication. In a real engagement, this is typically a CRITICAL finding.
HFP / AT Commands¶
The SPP channel (1) and HFP channel (10) both respond to AT commands. The AT engine returns fake IMEI, IMSI, battery, signal strength, operator, and subscriber number.
AT command session example
PIN Brute Force¶
The IVI uses legacy PIN "1234" with no rate limiting. Expect the brute force to succeed within a few seconds.
Fuzzing¶
# SDP deep fuzz
$ sudo blue-tap fuzz <IVI_MAC> sdp-deep
# L2CAP signaling fuzz
$ sudo blue-tap fuzz <IVI_MAC> l2cap-sig
# RFCOMM raw fuzz
$ sudo blue-tap fuzz <IVI_MAC> rfcomm-raw
The L2CAP PSM listeners (BNEP, AVCTP, AVDTP) act as fuzz absorbers -- they accept and log malformed data without crashing. This tests your fuzzer's stability and packet generation without risk of losing the target. The IVI daemon logs all received fuzz packets to stdout, so you can verify what the target actually received.
Connection Hijack¶
The IVI's bonding configuration is intentionally vulnerable to hijack attacks. This requires MAC spoofing capability on your attacking adapter -- see Hardware Setup -- MAC Address Spoofing.
Configuration¶
Changing IVI Name and Class¶
Edit target/ivi_config.py:
Or pass arguments to the setup script:
# Custom profile and phone MAC
sudo ./setup_ivi.sh legacy AA:BB:CC:DD:EE:FF
# Custom adapter
sudo ./setup_ivi.sh auto AA:BB:CC:DD:EE:FF hci1
Setup Profiles¶
The setup script supports multiple profiles that configure different pairing behaviors. This lets you test Blue-Tap against various pairing configurations without editing config files.
| Profile | Command | Pairing Behavior | Attack Surface |
|---|---|---|---|
auto |
sudo ./setup_ivi.sh |
Auto-detect best profile | Tests both legacy and SSP depending on adapter capabilities |
legacy |
sudo ./setup_ivi.sh legacy |
Force legacy PIN mode | PIN brute force, no SSP protections |
ssp |
sudo ./setup_ivi.sh ssp |
Force SSP / Just Works | Just Works pairing with no user confirmation |
detect |
sudo ./setup_ivi.sh detect |
Dry-run diagnostics only | No changes -- reports what would be configured |
reset |
sudo ./setup_ivi.sh reset |
Undo all adapter changes | Restores adapter to default state |
Changing the PIN¶
Edit target/ivi_config.py:
The PIN agent (pin_agent.py) reads this value at startup. You can change it to test Blue-Tap's brute force against different PIN values -- for example, set it to "9999" to verify the brute force covers the full keyspace.
Changing the Pre-Paired Phone MAC¶
# Via setup script argument
sudo ./setup_ivi.sh auto BB:CC:DD:EE:FF:00
# Or edit ivi_config.py
DEFAULT_PHONE_MAC = "BB:CC:DD:EE:FF:00"
The pre-paired MAC matters for connection hijack testing: Blue-Tap's hijack module spoofs this address to steal the bond.
Test Data Size¶
Regenerate with custom counts by editing obex_servers.py generation parameters
or modifying the vCard/message files in target/data/ directly.
Adapter Selection¶
# Use hci1 instead of default hci0
sudo ./setup_ivi.sh auto AA:BB:CC:DD:EE:FF hci1
sudo python3 ivi_daemon.py --hci hci1
sudo python3 ble_gatt.py --hci hci1
Troubleshooting¶
Adapter not found¶
Cause: The specified HCI adapter does not exist or is not recognized by BlueZ.
Fix:
# List available adapters
hciconfig -a
# If adapter exists but is DOWN
sudo hciconfig hci0 up
# If USB adapter not detected, check dmesg
dmesg | tail -20
SDP registration failed¶
Cause: BlueZ compatibility mode is not enabled. sdptool requires the --compat flag on bluetoothd.
Fix:
sudo sed -i 's|ExecStart=/usr/lib/bluetooth/bluetoothd|ExecStart=/usr/lib/bluetooth/bluetoothd --compat|' \
/lib/systemd/system/bluetooth.service
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
L2CAP PSM bind error¶
Cause: Another process (often bluetoothd) already holds the PSM.
Fix:
# Check what is using the PSM
sudo ss -tlnp | grep bluetooth
# Restart bluetoothd to release PSMs
sudo systemctl restart bluetooth
# Then start the IVI daemon again
sudo python3 ivi_daemon.py
SSP cannot be disabled¶
On some kernels and BlueZ versions, disabling SSP (Secure Simple Pairing) to force legacy PIN mode is not supported at the management API level.
Symptoms: setup_ivi.sh legacy completes but the adapter still uses SSP.
Fix:
# Check current SSP state
sudo btmgmt info
# If SSP cannot be disabled, use the ssp profile instead
sudo ./setup_ivi.sh ssp
The ssp profile configures Just Works pairing, which is also a valid attack surface
(no user confirmation required on many devices).
IVI not visible during discovery¶
Symptoms: Blue-Tap's discover classic does not find the IVI.
Fix:
# Verify the IVI adapter is UP and PSCAN-enabled (page scan = discoverable)
sudo hciconfig hci1
# Look for "UP RUNNING PSCAN" in the output
# If PSCAN is missing
sudo hciconfig hci1 piscan
# Verify from a different tool
bluetoothctl scan on
Separate Adapters
If Blue-Tap and the IVI simulator are on the same machine, they must use different
adapters. A single adapter cannot simultaneously act as both the scanner and the
target. Use --hci hci0 for Blue-Tap and hci1 for the IVI (or vice versa).
What's Next?¶
- Quick Start -- run the standard assessment workflow against the IVI simulator
- Full Penetration Test -- end-to-end workflow including exploitation and post-exploitation
- Fuzzing Campaign -- use the IVI's fuzz absorbers for protocol fuzzing practice
- Troubleshooting -- general Blue-Tap troubleshooting guide