Commit 54b10e6e authored by Devon Kearns's avatar Devon Kearns

Imported Upstream version 0.5.2

parents
v0.5.2
- Added -B flag to remove the banner. Easier to use on small screens.
v0.5.1
- Fixed bug in variable name "class" causing conflict name issues.
v0.5
- Fixed segmentation fault in manual assigning of Device Name and Class of Device
- Modified flags
- Depreciated
-r: Assign random NAME, CLASS, and ADDR
-l <log>: Load SpoofTooph CSV logfile
-d <log>: Dump scan into SpoofTooph CSV logfile
- New
-w <file>: Write to CSV file
-r <file>: Read from CSV file
-R: Assign random NAME, CLASS, and ADDR
-m: Specify multiple interfaces during selection
-u: USB delay. Interactive delay for reinitializing interfaces
v0.4.1 - 06/15/2011
- Took out some testing code
v0.4 - 03/24/2011
- Save file on exit.
- Fixed problem with saving log.
- Fixed problem with closing threads.
- Changed probes for device name. Scan runs much much faster now.
v0.3
- Fixed socket closing error
- Fixed log data verification for valid ADDR and CLASS
- Changed logging format to CSV: ADDR,CLASS,NAME
- Added -m flag for choosing multiple interfaces to use for cloning
(Useful to test Man-In-The-Middle attacks)
- Fixed the problem with reading in the Class from a log
- Fixed overflow problem with array of devices
- Fixed selection of Bluetooth interface from a always using
interface hci0
- Changed device array to dynmically resize
- Added -b flag for specifying the number of Bluetooth devices
to display per page
v0.1
- Initial release
spooftooph
Copyright (C) 2009-2011 Shadow Cave LLC
Written 2009-2011 by JP Dunning (.ronin)
ronin [ at ] shadowcave [dt] org
<www.hackfromacave.com>
License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS
DISCLAIMED.
ABOUT
Spooftooph is designed to automate spoofing or cloning Bluetooth device
Name, Class, and Address. See 'Usage' for more information of its capabilities.
INSTALL
1. Run "make" to compile binaries.
2. Run "make install" to install into system.
3. Run "make clean" to delete binaries from spooftooph directory.
RESOURCES
- BlueZ
- BlueZ-devel
- ncurses
- ncurses-devel
USAGE
To modify the Bluetooth adapter, spooftooth must be run with root privileges.
Spooftooph offers five modes of usage:
1) Specify NAME, CLASS and ADDR.
> spooftooph -i hci0 -n new_name -a 00:11:22:33:44:55 -c 0x1c010c
2) Randomly generate NAME, CLASS and ADDR.
> spooftooph -i hci0 -r
3) Scan for devices in range and select device to clone. Optionally dump the device
information in a specified log file.
> spooftooph -i hci0 -s -d file.log
4) Load in device info from log file and specify device info to clone.
> spooftooph -i hci0 -l file.log
5) Clone a random devices info in range every X seconds.
> spooftooph -i hci0 -t 10
HELP
NAME
spooftooph
SYNOPSIS
spooftooph -i dev [-m] [-sd] [-nac] [-r] [-l] [-t]
DESCRIPTION
-a <address> : Specify new ADDR
-b <num_lines> : Number of Bluetooth profiles to display per page
-c <class> : Specify new CLASS
-d <log> : Dump scan into log file
-h : Help
-i <dev> : Specify interface
-l <log> : Load a list of Bluetooth profiles to clone from saved log
-n <name> : Specify new NAME
-m : Specify multiple interfaces durring selection.
-r : Assign random NAME, CLASS, and ADDR
-s : Scan for devices in local area
-t <time> : Time interval to clone device in range
\ No newline at end of file
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
*
* Modified by JP Dunning (.ronin) 2010 <ronin [ at ] shadowcave [dt] org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include "oui.h"
static int transient = 0;
static int generic_reset_device(int dd)
{
bdaddr_t bdaddr;
int err;
err = hci_send_cmd(dd, 0x03, 0x0003, 0, NULL);
if (err < 0)
return err;
return hci_read_bd_addr(dd, &bdaddr, 10000);
}
#define OCF_ERICSSON_WRITE_BD_ADDR 0x000d
typedef struct {
bdaddr_t bdaddr;
} __attribute__ ((packed)) ericsson_write_bd_addr_cp;
#define ERICSSON_WRITE_BD_ADDR_CP_SIZE 6
static int ericsson_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
struct hci_request rq;
ericsson_write_bd_addr_cp cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, bdaddr);
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = OCF_ERICSSON_WRITE_BD_ADDR;
rq.cparam = &cp;
rq.clen = ERICSSON_WRITE_BD_ADDR_CP_SIZE;
rq.rparam = NULL;
rq.rlen = 0;
if (hci_send_req(dd, &rq, 1000) < 0)
return -1;
return 0;
}
#define OCF_ERICSSON_STORE_IN_FLASH 0x0022
typedef struct {
uint8_t user_id;
uint8_t flash_length;
uint8_t flash_data[253];
} __attribute__ ((packed)) ericsson_store_in_flash_cp;
#define ERICSSON_STORE_IN_FLASH_CP_SIZE 255
static int ericsson_store_in_flash(int dd, uint8_t user_id, uint8_t flash_length, uint8_t *flash_data)
{
struct hci_request rq;
ericsson_store_in_flash_cp cp;
memset(&cp, 0, sizeof(cp));
cp.user_id = user_id;
cp.flash_length = flash_length;
if (flash_length > 0)
memcpy(cp.flash_data, flash_data, flash_length);
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = OCF_ERICSSON_STORE_IN_FLASH;
rq.cparam = &cp;
rq.clen = ERICSSON_STORE_IN_FLASH_CP_SIZE;
rq.rparam = NULL;
rq.rlen = 0;
if (hci_send_req(dd, &rq, 1000) < 0)
return -1;
return 0;
}
static int csr_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
unsigned char cmd[] = { 0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70,
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char cp[254], rp[254];
struct hci_request rq;
if (transient)
cmd[14] = 0x08;
cmd[16] = bdaddr->b[2];
cmd[17] = 0x00;
cmd[18] = bdaddr->b[0];
cmd[19] = bdaddr->b[1];
cmd[20] = bdaddr->b[3];
cmd[21] = 0x00;
cmd[22] = bdaddr->b[4];
cmd[23] = bdaddr->b[5];
memset(&cp, 0, sizeof(cp));
cp[0] = 0xc2;
memcpy(cp + 1, cmd, sizeof(cmd));
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = 0x00;
rq.event = EVT_VENDOR;
rq.cparam = cp;
rq.clen = sizeof(cmd) + 1;
rq.rparam = rp;
rq.rlen = sizeof(rp);
if (hci_send_req(dd, &rq, 2000) < 0)
return -1;
if (rp[0] != 0xc2) {
errno = EIO;
return -1;
}
if ((rp[9] + (rp[10] << 8)) != 0) {
errno = ENXIO;
return -1;
}
return 0;
}
static int csr_reset_device(int dd)
{
unsigned char cmd[] = { 0x02, 0x00, 0x09, 0x00,
0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char cp[254], rp[254];
struct hci_request rq;
if (transient)
cmd[6] = 0x02;
memset(&cp, 0, sizeof(cp));
cp[0] = 0xc2;
memcpy(cp + 1, cmd, sizeof(cmd));
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = 0x00;
rq.event = EVT_VENDOR;
rq.cparam = cp;
rq.clen = sizeof(cmd) + 1;
rq.rparam = rp;
rq.rlen = sizeof(rp);
if (hci_send_req(dd, &rq, 2000) < 0)
return -1;
return 0;
}
#define OCF_TI_WRITE_BD_ADDR 0x0006
typedef struct {
bdaddr_t bdaddr;
} __attribute__ ((packed)) ti_write_bd_addr_cp;
#define TI_WRITE_BD_ADDR_CP_SIZE 6
static int ti_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
struct hci_request rq;
ti_write_bd_addr_cp cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, bdaddr);
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = OCF_TI_WRITE_BD_ADDR;
rq.cparam = &cp;
rq.clen = TI_WRITE_BD_ADDR_CP_SIZE;
rq.rparam = NULL;
rq.rlen = 0;
if (hci_send_req(dd, &rq, 1000) < 0)
return -1;
return 0;
}
#define OCF_BCM_WRITE_BD_ADDR 0x0001
typedef struct {
bdaddr_t bdaddr;
} __attribute__ ((packed)) bcm_write_bd_addr_cp;
#define BCM_WRITE_BD_ADDR_CP_SIZE 6
static int bcm_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
struct hci_request rq;
bcm_write_bd_addr_cp cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, bdaddr);
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = OCF_BCM_WRITE_BD_ADDR;
rq.cparam = &cp;
rq.clen = BCM_WRITE_BD_ADDR_CP_SIZE;
rq.rparam = NULL;
rq.rlen = 0;
if (hci_send_req(dd, &rq, 1000) < 0)
return -1;
return 0;
}
#define OCF_ZEEVO_WRITE_BD_ADDR 0x0001
typedef struct {
bdaddr_t bdaddr;
} __attribute__ ((packed)) zeevo_write_bd_addr_cp;
#define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6
static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
struct hci_request rq;
zeevo_write_bd_addr_cp cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, bdaddr);
memset(&rq, 0, sizeof(rq));
rq.ogf = OGF_VENDOR_CMD;
rq.ocf = OCF_ZEEVO_WRITE_BD_ADDR;
rq.cparam = &cp;
rq.clen = ZEEVO_WRITE_BD_ADDR_CP_SIZE;
rq.rparam = NULL;
rq.rlen = 0;
if (hci_send_req(dd, &rq, 1000) < 0)
return -1;
return 0;
}
static int st_write_bd_addr(int dd, bdaddr_t *bdaddr)
{
return ericsson_store_in_flash(dd, 0xfe, 6, (uint8_t *) bdaddr);
}
static struct {
uint16_t compid;
int (*write_bd_addr)(int dd, bdaddr_t *bdaddr);
int (*reset_device)(int dd);
} vendor[] = {
{ 0, ericsson_write_bd_addr, NULL },
{ 10, csr_write_bd_addr, csr_reset_device },
{ 13, ti_write_bd_addr, NULL },
{ 15, bcm_write_bd_addr, generic_reset_device },
{ 18, zeevo_write_bd_addr, NULL },
{ 48, st_write_bd_addr, generic_reset_device },
{ 57, ericsson_write_bd_addr, generic_reset_device },
{ 65535, NULL, NULL },
};
/*static void usage(void)
{
printf("bdaddr - Utility for changing the Bluetooth device address\n\n");
printf("Usage:\n"
"\tbdaddr [-i <dev>] [-r] [-t] [new bdaddr]\n");
}
*/
static struct option main_options[] = {
{ "device", 1, 0, 'i' },
{ "reset", 0, 0, 'r' },
{ "transient", 0, 0, 't' },
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};
/* Modifide by JP Dunning (.ronin)
*
* All modifications to btaddr.c are made in the following function.
* Modification were made to allow the functionality in the following
* function to be called from another application.
*/
static int cmd_bdaddr(int dev, char * new_addr)
//int main(int argc, char **argv)
{
struct hci_dev_info di;
struct hci_version ver;
bdaddr_t bdaddr;
char addr[18], oui[9], *comp;
int i, dd, opt, reset = 1;
bacpy(&bdaddr, BDADDR_ANY);
optind = 0;
dd = hci_open_dev(dev);
if (dd < 0) {
fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
dev, strerror(errno), errno);
return(1);
}
if (hci_devinfo(dev, &di) < 0) {
fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",
dev, strerror(errno), errno);
hci_close_dev(dd);
return(1);
}
if (hci_read_local_version(dd, &ver, 1000) < 0) {
fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
dev, strerror(errno), errno);
hci_close_dev(dd);
return(1);
}
if (!bacmp(&di.bdaddr, BDADDR_ANY)) {
if (hci_read_bd_addr(dd, &bdaddr, 1000) < 0) {
fprintf(stderr, "Can't read address for hci%d: %s (%d)\n",
dev, strerror(errno), errno);
hci_close_dev(dd);
return(1);
}
} else
bacpy(&bdaddr, &di.bdaddr);
printf("Manufacturer: %s (%d)\n",
bt_compidtostr(ver.manufacturer), ver.manufacturer);
ba2oui(&bdaddr, oui);
comp = ouitocomp(oui);
ba2str(&bdaddr, addr);
printf("Device address: %s", addr);
if (comp) {
printf(" (%s)\n", comp);
free(comp);
} else
printf("\n");
/* if (argc < 1) {
hci_close_dev(dd);
return(0);
}
*/
str2ba(new_addr, &bdaddr);
if (!bacmp(&bdaddr, BDADDR_ANY)) {
hci_close_dev(dd);
return(0);
}
for (i = 0; vendor[i].compid != 65535; i++)
if (ver.manufacturer == vendor[i].compid) {
ba2oui(&bdaddr, oui);
comp = ouitocomp(oui);
ba2str(&bdaddr, addr);
printf("New BD address: %s", addr);
if (comp) {
printf(" (%s)\n\n", comp);
free(comp);
} else
printf("\n\n");
if (vendor[i].write_bd_addr(dd, &bdaddr) < 0) {
fprintf(stderr, "Can't write new address\n");
hci_close_dev(dd);
return(1);
}
printf("Address changed\n");
if (reset && vendor[i].reset_device) {
if (vendor[i].reset_device(dd) < 0) {
// printf("Reset device manually\n");
} else {
ioctl(dd, HCIDEVRESET, dev);
printf("Device reset successully\n");
}
} else {
printf("Reset device now\n");
}
//ioctl(dd, HCIDEVRESET, dev);
//ioctl(dd, HCIDEVDOWN, dev);
//ioctl(dd, HCIDEVUP, dev);
hci_close_dev(dd);
return(0);
}
hci_close_dev(dd);
printf("\n");
fprintf(stderr, "Unsupported manufacturer\n");
return(1);
}
/*
SpoofTooph
Copyright (C) 2010 Shadow Cave LLC
Written 2010 by JP Dunning (.ronin)
ronin@shadowcave.org
<www.hackfromacave.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS
DISCLAIMED.
*/
#define LENGTH_NAME 249
#define LENGTH_ADDR 18
#define LENGTH_CLASS 9
struct btdev {
char name[LENGTH_NAME];
char addr[LENGTH_ADDR];
char cod[LENGTH_CLASS];
int flags;
int major_class;
int minor_class;
uint8_t pscan_rep_mode;
uint8_t pscan_mode;
uint8_t clock_offset;
};
/*
SpoofTooph
Copyright (C) 2010 Shadow Cave LLC
Written 2010 by JP Dunning (.ronin)
ronin [ at ] shadowcave [dt] org
<www.hackfromacave.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS
DISCLAIMED.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
/*
* A majority of the following code is from 'hciconfig.c'
*/
static char * get_minor_device_name(int major, int minor)
{
switch (major) {
case 0: /* misc */
return "";
case 1: /* computer */
switch(minor) {
case 0:
return "Uncategorized";
case 1:
return "Desktop workstation";
case 2:
return "Server";
case 3:
return "Laptop";
case 4:
return "Handheld";
case 5:
return "Palm";
case 6:
return "Wearable";
}
break;
case 2: /* phone */
switch(minor) {
case 0:
return "Uncategorized";
case 1:
return "Cellular";
case 2:
return "Cordless";
case 3:
return "Smart phone";
case 4:
return "Wired modem / voice gateway";
case 5:
return "Common ISDN Access";
case 6:
return "Sim Card Reader";
}
break;
case 3: /* lan access */
if (minor == 0)
return "Uncategorized";
switch(minor / 8) {
case 0:
return "Fully available";
case 1:
return "1-17% utilized";
case 2:
return "17-33% utilized";
case 3:
return "33-50% utilized";
case 4:
return "50-67% utilized";
case 5:
return "67-83% utilized";
case 6:
return "83-99% utilized";
case 7:
return "No service available";
}
break;
case 4: /* audio/video */
switch(minor) {
case 0:
return "Uncategorized";
case 1:
return "Headset profile";
case 2:
return "Hands-free";
/* 3 is reserved */
case 4:
return "Microphone";
case 5:
return "Loudspeaker";
case 6:
return "Headphones";
case 7:
return "Portable Audio";
case 8:
return "Car Audio";
case 9:
return "Set-top box";
case 10:
return "HiFi Audio Device";
case 11:
return "VCR";
case 12:
return "Video Camera";
case 13:
return "Camcorder";