Created
April 29, 2020 18:38
-
-
Save Alkenso/ff68c496eba2e3c70dd15eb4333a1c22 to your computer and use it in GitHub Desktop.
Observe KEXT: kern_event
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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