Hi! I was wondering if we could use osquery to ext...
# macos
r
Hi! I was wondering if we could use osquery to extrat the output from a tool like this one: https://github.com/todbot/mac-hid-dump/blob/main/mac-hid-dump.c to extract descriptors from connected usb devices.
Code is
Copy code
/* 
 * mac-hid-dump -- Dump HID Report Descriptors on MacOS
 *                 Sort of a MacOS version of `usbhid-dump`
 *
 * Borrows heavily from libusb/hidapi/mac/hid.c
 *
 * 2021, Tod Kurt, <mailto:tod@todbot.com|tod@todbot.com>
 */

#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>

static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
{
	CFTypeRef ref;
	int32_t value;

	ref = IOHIDDeviceGetProperty(device, key);
	if (ref) {
		if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
			CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
			return value;
		}
	}
	return 0;
}

static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
{
	CFStringRef str;

	if (!len)
		return 0;

	str = (CFStringRef) IOHIDDeviceGetProperty(device, prop);

	buf[0] = 0;

	if (str) {
		CFIndex str_len = CFStringGetLength(str);
		CFRange range;
		CFIndex used_buf_len;
		CFIndex chars_copied;

		len --;

		range.location = 0;
		range.length = ((size_t) str_len > len)? len: (size_t) str_len;
		chars_copied = CFStringGetBytes(str,
			range,
			kCFStringEncodingUTF32LE,
			(char) '?',
			FALSE,
			(UInt8*)buf,
			len * sizeof(wchar_t),
			&used_buf_len);

		if (chars_copied <= 0)
			buf[0] = 0;
		else
			buf[chars_copied] = 0;

		return 0;
	}
	else
		return -1;
}

static unsigned short get_vendor_id(IOHIDDeviceRef device)
{
	return get_int_property(device, CFSTR(kIOHIDVendorIDKey));
}

static unsigned short get_product_id(IOHIDDeviceRef device)
{
	return get_int_property(device, CFSTR(kIOHIDProductIDKey));
}

static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
{
	return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
}

static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
{
	return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len);
}

static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
{
	return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len);
}

int main(void)
{    
	IOHIDManagerRef mgr;
    int i;
    
	mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
	IOHIDManagerSetDeviceMatching(mgr, NULL);
	IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);

	CFSetRef device_set = IOHIDManagerCopyDevices(mgr);

	CFIndex num_devices = CFSetGetCount(device_set);
	IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
	CFSetGetValues(device_set, (const void **) device_array);

    //printf("got %ld devices\n", num_devices);
    printf("mac-hid-dump:\n");
    
	for (i = 0; i < num_devices; i++) {
		IOHIDDeviceRef dev = device_array[i];
		wchar_t str1[256], str2[256];

        get_manufacturer_string( dev, str1, sizeof(str1) );
        get_product_string( dev, str2, sizeof(str2) );
        printf("%04hX %04hX: %ls - %ls\n",
               get_vendor_id(dev), get_product_id(dev), str1, str2);

        CFDataRef cfprop = (CFDataRef)IOHIDDeviceGetProperty(dev,
                                                             CFSTR(kIOHIDReportDescriptorKey));
        printf("DESCRIPTOR:\n  ");
        uint8_t pbuf[1024];
        if( cfprop != NULL) {
            long len = CFDataGetLength(cfprop);
            CFDataGetBytes( cfprop, CFRangeMake(0,len), pbuf);
            for( int i=0; i< len; i++) {
                printf("%02x ", pbuf[i]);
                printf( (i % 16 == 15) ? "\n  " : " ");
            }
            printf("\n  (%ld bytes)\n", len);
        }
    }

	return 0;
}
f
you haven't mentioned if you tried the native tabledyet or what info is missing if so, but in case you weren't aware of it => https://osquery.io/schema/5.14.1#usb_devices
r
Sorry, I did, but the output is not providing the HID dump I'd like to get
f
ah gotcha. i haven't used this tool but in general, if you are using vanilla osquery, by design it can't readily "read" files, a workaround is to automate the running of a tool like this, and put the output into a plist file, osquery can parse plists out of the box. If you are using an orchestration service, or something premium like fleet, there are ways that they allow for more arbitrary access to a host like running scripts etc.
another option, again if you can control the execution and output of your tool by other means, is to dump the data as a sqlite table, and you can use this built-in function to read it out: https://blog.1password.com/build-custom-osquery-tables-using-atc/