Unpairing a DualShock 4 and Setting a new BDADDR

While doing stuff regarding sniffing and spoofing a DualShock 4 controller for the Playstation 4, it might be useful to permanently unpair a DualShock 4 from the Playstation 4. This tool does that by setting a new Bluetooth MAC address (BDADDR) into a DualShock 4 using a computer.

Use this Python script. It works under Python 2.7.3 , and requires PyUSB and netaddr to be installed. Usage instructions are contained within the code. Windows users will need libusb-win32 and the install-filter-win tool contained inside libusb-win32.

# This tool is supposed to override the PS4 BDADDR inside a DualShock 4
# By Frank Zhao, see https://eleccelerator.com/wiki/index.php?title=DualShock_4
# You may need to install a filter driver before libusb can access the device, use "install-filter-win.exe" from libusb-win32

import sys, time, getopt, select
import usb.core, usb.util
from netaddr import *

def main(argv):
    verbose = False
    mac = False
    needRead = False

    try:
       opts, args = getopt.getopt(argv,"hvra:",[])
    except getopt.GetoptError:
        print 'Error: GetoptError'
        printHelp()
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            printHelp()
            sys.exit()
        elif opt in ("-a"):
            mac = EUI(arg)
        elif opt in ("-r"):
            needRead = True
        elif opt in ("-v"):
            verbose = True

    if mac != None and mac != False and mac != 0:
        if verbose:
            print 'Setting MAC to: ', str(mac), ' , words[', len(mac.words) ,']: ', mac.words

    if verbose:
        print 'Searching for USB device with VID 0x054C and PID 0x05C4'

    dev = usb.core.find(idVendor = 0x054C, idProduct = 0x05C4)
    if dev == None or dev == False or dev == 0:
        print 'Unable to find DualShock 4'
        print 'You may need to install a filter driver before libusb can access the device, use "install-filter-win.exe" from libusb-win32'
        quit()

    if verbose:
        print 'Found DualShock 4 in USB port'

    dev.set_configuration()
    if verbose:
        print 'USB device set configuration'

    if needRead:
        if verbose:
            print 'Attempting read with USB control transfer GET REPORT on 0x12'
        msg = dev.ctrl_transfer(0xA1, 0x01, 0x0312, 0x0000, 0x0010);
        if verbose:
            print 'Read back raw data from report 0x12: [ ', printHexArray(msg), ']'
        print 'Read DualShock4 UID: ', EUI(format(msg[6], 'X') + '-' + format(msg[5], 'X') + '-' + format(msg[4], 'X') + '-' + format(msg[3], 'X') + '-' + format(msg[2], 'X') + '-' + format(msg[1], 'X'))
        print 'Read PlayStation4 MAC: ', EUI(format(msg[15], 'X') + '-' + format(msg[14], 'X') + '-' + format(msg[13], 'X') + '-' + format(msg[12], 'X') + '-' + format(msg[11], 'X') + '-' + format(msg[10], 'X'))

    if mac != None and mac != False and mac != 0:
        if verbose:
            print 'USB sending control transfer SET REPORT on 0x13'
        msg = [0x13, mac.words[5], mac.words[4], mac.words[3], mac.words[2], mac.words[1], mac.words[0], 0x56, 0xE8, 0x81, 0x38, 0x08, 0x06, 0x51, 0x41, 0xC0, 0x7F, 0x12, 0xAA, 0xD9, 0x66, 0x3C, 0xCE];
        ret = dev.ctrl_transfer(0x21, 0x09, 0x0313, 0x0000, msg);
        print 'Written raw data to report 0x13, return code was: ', ret
        if needRead:
            if verbose:
                print 'Attempting read with USB control transfer GET REPORT on 0x12'
            msg = dev.ctrl_transfer(0xA1, 0x01, 0x0312, 0x0000, 0x0010);
            if verbose:
                print 'Read back raw data from report 0x12: [ ', printHexArray(msg), ']'
            print 'Read DualShock4 UID: ', EUI(format(msg[6], 'X') + '-' + format(msg[5], 'X') + '-' + format(msg[4], 'X') + '-' + format(msg[3], 'X') + '-' + format(msg[2], 'X') + '-' + format(msg[1], 'X'))
            print 'Read PlayStation4 MAC: ', EUI(format(msg[15], 'X') + '-' + format(msg[14], 'X') + '-' + format(msg[13], 'X') + '-' + format(msg[12], 'X') + '-' + format(msg[11], 'X') + '-' + format(msg[10], 'X'))

    if verbose:
        print 'That\'s all this tool will do, goodbye'
        quit()

def printHexArray(arr):
    str = ''
    for i in arr:
        str += '0x' + format(i, 'X') + ', '
    return str

def printHelp():
    print 'This tool is supposed to override the PS4 BDADDR inside a DualShock 4'
    print ''
    print 'command line options:'
    print '-h'
    print '    will print the help'
    print ''
    print '-a <PS4\'s BDADDR>'
    print '    will set BDADDR, common formats accepted but no spaces allowed'
    print ''
    print '-r'
    print '    will do a control transfer read on report 0x12'
    print ''
    print '-v'
    print '    will enable verbose output'
    print ''
    print 'By Frank Zhao, see https://eleccelerator.com/wiki/index.php?title=DualShock_4'

if __name__ == "__main__":
    main(sys.argv[1:])

 

4 thoughts on “Unpairing a DualShock 4 and Setting a new BDADDR

  1. James

    Hi Frank. Thank you so much for the script and all that info on the wiki. I’m trying to troubleshoot my PS4 with it.

    I need your help with one thing though, if possible. Can you tell me what is the “OUI” address used by the PS4(the console) bluetooth? I mean I need to know the first three octets from the bluetooth MAC address. I will do a scan on the entire range(using redfang) to try to find the one from my PS4 but it will be way easier knowing at least the range.

    My problem is that my PS4 is not syncing any more controllers. When the problem first happened I went to test my DS4 on the PS3, so the MAC that was registered under the DS4 was the PS3`s, not the PS4 one! I am now blind without knowing not even the OUI. I know that even with it I’m still trapped with 16 million results but I have no choice. I can’t afford to buy another now. Also there are a lot of people online with very similar problems so I hope it will have some use to others too.

    I know both DS4 and PS4 are still trying to sync because I can scan the controllers “response” when plugged to ps4. My guess is that the headers on ps4 request are somehow corrupted but if I found the bd_addr and use your script to set it manually I’m hoping to get it working again.

    Sorry about the long message and thank you very much!
    Best regards.

    Reply
    1. James

      Hey Frank. I managed to got the OUI range on the PS4 BD_ADDR from the wiresharks samples you provided on the wiki.
      Thank you very much!

      Reply
  2. Wz

    I don’t know a lot about USB, but it errored with:
    usb.core.USBError: [Errno 16] Resource busy

    I also tried powering off PS4

    Reply

Leave a Reply to Wz Cancel reply

Your email address will not be published. Required fields are marked *