├── READ.md ├── contributors.txt ├── .gitignore ├── bdaddr ├── data.db ├── packet.cpp ├── Makefile ├── packet.h ├── strategy.h ├── READ.ME ├── global.cpp ├── pairing.h ├── Database.h ├── sdpscan.h ├── devscan.h ├── bProfile.h ├── strategy.cpp ├── global.h ├── bProtocol.h ├── bProfile.cpp ├── prtRFCOMM.h ├── prtL2CAP.h ├── Fuzzer.h ├── devscan.cpp ├── bProtocol.cpp ├── prtSDP.h ├── prtOBEX.h ├── iGenerator.h ├── Database.cpp ├── prtSDP.cpp ├── prtRFCOMM.cpp ├── prtL2CAP.cpp ├── Fuzzer.cpp ├── main.cpp ├── iGenerator.cpp ├── pairing.cpp ├── prtOBEX.cpp ├── sdpscan.cpp └── bdaddr.c /READ.md: -------------------------------------------------------------------------------- 1 | # Intl_Study_bbfuz 2 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | dngthe93 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | BTTestingTool 3 | db_test 4 | log.wfl -------------------------------------------------------------------------------- /bdaddr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Earl31/IntlStudy_bbfuzz/HEAD/bdaddr -------------------------------------------------------------------------------- /data.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Earl31/IntlStudy_bbfuzz/HEAD/data.db -------------------------------------------------------------------------------- /packet.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "packet.h" 3 | 4 | 5 | packet::packet() 6 | { 7 | } 8 | 9 | packet::~packet() 10 | { 11 | } 12 | 13 | int packet::_parse_packet(uint8_t *p, int size) 14 | { 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | OBJS = main.o bProtocol.o bProfile.o sdpscan.o prtL2CAP.o prtRFCOMM.o prtOBEX.o \ 3 | iGenerator.o devscan.o strategy.o pairing.o global.o Fuzzer.o prtSDP.o \ 4 | Database.o packet.o 5 | TARGET = BTTestingTool 6 | 7 | .SUFFIXES : .c .o 8 | 9 | all : $(TARGET) 10 | 11 | $(TARGET): $(OBJS) 12 | $(CC) -o $@ $(OBJS) -lbluetooth -lsqlite3 13 | 14 | clean : 15 | rm -f $(OBJS) $(TARGET) 16 | -------------------------------------------------------------------------------- /packet.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __PACKET_H__ 3 | #define __PACKET_H__ 4 | 5 | 6 | #include 7 | #include 8 | 9 | #if ( __cplusplus > 201103L ) 10 | #include 11 | 12 | #else 13 | #include 14 | 15 | #endif 16 | 17 | class packet 18 | { 19 | public: 20 | packet(); 21 | ~packet(); 22 | 23 | std::string msg; 24 | int proto; 25 | 26 | private: 27 | std::vector _payload; 28 | int _parse_packet(uint8_t *p, int size); 29 | }; 30 | 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /strategy.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __STRATEGY_H__ 17 | #define __STRATEGY_H__ 18 | 19 | extern int anal_lev; 20 | extern int depth; 21 | 22 | int strategy(); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /READ.ME: -------------------------------------------------------------------------------- 1 | Black Box Testing - Bluetooth Stateful Fuzzer 2 | 3 | USB dongle : Insignia™ - Bluetooth 4.0 USB Adapter ( Dongle is not important - just use yours ) 4 | 5 | How to use this tool 6 | 7 | 1. Go to kernell 8 | 2. Go to bluetooth_fuzz 9 | 3. make 10 | 4. ./BBTestingTool 11 | 12 | And you can choose two option. 13 | 14 | If you choose [1] - You can analyze your dongle. (Sniffing, Spoofing) 15 | If you choose [2] - You can analyze your bluetooth device. (Protocol Fuzzing) 16 | 17 | You have to choose 2 if you want to fuzz your device. -------------------------------------------------------------------------------- /global.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "global.h" 17 | 18 | //vector profiles; 19 | vector devices; 20 | vector hcidevs; 21 | 22 | bdaddr_t snf_bdr; 23 | bdaddr_t inq_bdr; 24 | bdaddr_t m_bdr; 25 | bdaddr_t s_bdr; 26 | 27 | FILE *fi; -------------------------------------------------------------------------------- /pairing.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __PAIRING_H__ 17 | #define __PAIRING_H__ 18 | 19 | #include "global.h" 20 | 21 | int pairing_check(); 22 | int hciscan(); 23 | int unpair_check(); 24 | int changebdaddr(string dev_inq, string new_bdr); 25 | int spoof_check(); 26 | int sniff_check(); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /Database.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __DATABASE_H__ 3 | #define __DATABASE_H__ 4 | 5 | #include 6 | #include 7 | #include "global.h" 8 | 9 | //#define QUERY_COUNT "SELECT COUNT(*) FROM packets WHERE proto = %d and state = %d" 10 | #define QUERY_COUNT "SELECT COUNT(*) FROM packets WHERE proto = %d;" 11 | //#define QUERY_GET "SELECT id, size, lower(quote(data)) FROM packets WHERE proto = %d LIMIT %d, 1;" 12 | #define QUERY_GET "SELECT id, size, data FROM packets WHERE proto = %d LIMIT %d, 1;" 13 | 14 | class Database 15 | { 16 | public: 17 | Database(); 18 | ~Database(); 19 | 20 | int open(const char *dbname); 21 | int open(); 22 | int close(); 23 | 24 | int get_packet(int proto, int state, int random, char *packet, int *size); 25 | private: 26 | sqlite3 *db; 27 | }; 28 | 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /sdpscan.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | 17 | #ifndef __SDPSCAN_H__ 18 | #define __SDPSCAN_H__ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "bProtocol.h" 28 | #include "bProfile.h" 29 | #include "prtL2CAP.h" 30 | #include "prtRFCOMM.h" 31 | #include "prtOBEX.h" 32 | #include "prtSDP.h" 33 | 34 | int sdpscan(char* szbtaddr, vector &bprofiles); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /devscan.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __DEVSCAN_H__ 17 | #define __DEVSCAN_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bProfile.h" 25 | //#include "sdpscan.h" 26 | 27 | using namespace std; 28 | 29 | class devscan 30 | { 31 | public: 32 | devscan(); 33 | ~devscan(); 34 | 35 | string name; 36 | string bt_addr; 37 | vector profiles; 38 | }; 39 | 40 | void finddev(); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /bProfile.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | 17 | #ifndef __BPROFILE_H__ 18 | #define __BPROFILE_H__ 19 | 20 | 21 | #include 22 | #include 23 | 24 | #include "bProtocol.h" 25 | 26 | 27 | using namespace std; 28 | 29 | 30 | class bProfile 31 | { 32 | public: 33 | bProfile(); 34 | ~bProfile(); 35 | bProfile(const bProfile &b); 36 | 37 | string name; 38 | int code; 39 | int version; 40 | uuid_t uuid; 41 | vector protocols; 42 | 43 | char *szbtaddr; 44 | 45 | private: 46 | 47 | }; 48 | 49 | 50 | 51 | #endif 52 | 53 | 54 | -------------------------------------------------------------------------------- /strategy.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include 17 | 18 | // Select analysis type whether it will cover paring prcess or profile. 19 | int strategy() 20 | { 21 | int type = 0; 22 | 23 | while(true) 24 | { 25 | printf(" Vulnerability Testing Menus\n"); 26 | printf(" [1] Pairing process vuln.\n [2] Profile vuln. \n"); 27 | printf(" Please select fuction to test : "); 28 | scanf(" %d", &type); 29 | if(type == 1 || type == 2) 30 | { 31 | break; 32 | } 33 | else 34 | { 35 | printf("[-] Invalid input. please try again.\n"); 36 | } 37 | } 38 | 39 | return type; 40 | } 41 | -------------------------------------------------------------------------------- /global.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __GLOBAL_H__ 17 | #define __GLOBAL_H__ 18 | 19 | #include 20 | #include 21 | 22 | #include "bProfile.h" 23 | #include "devscan.h" 24 | 25 | using namespace std; 26 | 27 | /* options in Fuzzer class */ 28 | #define DEFAULT_SLEEP_MS 0 29 | #define DEFAULT_ITERATION 1000000 30 | 31 | #define PAYLOAD_SIZE 4096 // iGenerator, Database too 32 | 33 | 34 | /* option is Database class */ 35 | #define SZ_DBNAME "data.db" 36 | 37 | //extern vector profiles; 38 | extern vector devices; 39 | extern vector hcidevs; 40 | 41 | extern bdaddr_t snf_bdr; 42 | extern bdaddr_t inq_bdr; 43 | extern bdaddr_t m_bdr; 44 | extern bdaddr_t s_bdr; 45 | 46 | extern FILE* fi; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /bProtocol.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | 17 | #ifndef __BTPROTOCOL_H__ 18 | #define __BTPROTOCOL_H__ 19 | 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | //#include "bProfile.h" 27 | 28 | using namespace std; 29 | 30 | 31 | class bProtocol 32 | { 33 | public: 34 | bProtocol(); 35 | virtual ~bProtocol(); 36 | bProtocol(const bProtocol &b); 37 | 38 | virtual bProtocol* Clone(); 39 | virtual int connect(); 40 | virtual int free(); 41 | virtual int send(char* s, int size); 42 | virtual int recv(char *s, int size); 43 | virtual int reconnect(); 44 | 45 | string name; 46 | int psm; 47 | int channel; 48 | int uint8; 49 | int uint16; 50 | int version; 51 | uuid_t uuid; 52 | 53 | void *pProfile; 54 | 55 | private: 56 | }; 57 | 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /bProfile.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include 17 | 18 | 19 | #include "bProfile.h" 20 | #include "bProtocol.h" 21 | 22 | 23 | 24 | using namespace std; 25 | 26 | 27 | //vector profiles; 28 | 29 | bProfile::bProfile() 30 | :code(0), version(0), szbtaddr(NULL) 31 | { 32 | memset(&(this->uuid), 0, sizeof(uuid_t)); 33 | } 34 | 35 | bProfile::~bProfile() 36 | { 37 | for (int i = 0; i < protocols.size(); i++) 38 | delete protocols[i]; 39 | } 40 | 41 | bProfile::bProfile(const bProfile &b) 42 | :name(b.name) 43 | { 44 | code = b.code; 45 | version = b.version; 46 | memcpy(&uuid, &b.uuid, sizeof(uuid_t)); 47 | for (int i = 0; i < b.protocols.size(); i++) 48 | { 49 | protocols.push_back(b.protocols[i]->Clone()); 50 | protocols[i]->pProfile = this; 51 | } 52 | 53 | szbtaddr = b.szbtaddr; 54 | } 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /prtRFCOMM.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __PRTRFCOMM_H__ 17 | #define __PRTRFCOMM_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bProtocol.h" 25 | #include "bProfile.h" 26 | #include "global.h" 27 | 28 | class prtRFCOMM : public bProtocol 29 | { 30 | public: 31 | prtRFCOMM(); 32 | prtRFCOMM(bProtocol &p); 33 | prtRFCOMM(prtRFCOMM &p); 34 | ~prtRFCOMM(); 35 | 36 | virtual int connect(); 37 | virtual int free(); 38 | virtual int send(char *s, int size); 39 | virtual int recv(char *s, int size); 40 | virtual int reconnect(); 41 | virtual bProtocol* Clone(); 42 | 43 | int sock; 44 | int state; 45 | struct sockaddr_rc addr_rc; 46 | struct sockaddr_l2 addr_l2; 47 | 48 | private: 49 | 50 | void choose_state(); 51 | 52 | }; 53 | 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /prtL2CAP.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __PRTL2CAP_H__ 17 | #define __PRTL2CAP_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bProfile.h" 25 | #include "bProtocol.h" 26 | #include "global.h" 27 | 28 | class prtL2CAP : public bProtocol 29 | { 30 | public: 31 | prtL2CAP(); 32 | prtL2CAP(const bProtocol &p); 33 | prtL2CAP(const prtL2CAP &p); 34 | ~prtL2CAP(); 35 | 36 | virtual int connect(); 37 | virtual int free(); 38 | virtual int send(char *s, int size); 39 | virtual int recv(char *s, int size); 40 | virtual int reconnect(); 41 | virtual bProtocol* Clone(); 42 | 43 | int sock; 44 | 45 | /* 46 | int connect1(); 47 | int free1(); 48 | int send1(char *s, int size); 49 | */ 50 | int sock1; 51 | int state; 52 | struct sockaddr_l2 addr; 53 | 54 | private: 55 | void choose_state(); 56 | }; 57 | 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Fuzzer.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __FUZZER_H__ 17 | #define __FUZZER_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "bProtocol.h" 24 | #include "bProfile.h" 25 | #include "iGenerator.h" 26 | #include "global.h" 27 | 28 | 29 | 30 | int _print_orgpayload(char* payld, int size); 31 | int _fprint_payld(char* payld, int size, int chk); 32 | 33 | class Fuzzer 34 | { 35 | public: 36 | //Fuzzer(); 37 | Fuzzer(bProtocol *p); 38 | ~Fuzzer(); 39 | //int set_protocol(bProtocol &p); 40 | int fuzz(); 41 | 42 | bProtocol *p; 43 | iGenerator igen; 44 | char prev_payload[PAYLOAD_SIZE]; 45 | int prev_size; 46 | 47 | /* fuzzing options */ 48 | int opt_sleep_ms; 49 | int opt_iteration; 50 | 51 | private: 52 | int set_default_opt(); 53 | int sleep_ms(); 54 | int set_timespec(); 55 | 56 | int print_start(); 57 | int print_end(); 58 | int print_payload(char* p, int s); 59 | void getTime(); 60 | 61 | struct timespec ts; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /devscan.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | #include 16 | #include "devscan.h" 17 | #include "sdpscan.h" 18 | #include "global.h" 19 | 20 | using namespace std; 21 | 22 | //bdaddr_t master; 23 | //bdaddr_t slave; 24 | 25 | //contains scanned device info. 26 | //vector devices; 27 | 28 | void finddev() 29 | { 30 | FILE *in; 31 | char buff[512]; 32 | 33 | 34 | if(!(in = popen("hcitool scan", "r"))) 35 | { 36 | printf("[-] Bluetooth scanning failed. \n"); 37 | return; 38 | } 39 | 40 | while(fgets(buff, sizeof(buff), in) != NULL){ 41 | if (strncmp(buff, "Scan", 3) != 0){ 42 | char tmpaddr[100]; 43 | char tmpname[100]; 44 | devices.push_back(devscan()); 45 | strncpy(tmpaddr, &buff[1], 17); 46 | tmpaddr[17] = 0; 47 | strncpy(tmpname, &buff[19], sizeof(tmpname)); 48 | if (tmpname[strlen(tmpname) - 1] == '\n') 49 | tmpname[strlen(tmpname) - 1] = 0; 50 | devices.back().name = tmpname; 51 | devices.back().bt_addr = tmpaddr; 52 | } 53 | } 54 | 55 | pclose(in); 56 | return; 57 | } 58 | 59 | devscan::devscan() 60 | :name("n/a"), bt_addr("00:00:00:00:00:00") 61 | { 62 | } 63 | 64 | devscan::~devscan() 65 | { 66 | } 67 | -------------------------------------------------------------------------------- /bProtocol.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | #include 16 | #include "bProtocol.h" 17 | 18 | using namespace std; 19 | 20 | bProtocol::bProtocol() 21 | :psm(0), channel(0), uint8(0), uint16(0), version(0), pProfile(NULL) 22 | { 23 | memset(&(this->uuid), 0, sizeof(uuid_t)); 24 | } 25 | 26 | bProtocol::~bProtocol() 27 | { 28 | 29 | } 30 | 31 | bProtocol::bProtocol(const bProtocol &b) 32 | :name(b.name) 33 | { 34 | psm = b.psm; 35 | channel = b.channel; 36 | uint8 = b.uint8; 37 | uint16 = b.uint16; 38 | version = b.version; 39 | memcpy(&uuid, &b.uuid, sizeof(uuid_t)); 40 | pProfile = NULL; 41 | } 42 | 43 | bProtocol* bProtocol::Clone() 44 | { 45 | return new bProtocol(*this); 46 | } 47 | 48 | 49 | int bProtocol::connect() 50 | { 51 | printf("connect() in bProtocol\n"); 52 | return 0; 53 | } 54 | 55 | int bProtocol::free() 56 | { 57 | printf("free() in bProtocol\n"); 58 | return 0; 59 | } 60 | 61 | int bProtocol::send(char *s, int size) 62 | { 63 | printf("send() in bProtocol\n"); 64 | return 0; 65 | } 66 | 67 | int bProtocol::recv(char *s, int size) 68 | { 69 | printf("recv() in bProtocol\n"); 70 | return 0; 71 | } 72 | 73 | int bProtocol::reconnect() 74 | { 75 | printf("check() in bProtocol\n"); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /prtSDP.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __PRTSDP_H__ 17 | #define __PRTSDP_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "bProfile.h" 27 | #include "bProtocol.h" 28 | #include "global.h" 29 | 30 | class prtSDP : public bProtocol 31 | { 32 | public: 33 | prtSDP(); 34 | prtSDP(const bProtocol &p); 35 | prtSDP(const prtSDP &p); 36 | ~prtSDP(); 37 | 38 | virtual int connect(); 39 | virtual int free(); 40 | virtual int send(char *s, int size); 41 | virtual int recv(char *s, int size); 42 | virtual int reconnect(); 43 | virtual bProtocol* Clone(); 44 | 45 | int sock; 46 | int state; 47 | uint16_t trans; 48 | struct sockaddr_l2 addr_l2; 49 | 50 | private: 51 | int _connect_l2cap(); 52 | void choose_state(); 53 | 54 | }; 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | /* sdp connection definition 61 | * pdu(protocol data units) contains 62 | * the basic requests and responses 63 | * needed to implement the functionality of 64 | * Bluetooth Service Discovery. 65 | */ 66 | typedef struct { 67 | uint32_t conID; 68 | uint8_t sdpCommand; 69 | uint8_t pduPayload[256]; 70 | int pduLength; 71 | uint8_t requestResponse[256]; 72 | int responseLength; 73 | } __attribute__ ((packed)) bt_sdp_request; 74 | 75 | typedef struct { 76 | uint8_t pdu_id; 77 | uint16_t transaction_id; 78 | uint16_t len; 79 | } __attribute__ ((packed)) sdp_searchattr_req; 80 | #define SEARCH_ATTR_REQ_HDR_SIZE 5 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | #endif 86 | -------------------------------------------------------------------------------- /prtOBEX.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #ifndef __PRTOBEX_H__ 17 | #define __PRTOBEX_H__ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "bProfile.h" 26 | #include "bProtocol.h" 27 | #include "global.h" 28 | 29 | class prtOBEX : public bProtocol 30 | { 31 | public: 32 | prtOBEX(); 33 | prtOBEX(const bProtocol &p); 34 | prtOBEX(const prtOBEX &p); 35 | ~prtOBEX(); 36 | 37 | virtual int connect(); 38 | virtual int free(); 39 | virtual int send(char *s, int size); 40 | virtual int recv(char *s, int size); 41 | virtual int reconnect(); 42 | virtual bProtocol* Clone(); 43 | 44 | int sock; 45 | int put_cnt; 46 | int connection_id; 47 | struct sockaddr_l2 addr_l2; 48 | struct sockaddr_rc addr_rc; 49 | 50 | private: 51 | int _connect_l2cap(); 52 | int _connect_rfcomm(); 53 | 54 | }; 55 | 56 | 57 | #define OBEX_OP_FINAL 0X80 58 | 59 | #define OBEX_OP_CONNECT 0x00 60 | #define OBEX_OP_PUT 0X02 61 | #define OBEX_OP_CONTINUE 0x10 62 | #define OBEX_OP_SUCCESS 0X20 63 | 64 | #define OBEX_HDR_NAME 0x01 65 | #define OBEX_HDR_BODY 0x48 66 | #define OBEX_HDR_LENGTH 0xC3 67 | #define OBEX_HDR_CONNECTIONID 0xCB 68 | #define OBEX_HDR_ENDOFBODY 0x49 69 | 70 | #ifdef __cplusplus 71 | extern "C" { 72 | #endif 73 | 74 | #pragma pack(push, 1) 75 | 76 | typedef struct { 77 | uint8_t opcode; 78 | uint16_t len; 79 | } __attribute__ ((packed)) obex_hdr; 80 | #define OBEX_HDR_SIZE 3 81 | 82 | typedef struct { 83 | uint8_t version; 84 | uint8_t flags; 85 | uint16_t maxlen; 86 | } __attribute__ ((packed)) obex_hdr_connect; 87 | #define OBEX_HDR_CONNECT_SIZE 4 88 | 89 | typedef struct { 90 | uint8_t opcode; 91 | uint16_t len; 92 | uint8_t version; 93 | uint8_t flags; 94 | uint16_t maxlen; 95 | } __attribute__ ((packed)) obex_connect; 96 | 97 | #pragma pack(pop) 98 | 99 | typedef struct { 100 | uint8_t opcode; 101 | uint16_t len; 102 | uint8_t connection_id_hdr; 103 | uint32_t connection_id; 104 | uint8_t name_hdr; 105 | uint16_t name_len; 106 | uint16_t name[5]; 107 | uint8_t len_hdr; 108 | uint32_t file_len; 109 | uint8_t bdy_hdr; 110 | uint16_t bdy_hdr_len; 111 | } __attribute__ ((packed)) obex_hdr_put; 112 | #define OBEX_HDR_PUT_SIZE 29 113 | 114 | typedef struct { 115 | uint8_t opcode; 116 | uint16_t len; 117 | uint8_t bdy_hdr; 118 | uint16_t bdy_hdr_len; 119 | } __attribute__ ((packed)) obex_hdr_put_cont; 120 | 121 | #ifdef __cplusplus 122 | } 123 | 124 | #endif 125 | 126 | #endif 127 | 128 | -------------------------------------------------------------------------------- /iGenerator.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | 17 | #ifndef __IGENERATOR_H__ 18 | #define __IGENERATOR_H__ 19 | 20 | #include // for () 21 | #include // for open() 22 | #include 23 | #include // for box-muller transform 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "Database.h" 31 | #include "global.h" 32 | 33 | class iGenerator 34 | { 35 | public: 36 | iGenerator(); 37 | ~iGenerator(); 38 | 39 | int getInput(uuid_t uuid, char *mut_payld, int *mut_size); 40 | int getRand(void *dst, int size); 41 | 42 | int cnt; 43 | 44 | private: 45 | int mutate0(char *payld, int size, void *opt); 46 | int genRandInput(char *payld, int size); 47 | double genGaussianNoise(double mu, double sigma); 48 | 49 | Database db; 50 | }; 51 | 52 | 53 | 54 | /* Default packet information */ 55 | 56 | #define PKT_L2C "\x01\x01\x12\x00" 57 | #define PKT_RFC "\x63\xef\x20\x04\x02\x02\x10\xcb\x00\x00\x00\x01\x01\x00\x0b\x00\x6f\x00\x75\x00\x74\x00\x00\xc3\x00\x00\x01\xf5\x48\x01\xf8\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x0a\x0e" 58 | #define PKT_OBEX "\x64\x6e\x67\x74\x68\x65\x39\x33\x0a" 59 | #define PKT_SDP "" 60 | #define PKT_AVC "" 61 | #define PKT_AVD "" 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Database.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Database.h" 3 | 4 | 5 | Database::Database() 6 | :db(NULL) 7 | { 8 | } 9 | 10 | Database::~Database() 11 | { 12 | } 13 | 14 | int Database::open() 15 | { 16 | return this->open(SZ_DBNAME); 17 | } 18 | 19 | int Database::open(const char *dbname) 20 | { 21 | int ret; 22 | 23 | ret = sqlite3_open(dbname, &db); 24 | if (ret) 25 | { 26 | fprintf(stderr, "[-] Database::open(), sqlite3_open() failed\n"); 27 | sqlite3_close(db); 28 | return -1; 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | int Database::close() 35 | { 36 | if (db) 37 | { 38 | sqlite3_close(db); 39 | db = NULL; 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | static int _atoi(char *a) 46 | { 47 | int ret = 0; 48 | while (*a) 49 | ret = (ret * 10) + (*(a++) - '0'); 50 | return ret; 51 | } 52 | 53 | static int _callback1(void *n, int argc, char **argv, char **azColName) 54 | { 55 | int *c = (int*)n; 56 | 57 | if (argc < 1) 58 | { 59 | fprintf(stderr, "[-] Database _callback1(), argc is less than 1\n"); 60 | return -1; 61 | } 62 | 63 | /* atoi */ 64 | /* 65 | *n = 0; 66 | for (int i = 0; argv[0][i]; i++) 67 | *n = (*n * 10) + (argv[0][i] - '0'); 68 | */ 69 | *c = _atoi(argv[0]); 70 | 71 | return 0; 72 | } 73 | 74 | #pragma pack(push, 1) 75 | struct opt 76 | { 77 | char* p; 78 | int* s; 79 | int* i; 80 | }; 81 | #pragma pack(pop) 82 | 83 | static int _callback2(void *n, int argc, char **argv, char **azColName) 84 | { 85 | struct opt *parg = (struct opt*)n; 86 | 87 | if (argc != 3) 88 | { 89 | fprintf(stderr, "[-] Database _callback2(), argc is not three\n"); 90 | return -1; 91 | } 92 | 93 | /* get size and do boundary check */ 94 | *(parg->s) = _atoi(argv[1]); 95 | if (*(parg->s) > PAYLOAD_SIZE) 96 | { 97 | fprintf(stderr, "[-] Database _callback2(), size(%d) is greater than %d\n", *(parg->s), PAYLOAD_SIZE); 98 | return -2; 99 | } 100 | 101 | /* get id */ 102 | *(parg->i) = _atoi(argv[0]); 103 | 104 | /* get data */ 105 | memcpy(parg->p, argv[2], *(parg->s)); 106 | 107 | return 0; 108 | } 109 | 110 | int Database::get_packet(int proto, int state, int random, char *packet, int *size) 111 | { 112 | int ret; 113 | char *err = NULL; 114 | 115 | if (!db) 116 | { 117 | fprintf(stderr, "[-] Database::get_packet(), database does not opened\n"); 118 | fprintf(stderr, " %s\n", sqlite3_errmsg(db)); 119 | return -1; 120 | } 121 | 122 | int count = 0; 123 | char query[1024]; 124 | sprintf(query, QUERY_COUNT, proto/*, state*/); 125 | ret = sqlite3_exec(db, query, _callback1, &count, &err); 126 | if (ret != SQLITE_OK) 127 | { 128 | if (ret == SQLITE_ABORT) 129 | { 130 | sqlite3_free(err); 131 | return 0; // no result -> return id zero 132 | } 133 | fprintf(stderr, "[-] Database::get_packet(), exec1 failed\n"); 134 | fprintf(stderr, " %s\n", err); 135 | sqlite3_free(err); 136 | return -1; 137 | } 138 | 139 | if (count < 1) 140 | { 141 | //fprintf(stderr, "[-] Database::get_packet(%d, %d), cannot find packet\n", proto, state); 142 | return -2; 143 | } 144 | random = (random % count) + 1; 145 | 146 | int id = 0; 147 | struct opt arg = { packet, size, &id }; 148 | sprintf(query, QUERY_GET, proto, random); 149 | ret = sqlite3_exec(db, query, _callback2, &arg, &err); 150 | if (ret != SQLITE_OK) 151 | { 152 | fprintf(stderr, "[-] Database::get_packet(%d, %d), _callback2 failed\n", proto, state); 153 | fprintf(stderr, " %s\n", err); 154 | sqlite3_free(err); 155 | return -3; 156 | } 157 | 158 | return id; 159 | } 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /prtSDP.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "prtSDP.h" 17 | #include 18 | 19 | extern FILE *fi; 20 | 21 | prtSDP::prtSDP() 22 | :sock(0), trans(0), state(0) 23 | { 24 | } 25 | 26 | prtSDP::prtSDP(const bProtocol &p) 27 | :bProtocol(p), sock(0), trans(0), state(0) 28 | { 29 | } 30 | 31 | prtSDP::prtSDP(const prtSDP &p) 32 | :bProtocol((bProtocol&)p) 33 | { 34 | sock = p.sock; 35 | } 36 | 37 | prtSDP::~prtSDP() 38 | { 39 | this->free(); 40 | } 41 | 42 | bProtocol* prtSDP::Clone() 43 | { 44 | return new prtSDP(*this); 45 | } 46 | 47 | int prtSDP::connect() 48 | { 49 | int ret; 50 | ret = _connect_l2cap(); 51 | 52 | if (ret) 53 | return ret; 54 | 55 | char packet[1024]; 56 | //sleep(100); 57 | 58 | // will use bt_sdp_request in prtSDP.h 59 | 60 | /*bdaddr_t add_any = {0,0,0,0,0,0}; 61 | 62 | bdaddr_t target; 63 | 64 | uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65 | 0, 0, 0xab, 0xcd }; 66 | uuid_t svc_uuid; 67 | int err; 68 | sdp_list_t *response_list = NULL, *search_list, *attrid_list; 69 | sdp_session_t *session = 0; 70 | 71 | // convert szbtaddr to bdaddr_t 72 | str2ba( ((bProfile*)(this->pProfile))->szbtaddr, &target ); 73 | 74 | // connect to the SDP server running on the remote machine 75 | session = sdp_connect( &add_any, &target, SDP_RETRY_IF_BUSY ); 76 | if (!session) 77 | { 78 | printf("[-] error : sdp_connect() failed\n"); 79 | return -1; 80 | }*/ 81 | } 82 | 83 | // SDP is based on L2CAP. 84 | int prtSDP::_connect_l2cap() 85 | { 86 | sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 87 | if (sock < 0) 88 | { 89 | printf("[-] prtSDP::_connect_l2cap, socket() failed\n"); 90 | return -1; 91 | } 92 | 93 | memset(&addr_l2, 0, sizeof(addr_l2)); 94 | addr_l2.l2_family = AF_BLUETOOTH; 95 | addr_l2.l2_psm = htobs(SDP_PSM); 96 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr_l2.l2_bdaddr); 97 | if (::connect(sock, (struct sockaddr*)&addr_l2, sizeof(addr_l2)) < 0) 98 | { 99 | printf("[-] prtSDP::_connect_l2cap, connect() failed\n"); 100 | printf("[-] %s\n", strerror(errno)); 101 | close(sock); 102 | sock = 0; 103 | return -1; 104 | } 105 | 106 | return 0; 107 | } 108 | 109 | int prtSDP::free() 110 | { 111 | if (sock) 112 | close(sock); 113 | sock = 0; 114 | return 0; 115 | } 116 | 117 | void prtSDP::choose_state(){ 118 | printf("You can choose state which want to fuzz.\n"); 119 | printf("(If you want to stop fuzzing, Press Ctrl + C.)\n"); 120 | printf("=================SDP State===============\n"); 121 | printf("(0) -> Service Search -> (1)\n"); 122 | printf("(0) -> Attribute Search -> (2)\n"); 123 | printf("(0) -> Service Attribute Search -> (3)\n"); 124 | printf("=========================================\n\n"); 125 | 126 | do{ 127 | printf("Select State(1,2,3,exit : -1) : "); 128 | scanf("%d",&state); 129 | if(state==-1) exit(0); 130 | }while(state<1 || state>3); 131 | fprintf(fi,"0\n%d\n",state); 132 | } 133 | 134 | char sdp_packet[65536]; 135 | int prtSDP::send(char *s, int size) 136 | { 137 | if(!sock) 138 | return -1; 139 | 140 | //memset(packet,0,sizeof(packet)); 141 | if(!state) choose_state(); 142 | sdp_searchattr_req *req_hdr = (sdp_searchattr_req*)sdp_packet; 143 | switch(state){ 144 | case 2 : req_hdr->pdu_id=SDP_SVC_SEARCH_REQ; break; 145 | case 3 : req_hdr->pdu_id=SDP_SVC_ATTR_REQ; break; 146 | case 4 : req_hdr->pdu_id=SDP_SVC_SEARCH_ATTR_REQ; break; 147 | } 148 | req_hdr->transaction_id=bswap_16(trans++); 149 | req_hdr->len=bswap_16(size+1); 150 | memcpy(sdp_packet+SEARCH_ATTR_REQ_HDR_SIZE,s,size); 151 | sdp_packet[SEARCH_ATTR_REQ_HDR_SIZE+size]=0x00; 152 | //fprintf(fi,"PDU(1 byte) | Transaction id(2 bytes) | Length(2 bytes) | Packet |"); 153 | fprintf(fi,"send|"); 154 | 155 | return write(sock, sdp_packet, size+SEARCH_ATTR_REQ_HDR_SIZE+1); 156 | 157 | } 158 | 159 | int prtSDP::recv(char *s, int size) 160 | { 161 | if (!sock) 162 | return -1; 163 | return ::recv(sock, s, size, 0); 164 | } 165 | 166 | int prtSDP::reconnect() 167 | { 168 | this->free(); 169 | return this->connect(); 170 | } 171 | 172 | -------------------------------------------------------------------------------- /prtRFCOMM.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "prtRFCOMM.h" 17 | 18 | extern FILE *fi; 19 | 20 | prtRFCOMM::prtRFCOMM() 21 | :sock(0), state(0) 22 | { 23 | } 24 | 25 | prtRFCOMM::prtRFCOMM(bProtocol &p) 26 | :bProtocol(p), sock(0), state(0) 27 | { 28 | } 29 | 30 | prtRFCOMM::prtRFCOMM(prtRFCOMM &p) 31 | :bProtocol((bProtocol&)p) 32 | { 33 | sock = p.sock; 34 | } 35 | 36 | prtRFCOMM::~prtRFCOMM() 37 | { 38 | this->free(); 39 | } 40 | 41 | bProtocol* prtRFCOMM::Clone() 42 | { 43 | return new prtRFCOMM(*this); 44 | } 45 | 46 | int prtRFCOMM::connect() 47 | { 48 | /* 49 | sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 50 | if (sock < 0) 51 | { 52 | printf("[-] prtRFCOMM::connect, socket() failed\n"); 53 | sock = 0; 54 | return -1; 55 | } 56 | 57 | memset(&addr, 0, sizeof(addr)); 58 | addr.rc_family = AF_BLUETOOTH; 59 | addr.rc_channel = (uint8_t)this->channel; 60 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr.rc_bdaddr); 61 | 62 | int ret; 63 | if ((ret = ::connect(sock, (struct sockaddr*)&addr, sizeof(addr)))) 64 | { 65 | printf("[-] prtRFCOMM::connect, connect() failed\n"); 66 | close(sock); 67 | sock = 0; 68 | return -1; 69 | } 70 | */ 71 | sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 72 | //sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP); 73 | if (sock < 0) 74 | { 75 | printf("[-] prtRFCOMM::connect, socket() failed\n"); 76 | return -1; 77 | } 78 | 79 | memset(&addr_l2, 0, sizeof(addr_l2)); 80 | addr_l2.l2_family = AF_BLUETOOTH; 81 | addr_l2.l2_psm = htobs(RFCOMM_PSM); 82 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr_l2.l2_bdaddr); 83 | if (::connect(sock, (struct sockaddr*)&addr_l2, sizeof(addr_l2)) < 0) 84 | { 85 | printf("[-] prtRFCOMM::connect, connect() failed\n"); 86 | close(sock); 87 | sock = 0; 88 | return -1; 89 | } 90 | 91 | return 0; 92 | } 93 | int prtRFCOMM::free() 94 | { 95 | if (sock) 96 | { 97 | close(sock); 98 | sock = 0; 99 | } 100 | return 0; 101 | } 102 | 103 | uint8_t rfcomm_packet[5][14]={ 104 | {0x03, 0x3f, 0x01, 0x1c}, 105 | {0x03, 0xef, 0x15, 0x83, 0x11, 0x18, 0xf0, 0x07, 0x00, 0xf0, 0x03, 0x00, 0x07, 0x70}, 106 | {0x63, 0x3f, 0x01, 0xa2}, 107 | {0x03, 0xef, 0x09, 0xe3, 0x05, 0x63}, 108 | {0x63, 0xff, 0x01, 0x21, 0x12} 109 | }; 110 | 111 | void prtRFCOMM::choose_state(){ 112 | printf("You can choose state which want to fuzz.\n"); 113 | printf("(If you want to stop fuzzing, Press Ctrl + C.)\n"); 114 | printf("================RFCOMM State===============\n"); 115 | printf("(1) -> SABM -> (2)\n"); 116 | printf("(2) -> PN(Negotitation) -> (3)\n"); 117 | printf("(3) -> SABM Channel -> (4)\n"); 118 | printf("(4) -> MSC -> (5)\n"); 119 | printf("(5) -> UID Channel -> (6)\n"); 120 | printf("===========================================\n\n"); 121 | do{ 122 | printf("Select State(1,2,3,4,5,6,exit : -1) : "); 123 | scanf("%d",&state); 124 | if(state==-1) exit(0); 125 | }while(state<1 && state>6); 126 | 127 | int i,j; 128 | int size[5]={4,14,4,6,5}; 129 | char rpack[30]={0}; 130 | 131 | fprintf(fi,"%d\n",state-1); 132 | for(i=1;ifree(); 186 | return this->connect(); 187 | } 188 | -------------------------------------------------------------------------------- /prtL2CAP.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "prtL2CAP.h" 17 | 18 | extern FILE *fi; 19 | 20 | prtL2CAP::prtL2CAP() 21 | :sock(0), sock1(0), state(0) 22 | { 23 | } 24 | 25 | prtL2CAP::prtL2CAP(const bProtocol &p) 26 | :bProtocol(p), sock(0), sock1(0), state(0) 27 | { 28 | } 29 | 30 | prtL2CAP::~prtL2CAP() 31 | { 32 | this->free(); 33 | //this->free1(); 34 | } 35 | 36 | prtL2CAP::prtL2CAP(const prtL2CAP &p) 37 | :bProtocol((const bProtocol&)p) 38 | { 39 | sock = p.sock; 40 | sock1 = p.sock1; 41 | memcpy(&addr, &p.addr, sizeof(sockaddr_l2)); 42 | } 43 | 44 | bProtocol* prtL2CAP::Clone() 45 | { 46 | return new prtL2CAP(*this); 47 | } 48 | 49 | /* 50 | int prtL2CAP::connect() 51 | { 52 | return 0; 53 | } 54 | int prtL2CAP::free() 55 | { 56 | return 0; 57 | } 58 | int prtL2CAP::send(char *s, int size) 59 | { 60 | return 0; 61 | } 62 | */ 63 | 64 | int prtL2CAP::connect() 65 | { 66 | 67 | sock1 = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP); 68 | if (sock1 < 0) 69 | { 70 | printf("[-] prtL2CAP::connect1, socket() failed\n"); 71 | return -1; 72 | } 73 | memset(&addr, 0, sizeof(addr)); 74 | addr.l2_family = AF_BLUETOOTH; 75 | 76 | 77 | if (bind(sock1, (struct sockaddr*)&addr, sizeof(addr)) < 0) 78 | { 79 | printf("[-] prtL2CAP:connect1, bind() failed\n"); 80 | close(sock1); 81 | sock1 = 0; 82 | return -1; 83 | } 84 | 85 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr.l2_bdaddr); 86 | 87 | if (::connect(sock1, (struct sockaddr*)&addr, sizeof(addr)) < 0) 88 | { 89 | printf("[-] prtL2CAP::connect1, connect() failed\n"); 90 | close(sock1); 91 | sock1 = 0; 92 | return -1; 93 | } 94 | 95 | return 0; 96 | } 97 | int prtL2CAP::free() 98 | { 99 | if (sock1) 100 | close(sock1); 101 | sock1 = 0; 102 | return 0; 103 | } 104 | 105 | uint8_t l2cap_info_packet[2][16]={ 106 | {0x0a, 0x02, 0x02, 0x00, 0x03, 0x00}, 107 | {0x0b, 0x03, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 108 | }; 109 | 110 | uint8_t l2cap_packet[3][19]={ 111 | {0x02, 0x04, 0x04, 0x00, 0x01, 0x00, 0x40, 0x00}, 112 | {0x04, 0x05, 0x0f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 113 | {0x05, 0x05, 0x0a, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x9b, 0x06} 114 | }; 115 | 116 | void prtL2CAP::choose_state(){ 117 | printf("You can choose state which want to fuzz.\n"); 118 | printf("(If you want to stop fuzzing, Press Ctrl + C.)\n"); 119 | printf("=================L2CAP State===============\n"); 120 | printf("(1) -> Connect_Request -> (2)\n"); 121 | printf("(2) -> Configure_Request -> (3)\n"); 122 | printf("(3) -> Configure_Response -> (4)\n"); 123 | printf("===========================================\n\n"); 124 | 125 | do{ 126 | printf("Select State(1,2,3,4,exit : -1) : "); 127 | scanf("%d",&state); 128 | if(state==-1) exit(0); 129 | }while(state<1 || state>4); 130 | 131 | int i,j; 132 | int size[3]={8,19,14}; 133 | int info_size[2]={6,16}; 134 | char rpack[30]={0}; 135 | 136 | /*for(i=0;i<2;i++){ 137 | write(sock1,l2cap_info_packet[i],info_size[i]); 138 | read(sock,rpack,30); 139 | }*/ 140 | 141 | fprintf(fi,"%d\n",state-1); 142 | for(i=1;icode = 1; 175 | cmd->ident = (id++%255) + 1; 176 | cmd->len = __cpu_to_le16(size + L2CAP_CMD_HDR_SIZE); 177 | 178 | int ret = ::send(sock1, buf, size + L2CAP_CMD_HDR_SIZE, 0); 179 | delete[] buf; 180 | return ret; 181 | */ 182 | 183 | if(!state) choose_state(); 184 | 185 | //fprintf(fi,"Connection Request(1byte) | Identifier(1byte) | Length(2bytes) | Packet |\n"); 186 | fprintf(fi,"send|"); 187 | return ::send(sock1, s, size, 0); 188 | } 189 | 190 | int prtL2CAP::recv(char *s, int size) 191 | { 192 | if (!sock) 193 | return -1; 194 | return ::recv(sock, s, size, 0); 195 | } 196 | 197 | int prtL2CAP::reconnect() 198 | { 199 | this->free(); 200 | return this->connect(); 201 | } 202 | -------------------------------------------------------------------------------- /Fuzzer.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "Fuzzer.h" 17 | 18 | Fuzzer::Fuzzer(bProtocol *p) 19 | { 20 | this->p = p; 21 | this->set_default_opt(); 22 | } 23 | 24 | Fuzzer::~Fuzzer() 25 | { 26 | } 27 | 28 | int Fuzzer::set_default_opt() 29 | { 30 | /* default option values are defined in global.h */ 31 | opt_sleep_ms = DEFAULT_SLEEP_MS; 32 | opt_iteration = DEFAULT_ITERATION; 33 | } 34 | 35 | void Fuzzer::getTime(){ 36 | struct timeval val; 37 | struct tm *ptm; 38 | 39 | gettimeofday(&val, NULL); 40 | ptm = localtime(&val.tv_sec); 41 | 42 | fprintf(fi, "%04d-%02d-%02d %02d:%02d:%02d.%06ld" 43 | ,ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday 44 | ,ptm->tm_hour,ptm->tm_min,ptm->tm_sec 45 | ,val.tv_usec); 46 | } 47 | 48 | struct sigaction old_action; 49 | 50 | void sigint_handler(int sig_no) 51 | { 52 | printf("\n\n***CTRL-C pressed, Fuzzing Module Stop***\n"); 53 | 54 | struct timeval val; 55 | struct tm *ptm; 56 | 57 | FILE *fo=fopen("log.wfl","a"); 58 | 59 | gettimeofday(&val, NULL); 60 | ptm = localtime(&val.tv_sec); 61 | 62 | fprintf(fo, "\n%04d-%02d-%02d %02d:%02d:%02d.%06ld" 63 | ,ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday 64 | ,ptm->tm_hour,ptm->tm_min,ptm->tm_sec 65 | ,val.tv_usec); 66 | 67 | fclose(fo); 68 | 69 | sigaction(SIGINT, &old_action, NULL); 70 | kill(0, SIGINT); 71 | } 72 | 73 | int Fuzzer::fuzz() 74 | { 75 | char payload[PAYLOAD_SIZE],rpayload[PAYLOAD_SIZE]; 76 | char org_payld[PAYLOAD_SIZE]; 77 | int payld_size, rpayload_size, orgpayld_size; 78 | int ch=0, j, cmp_size; 79 | fi=fopen("log.wfl","a"); 80 | 81 | struct sigaction action; 82 | memset(&action, 0, sizeof(action)); 83 | action.sa_handler = &sigint_handler; 84 | sigaction(SIGINT, &action, &old_action); 85 | 86 | print_start(); 87 | 88 | if (opt_sleep_ms) 89 | set_timespec(); 90 | 91 | if (p->connect()) 92 | { 93 | print_end(); 94 | return -1; 95 | } 96 | 97 | printf("# of tested inputs : \n"); 98 | 99 | for (int i = 0; i < opt_iteration; i++) 100 | { 101 | ch=0; 102 | if((int)(i%1000) == 999) 103 | printf("# of Packet Sent : %d \n", i+1); 104 | 105 | igen.getInput(p->uuid, payload, &payld_size); 106 | //printf("payload: \n"); 107 | 108 | if (!i){ 109 | _print_orgpayload(payload, payld_size); 110 | 111 | for(j=0;jname.c_str()); 118 | getTime(); 119 | fprintf(fi,"\n"); 120 | } 121 | 122 | //if (p->send(payload, payld_size) <= 0 123 | ch=p->send(payload, payld_size); 124 | if(ch<=0){ 125 | //if(p->reconnect()){ 126 | /* show previous payload */ 127 | printf("\n[-] **SENDING FAILED**\n"); 128 | print_payload(prev_payload, prev_size); 129 | _fprint_payld(payload,payld_size,1); 130 | 131 | /*fprintf(fi,"Compare with original packet\n"); 132 | if(payld_size>orgpayld_size) cmp_size=orgpayld_size; 133 | else cmp_size=payld_size; 134 | for(j=0;jrecv(rpayload,rpayload_size); 152 | //if(ch<=0) printf("failed\n"); 153 | } 154 | 155 | 156 | memcpy(prev_payload, payload, payld_size); 157 | prev_size = payld_size; 158 | 159 | if (opt_sleep_ms) 160 | sleep_ms(); 161 | } 162 | getTime(); 163 | printf("\n"); 164 | p->free(); 165 | print_end(); 166 | fclose(fi); 167 | return 0; 168 | } 169 | 170 | int _fprint_payld(char* payld, int size,int chk) 171 | { 172 | if (!fi) 173 | { 174 | fprintf(stderr, "[-] Failed to open log file\n"); 175 | return -1; 176 | } 177 | fprintf(fi,"%d|",size); 178 | if(chk==1) fprintf(fi,"*"); 179 | for (int i = 0; i < size; i++) 180 | { 181 | //if (i % 16 == 0) 182 | // fprintf(fp, "[+] "); 183 | fprintf(fi, "%02X", (unsigned char)payld[i]); 184 | if(i!=size-1) fprintf(fi," "); 185 | //if (i % 16 == 15) 186 | // fprintf(fp, "\n"); 187 | } 188 | 189 | fprintf(fi,"\n"); 190 | } 191 | 192 | int _print_orgpayload(char* payld, int size) 193 | { 194 | printf("[+] Original Packet\n"); 195 | for (int i = 0; i < size; i++) 196 | { 197 | if (i % 16 == 0) 198 | printf("[+] "); 199 | printf("%02X ", (unsigned char)payld[i]); 200 | if (i % 16 == 15) 201 | printf("\n"); 202 | } 203 | printf("\n\n"); 204 | return 0; 205 | } 206 | 207 | 208 | int Fuzzer::print_payload(char* payld, int size) 209 | { 210 | printf("[+] %s might be crashed. Check it out\n", this->p->name.c_str()); 211 | for (int i = 0; i < size; i++) 212 | { 213 | if (i % 16 == 0) 214 | printf("[+] "); 215 | printf("%02X ", (unsigned char)payld[i]); 216 | if (i % 16 == 15) 217 | printf("\n"); 218 | } 219 | printf("\n\n"); 220 | return 0; 221 | } 222 | 223 | int Fuzzer::set_timespec() 224 | { 225 | ts.tv_sec = opt_sleep_ms / 1000; 226 | ts.tv_nsec = (opt_sleep_ms % 1000) * 10e6; 227 | } 228 | 229 | int Fuzzer::sleep_ms() 230 | { 231 | return nanosleep(&ts, NULL); 232 | } 233 | 234 | int Fuzzer::print_start() 235 | { 236 | printf("-----------------------------------------------------------\n"); 237 | printf("[+] Fuzzing start <%s>...\n", p->name.c_str()); 238 | } 239 | 240 | int Fuzzer::print_end() 241 | { 242 | printf("[+] Fuzzing end\n"); 243 | printf("-----------------------------------------------------------\n"); 244 | printf("\n"); 245 | } 246 | 247 | 248 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bProtocol.h" 25 | #include "bProfile.h" 26 | #include "Fuzzer.h" 27 | #include "devscan.h" 28 | #include "sdpscan.h" 29 | #include "strategy.h" 30 | #include "pairing.h" 31 | #include "global.h" 32 | 33 | 34 | #include "prtOBEX.h" 35 | 36 | 37 | int profile_fuzz(); 38 | 39 | int test_main() 40 | { 41 | char addr[] = "7C:66:9D:B0:88:30"; 42 | 43 | bProfile profile; 44 | prtOBEX* pobex = new prtOBEX(); 45 | pobex->channel = 12; 46 | profile.szbtaddr = addr; 47 | profile.protocols.push_back(pobex); 48 | profile.protocols[0]->pProfile = &profile; 49 | 50 | 51 | profile.protocols[0]->connect(); 52 | //profile.protocols[0]->send("asd", 4); 53 | profile.protocols[0]->free(); 54 | 55 | return 0; 56 | } 57 | 58 | 59 | int main(int argc, char* argv[]) 60 | { 61 | 62 | //int s = strategy(); 63 | 64 | /*switch(s) 65 | { 66 | case 1: 67 | // no.1 pairing level analysis 68 | if(pairing_check() < 0) 69 | { 70 | return 0; // pairing checking err 71 | } 72 | printf("Pairing checking completed.\n"); 73 | break; 74 | 75 | case 2: 76 | // no.2 profile level (protocols) 77 | profile_fuzz(); 78 | break; 79 | default: 80 | break; 81 | }*/ 82 | 83 | printf("\nBlackBox Testing - Bluetooth Fuzzer ver. 1.2\n"); 84 | profile_fuzz(); 85 | 86 | return 0; 87 | 88 | } 89 | 90 | 91 | 92 | int profile_fuzz() 93 | { 94 | /* test code - add S-Link device */ 95 | 96 | printf("\n"); 97 | printf("[+] Start scanning bluetooth devices...\n"); 98 | printf("(Press Ctrl + C if you want to quit.)\n"); 99 | finddev(); 100 | if(devices.size() == 0) 101 | { 102 | printf("[-] No device found. Please try again.\n"); 103 | return 0; 104 | } 105 | 106 | printf("\n Target Bluetooth Device List\n"); 107 | printf(" [No.]\t[BT address]\t\t[Device name]\n"); 108 | for (int i = 0; i < devices.size(); i++) 109 | printf(" %02d\t%s\t%s\n", i, devices[i].bt_addr.c_str(), devices[i].name.c_str()); 110 | 111 | printf(" Total : %ld\n\n", devices.size()); 112 | 113 | int device_num = -1; 114 | printf("\nselect device(exit : -1): "); 115 | scanf("%d", &device_num); 116 | if(device_num==-1) return 0; 117 | while (device_num < 0 || device_num >= devices.size()) 118 | { 119 | printf("wrong device number\n"); 120 | printf("select device: "); 121 | scanf("%d", &device_num); 122 | } 123 | devscan *pDev_s = &devices[device_num]; 124 | 125 | /* sdp scan module start */ 126 | 127 | printf("\nStart scanning services...\n"); 128 | printf("(Press Ctrl + C if you want to quit.)\n\n"); 129 | //sdpscan((char*)devices[device_num].bt_addr.c_str(), devices[device_num].profiles); 130 | int ret=sdpscan((char*)pDev_s->bt_addr.c_str(), pDev_s->profiles); 131 | if(ret==-1){ 132 | printf("\n***Fuzzing Module Stop***\n\n"); 133 | return 0; 134 | } 135 | 136 | /* sdp scan module complete */ 137 | 138 | 139 | //printf("profiles.size(): %ld\n", devices[device_num].profiles.size()); 140 | for (int i = 0; i < pDev_s->profiles.size(); i++) 141 | { 142 | //printf("\t%02d\t[0x%04x]: %s\n", i, devices[device_num].profiles[i].uuid.value.uuid16, devices[device_num].profiles[i].name.c_str()); 143 | printf("\t%02d\t[0x%04x]: %s\n", i, pDev_s->profiles[i].uuid.value.uuid16, pDev_s->profiles[i].name.c_str()); 144 | /* 145 | for (int j = 0; j < profiles[i].protocols.size(); j++) 146 | printf("\t [0x%04x]: %s\n", j, devices[device_num].profiles[i].protocols[j].uuid.value.uuid16, devices[device_num].profiles[i].protocols[j].name.c_str()); 147 | */ 148 | } 149 | 150 | int prof_num = -1; 151 | printf("\nSelect a profile to fuzz(exit : -1): "); 152 | scanf("%d", &prof_num); 153 | if(prof_num==-1) return 0; 154 | //while (prof_num < 0 || prof_num >= devices[device_num].profiles.size()) 155 | while (prof_num < 0 || prof_num >= pDev_s->profiles.size()) 156 | { 157 | printf("Wrong profile number\n"); 158 | printf("Select a profile to fuzz(exit : -1): "); 159 | scanf("%d", &prof_num); 160 | } 161 | printf("\n"); 162 | if(prof_num==-1) return 0; 163 | //bProfile *pProfile_s = &devices[device_num].profiles[prof_num]; 164 | bProfile *pProfile_s = &pDev_s->profiles[prof_num]; 165 | 166 | 167 | printf("\t00\t[0x0000]: ALL protocols\n"); 168 | for (int i = 0; i < pProfile_s->protocols.size(); i++) 169 | printf("\t%02d\t[0x%04x]: %s\n", i + 1, pProfile_s->protocols[i]->uuid.value.uuid16, pProfile_s->protocols[i]->name.c_str()); 170 | 171 | 172 | int proto_num = -1; 173 | printf("Select a protocol to fuzz(exit : -1): "); 174 | scanf("%d", &proto_num); 175 | while (proto_num < -1 || proto_num > devices[device_num].profiles[prof_num].protocols.size()) 176 | { 177 | printf("Wrong protocol number\n"); 178 | printf("Select a protocol to fuzz(exit : -1): "); 179 | scanf("%d", &proto_num); 180 | } 181 | if(proto_num==-1) return 0; 182 | printf("\n\n"); 183 | 184 | FILE *fo; 185 | fo=fopen("log.wfl","w"); 186 | fprintf(fo,"%s\n",pDev_s->bt_addr.c_str()); 187 | fclose(fo); 188 | 189 | if (!proto_num) 190 | { // fuzz ALL protocols 191 | for (int i = 0; i < pProfile_s->protocols.size(); i++) 192 | { 193 | Fuzzer fuzz(pProfile_s->protocols[i]); 194 | fuzz.fuzz(); 195 | } 196 | } 197 | else 198 | { // fuzz specific protocol 199 | Fuzzer fuzz(pProfile_s->protocols[proto_num - 1]); 200 | fuzz.fuzz(); 201 | } 202 | 203 | 204 | return 0; 205 | } 206 | 207 | 208 | 209 | int main1(int argc, char* argv[]) 210 | { 211 | struct sockaddr_l2 addr; 212 | l2cap_cmd_hdr *cmd; 213 | int sock; 214 | char* bdstr_addr = argv[1]; 215 | 216 | sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP); 217 | if ( sock < 0 ) 218 | { 219 | printf("sock() error\n"); 220 | return 1; 221 | } 222 | 223 | 224 | memset(&addr, 0, sizeof(addr)); 225 | addr.l2_family = AF_BLUETOOTH; 226 | if ( bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0 ) 227 | { 228 | printf("bind() error\n"); 229 | return 1; 230 | } 231 | 232 | 233 | str2ba(bdstr_addr, &addr.l2_bdaddr); 234 | if ( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0 ) 235 | { 236 | printf("connect() error\n"); 237 | return 1; 238 | } 239 | 240 | { 241 | char buf[1024]; 242 | int i; 243 | l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr*)buf; 244 | cmd->code = 1; 245 | cmd->ident = 1; 246 | cmd->len = __cpu_to_le16(10); 247 | for (i = L2CAP_CMD_HDR_SIZE; i < 1024; i++) 248 | { 249 | } 250 | } 251 | 252 | 253 | 254 | return 0; 255 | } 256 | -------------------------------------------------------------------------------- /iGenerator.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "iGenerator.h" 17 | 18 | extern const char* PKT_TABLE[260]; 19 | extern int SIZE_TABLE[]; 20 | 21 | iGenerator::iGenerator() 22 | :cnt(0) 23 | { 24 | db.open(); 25 | } 26 | 27 | iGenerator::~iGenerator() 28 | { 29 | db.close(); 30 | } 31 | 32 | int iGenerator::getInput(uuid_t uuid, char *mut_payld, int *mut_size) 33 | { 34 | int proto; 35 | 36 | /* get original packet form database */ 37 | /* NOT IMPLEMENTED YET */ 38 | proto = sdp_uuid_to_proto(&uuid); 39 | /* 40 | if (proto == L2CAP_UUID) 41 | { 42 | memcpy(org_payld, PKT_L2C, sizeof(PKT_L2C) - 1); 43 | if (!isFirst) 44 | org_size = sizeof(PKT_L2C) - 1; 45 | else 46 | { 47 | getRand(&org_size, sizeof(org_size)); 48 | org_size %= 500; 49 | org_size += 4; 50 | } 51 | //for (int i = 0; i < 100; i++) 52 | // org_payld[i] = (i+1)*219732173>>3; 53 | //org_size = 100; 54 | } 55 | else if (proto == RFCOMM_UUID) 56 | { 57 | memcpy(org_payld, PKT_RFC, sizeof(PKT_RFC) - 1); 58 | if (!isFirst) 59 | org_size = sizeof(PKT_RFC) - 1; 60 | else 61 | { 62 | getRand(&org_size, sizeof(org_size)); 63 | org_size %= 500;//(sizeof(PKT_RFC) - 5); 64 | org_size += 5; 65 | } 66 | } 67 | else if (proto == OBEX_UUID) 68 | { 69 | memcpy(org_payld, PKT_OBEX, sizeof(PKT_OBEX) - 1); 70 | if (!isFirst) 71 | org_size = sizeof(PKT_OBEX) -1; 72 | else 73 | { 74 | getRand(&org_size, sizeof(org_size)); 75 | org_size %= 500;//(sizeof(PKT_OBEX) - 1); 76 | org_size += 1; 77 | } 78 | } 79 | else 80 | { 81 | for (int i = 0; i < 30; i++) 82 | org_payld[i] = i; 83 | org_size = 30; 84 | } 85 | */ 86 | int random, id; 87 | srand(time(NULL)); 88 | getRand(&random, sizeof(random)); 89 | if(cnt>=10000 || cnt==0){ 90 | if ((id = db.get_packet(proto, 0, random, mut_payld, mut_size)) < 1) 91 | { 92 | int size; 93 | if (0 < proto && proto < sizeof(PKT_TABLE) - 1){ 94 | if(*mut_size==0) 95 | size=SIZE_TABLE[proto]; 96 | else 97 | size=*mut_size; 98 | memcpy(mut_payld, PKT_TABLE[proto], size); 99 | *mut_size=size; 100 | } 101 | else 102 | { 103 | size=30; 104 | getRand(mut_payld, size); 105 | *mut_size = size; 106 | } 107 | } 108 | cnt=0; 109 | } 110 | 111 | else 112 | { 113 | /* scheduling the mutate function */ 114 | /* IMPLEMENTATION DOES NOT FINISHED */ 115 | int size; 116 | srand(time(NULL)); 117 | size=*mut_size; 118 | if(cnt%1000==0) 119 | *mut_size=rand()%(size*13/10)+(size*7/10); 120 | mutate0(mut_payld, *mut_size, NULL); 121 | //genRandInput(org_payld, org_size); 122 | } 123 | 124 | cnt++; 125 | return 0; 126 | } 127 | 128 | int iGenerator::mutate0(char *payld, int size, void *opt) 129 | { /* opt should contain value of r and n */ 130 | uint32_t rand32; 131 | int i; 132 | 133 | double r = 0.3; // [0, 1] 134 | int n = 1; // byte sequence 135 | 136 | for (i = 0; i < size * r; i++) 137 | { 138 | getRand(&rand32, sizeof(rand32)); 139 | genRandInput(&payld[rand32 % (size-n+1)], n); 140 | //getRand(&payld[rand32 % (size-n+1)], n); 141 | //payld[rand32 % (size-n+1)] = rand32 >> 16; 142 | } 143 | 144 | return 0; 145 | } 146 | 147 | int iGenerator::genRandInput(char *payld, int size) 148 | { 149 | double mu = 400.0; 150 | double sigma = 150.0; 151 | int i; 152 | 153 | for (i = 0; i < size; i++) 154 | { 155 | payld[i] = (char)genGaussianNoise(mu, sigma); 156 | } 157 | } 158 | 159 | int iGenerator::getRand(void *dst, int size) 160 | { 161 | int fd = open("/dev/urandom", O_RDONLY); 162 | if (fd < 0) 163 | { 164 | printf("[-] iGenerator::getRand(), open() failed\n"); 165 | return -1; 166 | } 167 | 168 | if (read(fd, dst, size) < 0) 169 | { 170 | printf("[-] iGenerator::getRand(), read() failed\n"); 171 | return -1; 172 | } 173 | 174 | close(fd); 175 | } 176 | 177 | double iGenerator::genGaussianNoise(double mu, double sigma) 178 | { 179 | const double epsilon = std::numeric_limits::min(); 180 | const double tau = 2.0*3.14159265358979323846; 181 | 182 | static double z0; 183 | double u1, u2; 184 | 185 | do 186 | { 187 | int tmp1, tmp2; 188 | getRand(&tmp1, sizeof(int)); 189 | getRand(&tmp2, sizeof(int)); 190 | u1 = tmp1 * (1.0 / RAND_MAX); 191 | u2 = tmp2 * (1.0 / RAND_MAX); 192 | } 193 | while ( u1 <= epsilon ); 194 | 195 | z0 = sqrt(-2.0 * log(u1)) * cos(tau * u2); 196 | 197 | return z0 * sigma + mu; 198 | } 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | const char* PKT_TABLE[260] = {0, PKT_SDP, 0, PKT_RFC, 0, 0, 0, 0, PKT_OBEX, 0, 207 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208 | 0, 0, 0, PKT_AVC, 0, PKT_AVD, 0, 0, 0, 0, 209 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216 | 217 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227 | 228 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233 | 0, 0, 0, 0, 0, 0, PKT_L2C, 0, 0, 0}; 234 | 235 | int SIZE_TABLE[] = {0, sizeof(PKT_SDP)-1, 0, sizeof(PKT_RFC)-1, 0, 0, 0, 0, sizeof(PKT_OBEX)-1, 0, 236 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237 | 0, 0, 0, sizeof(PKT_AVC)-1, 0, sizeof(PKT_AVD)-1, 0, 0, 0, 0, 238 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245 | 246 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256 | 257 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 258 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 260 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 261 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262 | 0, 0, 0, 0, 0, 0, sizeof(PKT_L2C)-1, 0, 0, 0}; 263 | 264 | 265 | -------------------------------------------------------------------------------- /pairing.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "pairing.h" 17 | 18 | int pairing_check() 19 | { 20 | int sniff_no, inq_no; 21 | int master_no, slave_no; 22 | 23 | hciscan(); 24 | /* two devices select */ 25 | while(true) 26 | { 27 | printf(" Enter number of a HCI device to read : "); 28 | scanf("%d", &sniff_no); 29 | if(sniff_no >= 0 && sniff_no <= (int)hcidevs.size()-1) 30 | { 31 | str2ba(hcidevs[sniff_no].bt_addr.c_str(), &snf_bdr); 32 | printf(" -> Device %s (%s) is set be reading device.\n", 33 | hcidevs[sniff_no].name.c_str(), 34 | hcidevs[sniff_no].bt_addr.c_str()); 35 | break; 36 | } 37 | printf("[-] Please enter the correct no.\n"); 38 | } 39 | 40 | while(true) 41 | { 42 | printf(" Enter number of a HCI device to write : "); 43 | scanf("%d", &inq_no); 44 | if(inq_no >= 0 && inq_no <= (int)hcidevs.size()-1) 45 | { 46 | str2ba(hcidevs[inq_no].bt_addr.c_str(), &inq_bdr); 47 | printf(" -> Device %s (%s) is set be writing device.\n", 48 | hcidevs[inq_no].name.c_str(), 49 | hcidevs[inq_no].bt_addr.c_str()); 50 | break; 51 | } 52 | printf("[-] Please enter the correct no.\n"); 53 | } 54 | 55 | /* test code - add S-Link device */ 56 | devscan d; 57 | d.name = "S-Link for test"; 58 | d.bt_addr = "7C:66:9D:B0:88:30"; 59 | devices.push_back(d); 60 | /* test code end */ 61 | printf("\n"); 62 | printf(" Start scanning bluetooth devices...\n"); 63 | finddev(); 64 | if(devices.size() == 0) 65 | { 66 | printf("[-] No device found. Please try again.\n"); 67 | return 0; 68 | } 69 | 70 | printf("\n Target Bluetooth Device List\n"); 71 | printf(" [No.]\t[BT address]\t\t[Device name]\n"); 72 | for (int i = 0; i < devices.size(); i++) 73 | printf(" %02d\t%s\t%s\n", i, devices[i].bt_addr.c_str(), devices[i].name.c_str()); 74 | 75 | printf(" Total : %ld\n\n", devices.size()); 76 | 77 | while(true) 78 | { 79 | printf(" Enter number of master device among target devices : "); 80 | scanf("%d", &master_no); 81 | if(master_no >= 0 && master_no <= (int)devices.size()-1) 82 | { 83 | str2ba(devices[master_no].bt_addr.c_str(), &m_bdr); 84 | printf(" -> Device %s (%s) is set to be master device.\n", 85 | devices[master_no].name.c_str(), 86 | devices[master_no].bt_addr.c_str()); 87 | break; 88 | } 89 | printf("[-] Please enter the correct no.\n"); 90 | } 91 | 92 | while(true) 93 | { 94 | printf(" Enter number of slave device among target devices : "); 95 | scanf("%d", &slave_no); 96 | if(slave_no == master_no) 97 | { 98 | printf("[-] Number of slave and master are same. Input again.\n"); 99 | continue; 100 | } 101 | if(slave_no >= 0 && slave_no <= (int)devices.size()-1) 102 | { 103 | str2ba(devices[slave_no].bt_addr.c_str(), &s_bdr); 104 | printf(" Device %s (%s) is set to be slave device.\n", 105 | devices[slave_no].name.c_str(), 106 | devices[slave_no].bt_addr.c_str()); 107 | break; 108 | } 109 | printf("[-] Please enter the correct no.\n"); 110 | } 111 | 112 | printf("\n Pairing checking start ... - \n"); 113 | 114 | // unpairing attack detection 115 | printf(" (1) Checking unpairing vuln. ... \n"); 116 | if(unpair_check() < 0) 117 | { 118 | printf("[-] An error occurred during checking unpairing vulnerabilty...\n"); 119 | return -1; 120 | } 121 | 122 | // pairing sniffing detection 123 | printf(" (2) Checking sniffing ... \n"); 124 | if(sniff_check() < 0) 125 | { 126 | printf("[-] An error occurred during checking sniffing vulnerabilty...\n"); 127 | return -1; 128 | } 129 | 130 | // pairing spoofing detection 131 | printf(" (3) Checking spoofing ... \n"); 132 | if(spoof_check() < 0) 133 | { 134 | printf("[-] An error occurred during checking spoofing vulnerabilty...\n"); 135 | return -1; 136 | } 137 | 138 | return 0; 139 | } 140 | 141 | int hciscan() 142 | { 143 | FILE *in; 144 | char buff[512]; 145 | 146 | if(!(in = popen("hciconfig", "r"))) 147 | { 148 | printf("[-] HCI devices scanning failed. \n"); 149 | return -1; 150 | } 151 | 152 | printf("\n"); 153 | 154 | char tmpaddr[100]; 155 | char tmpname[100]; 156 | printf(" HCI Device List\n"); 157 | printf(" [No.]\t[BT address]\t\t[Device name]\n"); 158 | while(fgets(buff, sizeof(buff), in) != NULL) 159 | { 160 | if (strncmp(buff, "hci", 3) == 0) 161 | { 162 | int i = -1; 163 | while (buff[++i] != ':'); 164 | buff[i] = 0; 165 | strcpy(tmpname, buff); 166 | } 167 | else if (strncmp(buff, "\tBD", 3) == 0) 168 | { 169 | int i = -1; 170 | while (buff[++i] != ':'); 171 | strncpy(tmpaddr, &buff[i+2], 17); 172 | tmpaddr[17] = 0; 173 | } 174 | 175 | if(strncmp(buff, "\n", 1) == 0) 176 | { 177 | // one hci element 178 | hcidevs.push_back(devscan()); 179 | hcidevs.back().name = tmpname; 180 | hcidevs.back().bt_addr = tmpaddr; 181 | } 182 | } 183 | 184 | pclose(in); 185 | 186 | for (int i = 0; i < hcidevs.size(); i++) 187 | printf(" %02d\t%s\t%s\n", i, hcidevs[i].bt_addr.c_str(), hcidevs[i].name.c_str()); 188 | 189 | printf(" Total : %ld \n\n", hcidevs.size()); 190 | 191 | return 0; 192 | } 193 | 194 | int unpair_check() 195 | { 196 | string str_inqbdr = ""; 197 | ba2str(&inq_bdr, (char *)str_inqbdr.c_str()); 198 | string str_slavebdr = ""; 199 | ba2str(&s_bdr, (char *)str_slavebdr.c_str()); 200 | 201 | if(changebdaddr(str_inqbdr, str_slavebdr) < 0) 202 | { 203 | return -1; 204 | } 205 | 206 | return 0; 207 | 208 | } 209 | 210 | int changebdaddr(string dev_inq, string new_bdr) 211 | { 212 | char cmd[] = "./bdaddr -i "; 213 | strcat(cmd, dev_inq.c_str()); 214 | strcat(cmd, " "); 215 | strcat(cmd, new_bdr.c_str()); 216 | 217 | FILE *in1, *in2; 218 | char buff1[512], buff2[512]; 219 | 220 | if(!(in1 = popen(cmd, "r"))) 221 | { 222 | printf("[-] Error executing address change. \n"); 223 | return -1; 224 | } 225 | 226 | while(fgets(buff1, sizeof(buff1), in1) != NULL) 227 | { 228 | if (strstr(buff1, "Can't write new address") != NULL) 229 | { 230 | printf("[-] The hci device %s is not available for address change.\n", dev_inq.c_str()); 231 | return -1; 232 | } 233 | 234 | if (strstr(buff1, "Address changed") != NULL) 235 | { 236 | printf(" Address is changed.\n"); 237 | strcpy(cmd, "hciconfig -a "); 238 | strcat(cmd, dev_inq.c_str()); 239 | strcat(cmd, " reset"); 240 | 241 | 242 | if(!(in2 = popen(cmd, "r"))) 243 | { 244 | printf("[-] Error executing address resetting. \n"); 245 | return -1; 246 | } 247 | 248 | if(fgets(buff2, sizeof(buff2), in2) != "','") 249 | { 250 | return -1; 251 | } 252 | 253 | printf(" Address is successfully changed. \n"); 254 | return 0; 255 | } 256 | } 257 | printf(" The target hci device %s is safe to address change.\n", new_bdr.c_str()); 258 | return -1; 259 | 260 | } 261 | 262 | int sniff_check() 263 | { 264 | return 0; 265 | } 266 | 267 | int spoof_check() 268 | { 269 | return 0; 270 | } 271 | -------------------------------------------------------------------------------- /prtOBEX.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "prtOBEX.h" 17 | #include 18 | 19 | using namespace std; 20 | 21 | extern FILE *fi; 22 | 23 | 24 | prtOBEX::prtOBEX() 25 | :sock(0), connection_id(0), put_cnt(0) 26 | { 27 | } 28 | 29 | prtOBEX::prtOBEX(const bProtocol &p) 30 | :bProtocol(p), sock(0), connection_id(0), put_cnt(0) 31 | { 32 | } 33 | 34 | prtOBEX::~prtOBEX() 35 | { 36 | this->free(); 37 | } 38 | 39 | prtOBEX::prtOBEX(const prtOBEX &p) 40 | :bProtocol((const bProtocol&)p) 41 | { 42 | sock = p.sock; 43 | memcpy(&addr_l2, &p.addr_l2, sizeof(sockaddr_l2)); 44 | memcpy(&addr_rc, &p.addr_rc, sizeof(sockaddr_rc)); 45 | } 46 | 47 | bProtocol* prtOBEX::Clone() 48 | { 49 | return new prtOBEX(*this); 50 | } 51 | 52 | int prtOBEX::connect() 53 | { 54 | int ret; 55 | //if (((bProfile*)pProfile)->version == 0x100) 56 | if (!this->psm) 57 | ret = _connect_rfcomm(); 58 | else 59 | ret = _connect_l2cap(); 60 | 61 | if (ret) /* error in connection process */ 62 | return ret; 63 | 64 | 65 | 66 | char packet[1024]; 67 | obex_hdr *phdr = (obex_hdr*)packet; 68 | obex_hdr_connect *phdr_connect = (obex_hdr_connect*)(packet + OBEX_HDR_SIZE); 69 | 70 | phdr->opcode = OBEX_OP_CONNECT | OBEX_OP_FINAL; 71 | phdr->len = bswap_16(OBEX_HDR_SIZE + OBEX_HDR_CONNECT_SIZE); // __cpu_to_be16? 72 | phdr_connect->version = 0x10; 73 | phdr_connect->flags = 0; 74 | phdr_connect->maxlen = bswap_16(PAYLOAD_SIZE); // __cpu_to_be16? 75 | 76 | ret = ::send(sock, packet, OBEX_HDR_SIZE + OBEX_HDR_CONNECT_SIZE, 0); 77 | // ret = this->send(packet, OBEX_HDR_SIZE + OBEX_HDR_CONNECT_SIZE); 78 | if (ret <= 0) 79 | { 80 | printf("[-] prtOBEX::connect, send() failed\n"); 81 | this->free(); 82 | return -1; 83 | } 84 | 85 | ::recv(sock, packet, 1024, 0); 86 | if (!(phdr->opcode & OBEX_OP_SUCCESS)) 87 | { 88 | printf("[-] prtOBEX::connect, recv opcode: %02X\n", phdr->opcode); 89 | this->free(); 90 | return -1; 91 | } 92 | 93 | phdr->len = bswap_16(phdr->len); 94 | if (phdr->len == 7) 95 | return 0; 96 | else if (phdr->len == 12 && (unsigned char)packet[7] == OBEX_HDR_CONNECTIONID) 97 | { 98 | connection_id = bswap_32(*(uint32_t*)(&packet[8])); 99 | } 100 | else 101 | { 102 | printf("[-] prtOBEX::connect, unknown option: %02X, %d\n", (unsigned char)packet[7], phdr->len); 103 | this->free(); 104 | return -1; 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | int prtOBEX::_connect_l2cap() 111 | { 112 | sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP); 113 | //sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 114 | if (sock < 0) 115 | { 116 | printf("[-] prtOBEX::_connect_l2cap, socket() failed\n"); 117 | return -1; 118 | } 119 | 120 | memset(&addr_l2, 0, sizeof(addr_l2)); 121 | addr_l2.l2_family = AF_BLUETOOTH; 122 | addr_l2.l2_psm = htobs(this->psm); 123 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr_l2.l2_bdaddr); 124 | if (::connect(sock, (struct sockaddr*)&addr_l2, sizeof(addr_l2)) < 0) 125 | { 126 | printf("[-] prtOBEX::_connect_l2cap, connect() failed\n"); 127 | printf("[-] %s\n", strerror(errno)); 128 | close(sock); 129 | sock = 0; 130 | return -1; 131 | } 132 | 133 | return 0; 134 | } 135 | 136 | int prtOBEX::_connect_rfcomm() 137 | { 138 | sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 139 | if (sock < 0) 140 | { 141 | printf("[-] prtOBEX::_connect_rfcomm, socket() failed\n"); 142 | return -1; 143 | } 144 | 145 | bProfile *pProfile = (bProfile*)this->pProfile; 146 | int rfc_channel = -1; 147 | for (int i = 0; i < pProfile->protocols.size(); i++) 148 | { 149 | if (pProfile->protocols[i]->uuid.value.uuid16 == RFCOMM_UUID) 150 | rfc_channel = pProfile->protocols[i]->channel; 151 | } 152 | if (rfc_channel == -1) 153 | { 154 | printf("[-] prtOBEX::_connect_rfcomm, cannot find rfcomm channel\n"); 155 | close(sock); 156 | sock = 0; 157 | return -1; 158 | } 159 | 160 | memset(&addr_rc, 0, sizeof(addr_rc)); 161 | addr_rc.rc_family = AF_BLUETOOTH; 162 | addr_rc.rc_channel = (uint8_t) rfc_channel; 163 | str2ba(((bProfile*)(this->pProfile))->szbtaddr, &addr_rc.rc_bdaddr); 164 | if (::connect(sock, (struct sockaddr*)&addr_rc, sizeof(addr_rc)) < 0) 165 | { 166 | printf("[-] prtOBEX::_connect_rfcomm, connect() failed\n"); 167 | printf("[-] %s\n", strerror(errno)); 168 | close(sock); 169 | sock = 0; 170 | return -1; 171 | } 172 | 173 | return 0; 174 | } 175 | 176 | 177 | int prtOBEX::free() 178 | { 179 | if (sock) 180 | close(sock); 181 | sock = 0; 182 | return 0; 183 | } 184 | 185 | char pack[65536]={0}; 186 | int prtOBEX::send(char *s, int size) 187 | { 188 | int size2=0; 189 | 190 | if (!sock) 191 | return -1; 192 | 193 | memset(pack,0,sizeof(pack)); 194 | 195 | if(!put_cnt){ 196 | //obex_hdr *phdr = (obex_hdr*)s; 197 | //obex_hdr_put *puthdr = (obex_hdr_put*)(s+OBEX_HDR_PUT_SIZE); 198 | obex_hdr_put *puthdr = (obex_hdr_put*)(pack); 199 | puthdr->opcode = OBEX_OP_PUT; 200 | puthdr->len = bswap_16(OBEX_HDR_PUT_SIZE+size); 201 | puthdr->connection_id_hdr = OBEX_HDR_CONNECTIONID; 202 | puthdr->connection_id = bswap_32(connection_id); 203 | puthdr->name_hdr=OBEX_HDR_NAME; 204 | puthdr->name_len=bswap_16(13); 205 | puthdr->name[0]=0x7400; 206 | puthdr->name[1]=0x6500; 207 | puthdr->name[2]=0x7300; 208 | puthdr->name[3]=0x7400; 209 | puthdr->name[4]=0x0000; 210 | puthdr->len_hdr = OBEX_HDR_LENGTH; 211 | puthdr->file_len = bswap_32(DEFAULT_ITERATION*size); 212 | puthdr->bdy_hdr = OBEX_HDR_BODY; 213 | puthdr->bdy_hdr_len = bswap_16(size+3); 214 | memcpy(pack+OBEX_HDR_PUT_SIZE,s,size); 215 | size2=OBEX_HDR_PUT_SIZE; 216 | 217 | //fprintf(fi,"PUT(1 byte) | Length(2 bytes) | Opcode(1 byte)| Connection id(4 bytes)| Opcode(1 byte)| Name Length(2 bytes) | test(name, 5 byte) | Opcode(1 byte) | File Length(4 bytes) | Opcode(1 byte) | Length(2 bytes) | Body |\n"); 218 | fprintf(fi,"1\nsend|1|"); 219 | } 220 | 221 | else{ 222 | if(put_cnt==1) fprintf(fi,"2\n"); 223 | //obex_hdr *phdr = (obex_hdr*)s; 224 | obex_hdr_put_cont *puthdr = (obex_hdr_put_cont*)(pack); 225 | puthdr->opcode = OBEX_OP_PUT; 226 | puthdr->len = bswap_16(size+6); 227 | puthdr->bdy_hdr = OBEX_HDR_BODY; 228 | puthdr->bdy_hdr_len = bswap_16(size+3); 229 | memcpy(pack+6,s,size); 230 | size2=6; 231 | 232 | //fprintf(fi,"PUT(1 byte) | Length(2 bytes) | Opcode(1 byte) | Length(2 bytes) | Body |\n"); 233 | fprintf(fi,"send|"); 234 | } 235 | //return ::write(sock, s, size); 236 | put_cnt++; 237 | 238 | if(put_cnt==DEFAULT_ITERATION){ 239 | write(sock, pack, size); 240 | 241 | //obex_hdr *phdr = (obex_hdr*)s; 242 | memset(pack,0,sizeof(pack)); 243 | obex_hdr_put_cont *puthdr = (obex_hdr_put_cont*) (pack); 244 | puthdr->opcode = OBEX_OP_PUT; 245 | puthdr->len = bswap_16(6); 246 | puthdr->bdy_hdr = OBEX_HDR_ENDOFBODY; 247 | puthdr->bdy_hdr_len = bswap_16(3); 248 | 249 | //fprintf(fi,"PUT(1 byte) | Length(2 bytes) | End Of Body(1 byte) | Length(2 bytes) |\n"); 250 | fprintf(fi,"send|3|"); 251 | 252 | return write(sock, pack, 6); 253 | 254 | } 255 | return write(sock, pack, size+size2); 256 | } 257 | 258 | int prtOBEX::recv(char *s, int size) 259 | { 260 | if (!sock) 261 | return -1; 262 | 263 | return ::recv(sock, s, size, 0); 264 | } 265 | 266 | int prtOBEX::reconnect() 267 | { 268 | this->free(); 269 | return this->connect(); 270 | } 271 | -------------------------------------------------------------------------------- /sdpscan.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * BBTestingTool - Bluetooth vulnerability testing tool 5 | * 6 | * Copyright (C) 2015 CCS, Korea University 7 | * All right reserved 8 | * 9 | * Authors 10 | * Dong-hyeok Kim 11 | * Choongin Lee 12 | * Jihwan Jeong 13 | * 14 | */ 15 | 16 | #include "sdpscan.h" 17 | 18 | using namespace std; 19 | 20 | bProfile* pProfile; // not a global variable 21 | 22 | static void _profile_desc(void *value, void *user) 23 | { 24 | char szName[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR]; 25 | char szUUID[MAX_LEN_UUID_STR]; 26 | sdp_profile_desc_t *desc = (sdp_profile_desc_t*)value; 27 | 28 | sdp_uuid2strn(&desc->uuid, szUUID, MAX_LEN_UUID_STR); // necessary? not sure... 29 | memcpy(&pProfile->uuid, &desc->uuid, sizeof(uuid_t)); 30 | //uuid_copy(pProfile->uuid, &desc->uuid); 31 | 32 | sdp_profile_uuid2strn(&desc->uuid, szName, sizeof(szName)); 33 | pProfile->name = szName; 34 | 35 | if (desc->version) 36 | pProfile->version = desc->version; 37 | } 38 | 39 | static void _service_desc(void *value, void *user) 40 | { 41 | sdp_data_t *p = (sdp_data_t*)value; 42 | sdp_data_t *s = NULL; 43 | char szName[MAX_LEN_PROTOCOL_UUID_STR]; 44 | char szUUID[MAX_LEN_UUID_STR]; 45 | int i = 0, proto = 0; 46 | 47 | if (pProfile == NULL) 48 | { 49 | printf("[-] error: pProfile is NULL\n"); 50 | return; 51 | } 52 | bProtocol tmpproto; 53 | //pProfile->protocols.push_back(bProtocol()); 54 | 55 | for (; p; p = p->next, i++) 56 | { 57 | switch (p->dtd) 58 | { 59 | case SDP_UUID16: 60 | case SDP_UUID32: 61 | case SDP_UUID128: 62 | sdp_uuid2strn(&p->val.uuid, szUUID, MAX_LEN_UUID_STR); // necessary? not sure... 63 | memcpy(&tmpproto.uuid, &p->val.uuid, sizeof(uuid_t)); 64 | //memcpy(&pProfile->protocols.back().uuid, &p->val.uuid, sizeof(uuid_t)); 65 | 66 | // get name of current protocol 67 | sdp_proto_uuid2strn(&p->val.uuid, szName, sizeof(szName)); 68 | tmpproto.name = szName; 69 | //pProfile->protocols.back().name = szName; 70 | 71 | proto = sdp_uuid_to_proto(&p->val.uuid); 72 | break; 73 | case SDP_UINT8: 74 | if (proto == RFCOMM_UUID) 75 | tmpproto.channel = p->val.uint8; 76 | //pProfile->protocols.back().channel = p->val.uint8; 77 | else 78 | tmpproto.uint8 = p->val.uint8; 79 | //pProfile->protocols.back().uint8 = p->val.uint8; 80 | break; 81 | case SDP_UINT16: 82 | if (proto == L2CAP_UUID) 83 | { 84 | if (i == 1) 85 | { // PSM 86 | tmpproto.psm = p->val.uint16; 87 | //pProfile->protocols.back().psm = p->val.uint16; 88 | } 89 | else 90 | { // version 91 | tmpproto.version = p->val.uint16; 92 | //pProfile->protocols.back().version = p->val.uint16; 93 | } 94 | } 95 | /* 96 | else if (proto == BNEP_UUID) 97 | {} 98 | else 99 | {} 100 | */ 101 | break; 102 | 103 | case SDP_SEQ16: 104 | case SDP_SEQ8: 105 | default: 106 | break; 107 | } 108 | } 109 | if (proto == SDP_UUID) 110 | pProfile->protocols.push_back(new prtSDP(tmpproto)); 111 | else if (proto == RFCOMM_UUID) 112 | pProfile->protocols.push_back(new prtRFCOMM(tmpproto)); 113 | else if (proto == L2CAP_UUID) 114 | pProfile->protocols.push_back(new prtL2CAP(tmpproto)); 115 | else if (proto == OBEX_UUID) 116 | pProfile->protocols.push_back(new prtOBEX(tmpproto)); 117 | else 118 | pProfile->protocols.push_back(new bProtocol(tmpproto)); 119 | } 120 | 121 | 122 | static void _access_protos(void *value, void *user) 123 | { 124 | sdp_list_t *protDescSeq = (sdp_list_t*)value; 125 | sdp_list_foreach(protDescSeq, _service_desc, 0); 126 | } 127 | 128 | static void _obex_psm_check(void *value, void* user) 129 | { 130 | sdp_data_t *p = (sdp_data_t*)value; 131 | if (p->attrId == 0x200 && p->dtd == SDP_UINT16) 132 | { /* attrId GOEP L2CAP PSM = 0x200 */ 133 | *(int*)user = p->val.uint32; 134 | //printf("data: %04x\n", p->val.uint32); 135 | } 136 | } 137 | 138 | static void _set_attr(sdp_record_t *rec, vector &bprofiles) 139 | { 140 | sdp_list_t *list = NULL; 141 | sdp_list_t *proto = NULL; 142 | 143 | //sdp_record_print(rec); 144 | 145 | if (sdp_get_access_protos(rec, &proto) == 0) 146 | { 147 | // create new profile 148 | bprofiles.push_back(bProfile()); 149 | pProfile = &bprofiles.back(); 150 | 151 | sdp_list_foreach(proto, _access_protos, 0); 152 | sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0); 153 | sdp_list_free(proto, 0); 154 | 155 | 156 | // check whether GOEP L2CAP PSM attribute exists or not 157 | int obex_psm = 0; 158 | if (rec && rec->attrlist) 159 | sdp_list_foreach(rec->attrlist, _obex_psm_check, &obex_psm); 160 | if (obex_psm) 161 | { // GOEP L2CAP PSM exists 162 | for (int i = 0; i < pProfile->protocols.size(); i++) 163 | { // double-check whether OBEX protocol exists or not 164 | if (pProfile->protocols[i]->uuid.value.uuid16 = OBEX_UUID) 165 | pProfile->protocols[i]->psm = obex_psm; 166 | } 167 | } 168 | 169 | 170 | // do not consider a profile that does not have any protocols 171 | if (sdp_get_profile_descs(rec, &list) == 0) 172 | { 173 | sdp_list_foreach(list, _profile_desc, 0); 174 | sdp_list_free(list, free); 175 | } 176 | } 177 | 178 | if (bprofiles.size() && bprofiles.back().uuid.value.uuid16 == 0 && bprofiles.back().name.length() == 0) 179 | bprofiles.pop_back(); 180 | } 181 | 182 | 183 | static void _init() 184 | { 185 | pProfile = NULL; 186 | } 187 | 188 | 189 | static int _sdpscan(char* szbtaddr, uuid_t svc_uuid, vector &bprofiles) 190 | { 191 | int err; 192 | 193 | _init(); 194 | 195 | // BDADDR_ANY 196 | bdaddr_t add_any = {0,0,0,0,0,0}; 197 | 198 | // convert szbtaddr to bdaddr_t 199 | bdaddr_t target; 200 | str2ba(szbtaddr, &target); 201 | 202 | 203 | // sdp session connect 204 | sdp_session_t *session = NULL; 205 | session = sdp_connect(&add_any, &target, SDP_RETRY_IF_BUSY); 206 | if (!session) 207 | { 208 | printf("[-] error: sdp_connect() failed\n"); 209 | return -1; 210 | } 211 | 212 | uint32_t range = 0x0000ffff; 213 | sdp_list_t *response_list = NULL; 214 | sdp_list_t *search_list = sdp_list_append(NULL, &svc_uuid); 215 | sdp_list_t *attrid_list = sdp_list_append(NULL, &range); 216 | 217 | 218 | // search all contained services 219 | err = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list); 220 | if (err) 221 | { 222 | printf("[-] error: sdp_service_search_attr_req() failed\n"); 223 | sdp_close(session); 224 | return -1; 225 | } 226 | sdp_list_free(attrid_list, 0); 227 | sdp_list_free(search_list, 0); 228 | 229 | 230 | // traversal all trees 231 | sdp_list_t *next; 232 | for (; response_list; response_list = next) 233 | { 234 | sdp_record_t *rec = (sdp_record_t*)response_list->data; 235 | 236 | // set profile data 237 | _set_attr(rec, bprofiles); 238 | 239 | next = response_list->next; 240 | free(response_list); 241 | sdp_record_free(rec); 242 | } 243 | 244 | sdp_close(session); 245 | return 0; 246 | 247 | } 248 | 249 | 250 | int sdpscan(char* szbtaddr, vector &bprofiles) 251 | { 252 | uuid_t uuid; 253 | sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); 254 | int ret = _sdpscan(szbtaddr, uuid, bprofiles); 255 | 256 | prtSDP *psdp = new prtSDP(); 257 | psdp->name = "SDP"; 258 | bProfile bp; 259 | bp.name = "SDP"; 260 | bp.protocols.push_back(psdp); 261 | bprofiles.push_back(bp); 262 | 263 | for (int i = 0; i < bprofiles.size(); i++) 264 | { 265 | bprofiles[i].szbtaddr = szbtaddr; 266 | 267 | for(int j = 0; j < bprofiles[i].protocols.size(); j++) 268 | { 269 | bprofiles[i].protocols[j]->pProfile = &bprofiles[i]; 270 | } 271 | } 272 | 273 | //psdp->free(); 274 | 275 | return ret; 276 | } 277 | -------------------------------------------------------------------------------- /bdaddr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BlueZ - Bluetooth protocol stack for Linux 4 | * 5 | * Copyright (C) 2004-2005 Marcel Holtmann 6 | * 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License version 2 as 10 | * published by the Free Software Foundation; 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 15 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 16 | * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 | * 21 | * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 22 | * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 23 | * SOFTWARE IS DISCLAIMED. 24 | * 25 | * 26 | * $Id: bdaddr.c,v 1.3.2 2008/02/08 00:02:32 ^_^ Exp $ 27 | * $Id: bdaddr.c,v 1.1.1.1 2005/12/27 14:31:21 bytebeater Exp $ 28 | * $Id: bdaddr.c,v 1.3 2005/04/20 16:54:53 holtmann Exp $ 29 | */ 30 | 31 | #ifdef HAVE_CONFIG_H 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #define OCF_ERICSSON_WRITE_BD_ADDR 0x000d 48 | typedef struct { 49 | bdaddr_t bdaddr; 50 | } __attribute__ ((packed)) ericsson_write_bd_addr_cp; 51 | #define ERICSSON_WRITE_BD_ADDR_CP_SIZE 6 52 | 53 | static int ericsson_write_bd_addr(int dd, bdaddr_t *bdaddr) 54 | { 55 | struct hci_request rq; 56 | ericsson_write_bd_addr_cp cp; 57 | 58 | memset(&cp, 0, sizeof(cp)); 59 | bacpy(&cp.bdaddr, bdaddr); 60 | 61 | memset(&rq, 0, sizeof(rq)); 62 | rq.ogf = OGF_VENDOR_CMD; 63 | rq.ocf = OCF_ERICSSON_WRITE_BD_ADDR; 64 | rq.cparam = &cp; 65 | rq.clen = ERICSSON_WRITE_BD_ADDR_CP_SIZE; 66 | rq.rparam = NULL; 67 | rq.rlen = 0; 68 | 69 | if (hci_send_req(dd, &rq, 1000) < 0) 70 | return -1; 71 | 72 | return 0; 73 | } 74 | 75 | #if 0 76 | #define OCF_ERICSSON_STORE_IN_FLASH 0x0022 77 | typedef struct { 78 | uint8_t user_id; 79 | uint8_t flash_length; 80 | uint8_t flash_data[253]; 81 | } __attribute__ ((packed)) ericsson_store_in_flash_cp; 82 | #define ERICSSON_STORE_IN_FLASH_CP_SIZE 255 83 | 84 | static int ericsson_store_in_flash(int dd, uint8_t user_id, uint8_t flash_length, uint8_t *flash_data) 85 | { 86 | struct hci_request rq; 87 | ericsson_store_in_flash_cp cp; 88 | 89 | memset(&cp, 0, sizeof(cp)); 90 | cp.user_id = user_id; 91 | cp.flash_length = flash_length; 92 | if (flash_length > 0) 93 | memcpy(cp.flash_data, flash_data, flash_length); 94 | 95 | memset(&rq, 0, sizeof(rq)); 96 | rq.ogf = OGF_VENDOR_CMD; 97 | rq.ocf = OCF_ERICSSON_STORE_IN_FLASH; 98 | rq.cparam = &cp; 99 | rq.clen = ERICSSON_STORE_IN_FLASH_CP_SIZE; 100 | rq.rparam = NULL; 101 | rq.rlen = 0; 102 | 103 | if (hci_send_req(dd, &rq, 1000) < 0) 104 | return -1; 105 | 106 | return 0; 107 | } 108 | #endif 109 | 110 | static int csr_write_bd_addr(int dd, bdaddr_t *bdaddr) 111 | { 112 | unsigned char cmd[] = { 0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70, 113 | 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 114 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 115 | 116 | unsigned char cp[254], rp[254]; 117 | struct hci_request rq; 118 | 119 | cmd[16] = bdaddr->b[2]; 120 | cmd[17] = 0x00; 121 | cmd[18] = bdaddr->b[0]; 122 | cmd[19] = bdaddr->b[1]; 123 | cmd[20] = bdaddr->b[3]; 124 | cmd[21] = 0x00; 125 | cmd[22] = bdaddr->b[4]; 126 | cmd[23] = bdaddr->b[5]; 127 | 128 | memset(&cp, 0, sizeof(cp)); 129 | cp[0] = 0xc2; 130 | memcpy(cp + 1, cmd, sizeof(cmd)); 131 | 132 | memset(&rq, 0, sizeof(rq)); 133 | rq.ogf = OGF_VENDOR_CMD; 134 | rq.ocf = 0x00; 135 | rq.event = EVT_VENDOR; 136 | rq.cparam = cp; 137 | rq.clen = sizeof(cmd) + 1; 138 | rq.rparam = rp; 139 | rq.rlen = sizeof(rp); 140 | 141 | if (hci_send_req(dd, &rq, 2000) < 0) 142 | return -1; 143 | 144 | if (rp[0] != 0xc2) { 145 | errno = EIO; 146 | return -1; 147 | } 148 | 149 | if ((rp[9] + (rp[10] << 8)) != 0) { 150 | errno = ENXIO; 151 | return -1; 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | #define OCF_ZEEVO_WRITE_BD_ADDR 0x0001 158 | typedef struct { 159 | bdaddr_t bdaddr; 160 | } __attribute__ ((packed)) zeevo_write_bd_addr_cp; 161 | #define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6 162 | 163 | static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr) 164 | { 165 | struct hci_request rq; 166 | zeevo_write_bd_addr_cp cp; 167 | 168 | memset(&cp, 0, sizeof(cp)); 169 | bacpy(&cp.bdaddr, bdaddr); 170 | 171 | memset(&rq, 0, sizeof(rq)); 172 | rq.ogf = OGF_VENDOR_CMD; 173 | rq.ocf = OCF_ZEEVO_WRITE_BD_ADDR; 174 | rq.cparam = &cp; 175 | rq.clen = ZEEVO_WRITE_BD_ADDR_CP_SIZE; 176 | rq.rparam = NULL; 177 | rq.rlen = 0; 178 | 179 | if (hci_send_req(dd, &rq, 1000) < 0) 180 | return -1; 181 | 182 | return 0; 183 | } 184 | 185 | static struct { 186 | uint16_t compid; 187 | int (*func)(int dd, bdaddr_t *bdaddr); 188 | } vendor[] = { 189 | { 0, ericsson_write_bd_addr }, 190 | { 10, csr_write_bd_addr }, 191 | { 18, zeevo_write_bd_addr }, 192 | { 65535, NULL }, 193 | }; 194 | 195 | static void usage(void) 196 | { 197 | printf("bdaddr - Utility for changing the Bluetooth device address\n\n"); 198 | printf("Usage:\n" 199 | "\tbdaddr [-i ] [new bdaddr]\n"); 200 | } 201 | 202 | static struct option main_options[] = { 203 | { "help", 0, 0, 'h' }, 204 | { "device", 1, 0, 'i' }, 205 | { 0, 0, 0, 0 } 206 | }; 207 | 208 | int main(int argc, char *argv[]) 209 | { 210 | struct hci_dev_info di; 211 | struct hci_version ver; 212 | bdaddr_t bdaddr; 213 | char addr[18]; 214 | int i, dd, opt, dev = 0; 215 | bdaddr_t any = {0, 0, 0, 0, 0, 0}; 216 | 217 | bacpy(&bdaddr, &any); 218 | 219 | while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { 220 | switch (opt) { 221 | case 'i': 222 | dev = hci_devid(optarg); 223 | if (dev < 0) { 224 | perror("Invalid device"); 225 | exit(1); 226 | } 227 | break; 228 | 229 | case 'h': 230 | default: 231 | usage(); 232 | exit(0); 233 | } 234 | } 235 | 236 | argc -= optind; 237 | argv += optind; 238 | optind = 0; 239 | 240 | dd = hci_open_dev(dev); 241 | if (dd < 0) { 242 | fprintf(stderr, "Can't open device hci%d: %s (%d)\n", 243 | dev, strerror(errno), errno); 244 | exit(1); 245 | } 246 | 247 | if (hci_devinfo(dev, &di) < 0) { 248 | fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n", 249 | dev, strerror(errno), errno); 250 | hci_close_dev(dd); 251 | exit(1); 252 | } 253 | 254 | if (hci_read_local_version(dd, &ver, 1000) < 0) { 255 | printf("fuck"); 256 | fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n", 257 | dev, strerror(errno), errno); 258 | hci_close_dev(dd); 259 | exit(1); 260 | } 261 | 262 | if (!bacmp(&di.bdaddr, &any)) { 263 | if (hci_read_bd_addr(dd, &bdaddr, 1000) < 0) { 264 | fprintf(stderr, "Can't read address for hci%d: %s (%d)\n", 265 | dev, strerror(errno), errno); 266 | hci_close_dev(dd); 267 | exit(1); 268 | } 269 | } else 270 | bacpy(&bdaddr, &di.bdaddr); 271 | 272 | printf("Manufacturer: %s (%d)\n", 273 | bt_compidtostr(ver.manufacturer), ver.manufacturer); 274 | 275 | ba2str(&bdaddr, addr); 276 | printf("Device address: %s\n", addr); 277 | 278 | if (argc < 1) { 279 | hci_close_dev(dd); 280 | exit(0); 281 | } 282 | 283 | str2ba(argv[0], &bdaddr); 284 | if (!bacmp(&bdaddr, &any)) { 285 | hci_close_dev(dd); 286 | exit(0); 287 | } 288 | 289 | for (i = 0; vendor[i].compid != 65535; i++) 290 | if (ver.manufacturer == vendor[i].compid) { 291 | ba2str(&bdaddr, addr); 292 | printf("New BD address: %s\n\n", addr); 293 | 294 | if (vendor[i].func(dd, &bdaddr) < 0) { 295 | fprintf(stderr, "Can't write new address\n"); 296 | hci_close_dev(dd); 297 | exit(1); 298 | } 299 | 300 | printf("Address changed - Reset device now\n"); 301 | 302 | //ioctl(dd, HCIDEVRESET, dev); 303 | //ioctl(dd, HCIDEVDOWN, dev); 304 | //ioctl(dd, HCIDEVUP, dev); 305 | 306 | hci_close_dev(dd); 307 | exit(0); 308 | } 309 | /*else { 310 | printf("Warning! No verified support of bdaddr for specified device. Trying ericcson_write_bd_addr function as default.\n"); 311 | ba2str(&bdaddr, addr); 312 | printf("New BD address: %s\n\n", addr); 313 | if (vendor[0].func(dd, &bdaddr) < 0) { 314 | fprintf(stderr, "Can't write new address\n"); 315 | hci_close_dev(dd); 316 | exit(1); 317 | } 318 | 319 | printf("Address changed - Reset device now\n"); 320 | hci_close_dev(dd); 321 | exit(0); 322 | }*/ 323 | 324 | hci_close_dev(dd); 325 | 326 | printf("\n"); 327 | fprintf(stderr, "Unsupported manufacturer\n"); 328 | 329 | exit(1); 330 | } 331 | --------------------------------------------------------------------------------