Skip to content

Instantly share code, notes, and snippets.

@Alkenso
Created April 29, 2020 18:38
Show Gist options
  • Select an option

  • Save Alkenso/ff68c496eba2e3c70dd15eb4333a1c22 to your computer and use it in GitHub Desktop.

Select an option

Save Alkenso/ff68c496eba2e3c70dd15eb4333a1c22 to your computer and use it in GitHub Desktop.
Observe KEXT: kern_event
// Common code
// used in both client and kernel parts.
// Common.h
enum TestKEXTEventType
{
TestKextEventStart = 1,
TestKextEventStop = 2
};
const char* TestKEXTBundleIdentifier = "com.alkenso.TestKext";
========================================================================================
// Client side
#include "Common.h"
#include <sys/socket.h>
#include <sys/kern_event.h>
#include <sys/ioctl.h>
int main(int argc, const char * argv[])
{
//create system socket to receive kernel event data
const int systemSocket = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
// receive vendor code
struct kev_vendor_code vendorCode = {};
strncpy(vendorCode.vendor_string, TestKEXTBundleIdentifier, KEV_VENDOR_CODE_MAX_STR_LEN);
ioctl(systemSocket, SIOCGKEVVENDOR, &vendorCode);
// prepare kernel request and set filtering options
struct kev_request kevRequest = {};
kevRequest.vendor_code = vendorCode.vendor_code;
kevRequest.kev_class = KEV_ANY_CLASS;
kevRequest.kev_subclass = KEV_ANY_SUBCLASS;
ioctl(systemSocket, SIOCSKEVFILT, &kevRequest);
// process events from desired kext
while (YES)
{
uint8_t buffer[KEV_RECVSPACE] = {};
const ssize_t bytesReceived = recv(systemSocket, &buffer, sizeof(buffer), 0);
if (bytesReceived < 0)
{
return 1;
}
const kern_event_msg* kextMsg = (const kern_event_msg*)buffer;
// Though in kernel-mode the data was inserted into various kev_d_vectors structures, in user-mode event_data points to a continuous buffer of the data.
switch (kextMsg->event_code)
{
case TestKextEventStart:
NSLog(@"Kext started: %s", (const char*)&kextMsg->event_data[0]);
break;
case TestKextEventStop:
NSLog(@"Kext started: %s", (const char*)&kextMsg->event_data[0]);
break;
default:
break;
}
}
[[NSRunLoop mainRunLoop] run];
return 0;
}
========================================================================================
// KEXT side
#include "Common.h"
#include <mach/mach_types.h>
#include <libkern/libkern.h>
#include <sys/types.h>
#include <sys/kern_event.h>
kern_return_t TestKext_start(kmod_info_t * ki, void *d);
kern_return_t TestKext_stop(kmod_info_t *ki, void *d);
kern_return_t TestKext_start(kmod_info_t * ki, void *d)
{
u_int32_t kextVendorID = 0;
// find vendor ID
if (kev_vendor_code_find(TestKEXTBundleIdentifier, &kextVendorID) != 0)
{
return KERN_FAILURE;
}
// prepare kernel event message
struct kev_msg kEventMsg = {};
kEventMsg.vendor_code = kextVendorID;
kEventMsg.kev_class = KEV_ANY_CLASS;
kEventMsg.kev_subclass = KEV_ANY_SUBCLASS;
kEventMsg.event_code = TestKextEventStart;
char message[] = "Hello kernel!";
kEventMsg.dv[0].data_length = strlen(message) + 1;
kEventMsg.dv[0].data_ptr = message;
// broadcast msg to user-mode
if (kev_msg_post(&kEventMsg) != 0 )
{
return KERN_FAILURE;
}
return KERN_SUCCESS;
}
kern_return_t TestKext_stop(kmod_info_t *ki, void *d)
{
u_int32_t kextVendorID = 0;
//find vendor ID
if (kev_vendor_code_find(TestKEXTBundleIdentifier, &kextVendorID) != 0)
{
return KERN_FAILURE;
}
//kernel event message
struct kev_msg kEventMsg = {};
kEventMsg.vendor_code = kextVendorID;
kEventMsg.kev_class = KEV_ANY_CLASS;
kEventMsg.kev_subclass = KEV_ANY_SUBCLASS;
kEventMsg.event_code = TestKextEventStop;
char message[] = "Bye kernel =(";
kEventMsg.dv[0].data_length = strlen(message) + 1;
kEventMsg.dv[0].data_ptr = message;
//broadcast msg to user-mode
if (kev_msg_post(&kEventMsg) != 0 )
{
return KERN_FAILURE;
}
return KERN_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment