Newer
Older
BLE_CTF_V2 / lvl_03.py
root on 11 Mar 2022 4 KB tidying for public release
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function   # import print from python3: end=""
import time   
import re
import pexpect    # sudo apt-get install python-pexpect
import subprocess
import random
import binascii
import struct
import sys, os, time
import bluepy.btle as btle

'''
Service <uuid=Heart Rate handleStart=40 handleEnd=65535>
42  0x2A   READ         Connect with pin 0000. Try using bluetoothctl

b46fa238cf820d0f60c1
'''

# !!! make sure bluetoothd runs in --compat mode before executing this script !!!
def pair_with_pin(start_time, pin, time_limit=60):  # int(time.time()), pin - \d{4}, time_limit - approximate pairing window time in seconds, it might take up to 2x (nested timeout conditions)
    "exectutes pairing with entered PIN on bluetooth adapter side"
    try:
        
        newpid = os.fork()
        if newpid == 0:
            time.sleep(5)
            '''
            Start bluepy stuff
            '''
            subprocess.call(['hciconfig','hci0','down'])
            subprocess.call(['hciconfig','hci0','up'])

            deviceMAC = open('ctf_mac.txt').read()  
            p = btle.Peripheral(deviceMAC)
            svc=p.getServiceByUUID("0000180d-0000-1000-8000-00805f9b34fb")
            print ("Attached to peripheral (pid 0)")  
            hex1 = p.readCharacteristic(0x2C)
            hex2 = binascii.b2a_hex(hex1) 
            hexlif2 = str(binascii.unhexlify(hex2))
            print("Flag: "+hexlif2) 
            p.disconnect()
            exit()
        else:
            
            '''
             Start actual pair stuff 
            '''
            subprocess.call(['hciconfig','hci0','sspmode', '0'])
            
            # bluetoothctl 
            print("Pairing")
            child = pexpect.spawn('bluetoothctl')
            child.logfile = open("/tmp/mylog", "w")
            child.expect("#")
            child.sendline('agent off') # might be unnecessary
            #child.sendline('scan on') # might be unnecessary
            child.expect("unregistered")
            
            child.sendline('agent KeyboardDisplay ')
            child.expect("Agent registered")
            child.sendline('pairable on')
            child.expect("pairable on succeeded")
            child.sendline('discoverable on')
            child.expect("discoverable on succeeded")
            child.sendline('default-agent')
            child.sendline('remove 3c:71:bf:f1:ef:c6')
            child.sendline('scan on')
            child.expect("Device 3C:71:BF:F1:EF:C6 FLAG_3")
            child.sendline('pair 3c:71:bf:f1:ef:c6')

            child.expect('Request passkey', timeout = time_limit )   # timeout <= PAIRING_TIME_LIMIT to keep some kind of logic
            print ('Sending PIN: ' + pin) 
            child.sendline(pin)
            i = child.expect(['Paired: yes', 'Enter passkey:'], timeout = time_limit)
            if i == 0: # found 'Paired: yes' == successful pairing
                trust_mac = 'trust ' + re.search(r'(?:[0-9a-fA-F]:?){12}.+$', child.before).group(0)    # extract MAC from last line, one with 'Paired: Yes'
                child.sendline(trust_mac)   # optionally add device to trusted
                child.expect('trust succeeded', timeout = 10)                
                pairing_status = True
                child.sendline('remove 3c:71:bf:f1:ef:c6')
            else: # i == 1
                print('wrong PIN, retrying if time will allow') 
    except pexpect.EOF:
        print ('!!!!!!!! EOF')
    except pexpect.TIMEOUT:
        print ('!!!!!!!! TIMEOUT')
        
    # hide Pi's bluetooth for security reasons
    child.sendline('pairable off')
    child.expect("pairable off succeeded")
    child.sendline('discoverable off')
    child.expect("discoverable off succeeded")    
    child.close()
    
    return pairing_status

#main program body
PAIRING_TIME_LIMIT = 60
BT_PIN = "0000" # random.randint(1000,10000)    # generate random 4-digit PIN 1000..9999

deviceMAC = open('ctf_mac.txt').read()  
p = btle.Peripheral(deviceMAC)
svc=p.getServiceByUUID(0x00FF)
print ("Attached to peripheral")

print("Loading level 03")
hex1 = binascii.unhexlify(str('%0*x' % (4,3)))
p.writeCharacteristic(0x30, hex1, withResponse=False)

p.disconnect()

status = pair_with_pin(int(time.time()), str(BT_PIN), PAIRING_TIME_LIMIT)
if status == True:
    print('Pairing successful')