├── .gitignore ├── Common ├── SignalHandler.hpp ├── SignalHandler.mm ├── Tools │ ├── Tools-ES.hpp │ ├── Tools-ES.mm │ ├── Tools.hpp │ └── Tools.mm └── logger.hpp ├── README.md └── demos ├── DTrace demo └── demo.d ├── DiskArbitration demo ├── DiskArbitration demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── DiskArbitration demo.xcscheme └── DiskArbitration demo │ └── main.cpp ├── ESF demo ├── ESF demo.entitlements ├── ESF demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── ESF demo.xcscheme ├── ESF demo │ ├── Makefile │ └── main.mm └── sign.sh ├── FSEvents demo ├── FSEvents demo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ ├── FSEvents-API demo.xcscheme │ │ └── FSEvents-dev demo.xcscheme └── FSEvents demo │ ├── FSEvents-API.cpp │ ├── FSEvents-dev.cpp │ └── fsevents.h ├── IDP-dema.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ ├── WorkspaceSettings.xcsettings │ └── xcschemes │ └── Build all.xcscheme ├── IOKit demo ├── IOKit demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── IOKit demo.xcscheme └── IOKit demo │ └── main.cpp ├── IOKit-driver demo ├── IOKit-driver demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── IOKit-driver demo.xcscheme └── IOKit-driver demo │ ├── IOKit_driver_demo.cpp │ ├── IOKit_driver_demo.hpp │ └── Info.plist ├── OpenBSM demo ├── OpenBSM demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── OpenBSM demo.xcscheme └── OpenBSM demo │ └── main.cpp ├── dev-blocker demo ├── Makefile └── test.c ├── dext demo ├── dext demo.xcodeproj │ └── project.pbxproj └── dext demo │ ├── Info.plist │ ├── dext_demo.cpp │ ├── dext_demo.entitlements │ └── dext_demo.iig ├── generic-kext demo ├── generic-kext demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── generic-kext demo.xcscheme └── generic-kext demo │ ├── Info.plist │ └── generic_kext_demo.c ├── kauth demo ├── kauth demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── kauth demo.xcscheme └── kauth demo │ ├── Info.plist │ └── kauth_demo.c ├── kdebug demo ├── kdebug demo.xcodeproj │ └── project.pbxproj └── kdebug demo │ ├── Makefile │ └── kdebug.c ├── kevent demo ├── kevent demo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── kevent demo.xcscheme └── kevent demo │ └── main.cpp └── macf demo ├── macf demo.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── macf demo.xcscheme └── macf demo ├── Info.plist └── macf_demo.c /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata 2 | DerivedData 3 | .o 4 | demos/ESF demo/ESF demo/ESF-demo 5 | demos/ESF demo/ESF demo/obj/ 6 | -------------------------------------------------------------------------------- /Common/SignalHandler.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // SignalHandler.hpp 3 | // 4 | // 5 | // Created by Jozef on 11/05/2020. 6 | // 7 | 8 | #ifndef SignalHandler_hpp 9 | #define SignalHandler_hpp 10 | 11 | #include 12 | 13 | void HandleSignalFromRunLoop(CFFileDescriptorRef f, CFOptionFlags callBackTypes, void *info); 14 | void InstallHandleSignalFromRunLoop(); 15 | 16 | #endif /* SignalHandler_hpp */ 17 | -------------------------------------------------------------------------------- /Common/SignalHandler.mm: -------------------------------------------------------------------------------- 1 | // 2 | // SignalHandler.cpp 3 | // 4 | // 5 | // Created by Jozef on 11/05/2020. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "logger.hpp" 14 | #include "SignalHandler.hpp" 15 | 16 | // Source: https://github.com/HelmutJ/CocoaSampleCode/blob/master/PreLoginAgents/PreLoginAgentCarbon/main.c & Mark Dalrymple, Advanced Mac OS X Programming: The Big Nerd Ranch Guide 17 | void HandleSignalFromRunLoop(CFFileDescriptorRef f, CFOptionFlags callBackTypes, void *info); 18 | // forward declaration 19 | 20 | void InstallHandleSignalFromRunLoop() 21 | // This routine installs HandleSIGTERMFromRunLoop as a SIGTERM handler. 22 | // The wrinkle is, HandleSIGTERMFromRunLoop is called from the runloop rather 23 | // than as a signal handler. This means that HandleSIGTERMFromRunLoop is not 24 | // limited to calling just the miniscule set of system calls that are safe 25 | // from a signal handler. 26 | // 27 | // This routine leaks lots of stuff. You're only expected to call it once, 28 | // from the main thread of your program. 29 | { 30 | // Ignore signals. Even though we've ignored the signal, the kqueue will 31 | // still see it. 32 | const std::vector signalsToWatch = {SIGINT, SIGABRT, SIGTERM}; 33 | // For SIGSEGV see 34 | // https://stackoverflow.com/questions/16204271/about-catching-the-sigsegv-in-multithreaded-environment 35 | // https://stackoverflow.com/questions/6533373/is-sigsegv-delivered-to-each-thread/6533431#6533431 36 | // https://stackoverflow.com/questions/20304720/catching-signals-such-as-sigsegv-and-sigfpe-in-multithreaded-program 37 | sig_t sigErr; 38 | for (const auto &signum : signalsToWatch) 39 | { 40 | sigErr = signal(signum, SIG_IGN); 41 | assert(sigErr != SIG_ERR); 42 | } 43 | sigErr = signal(SIGPIPE, SIG_IGN); 44 | assert(sigErr != SIG_ERR); 45 | 46 | // Create a kqueue and configure it to listen for the selected signals. 47 | int kq = kqueue(); 48 | assert(kq >= 0); 49 | 50 | // Use the new-in-10.5 EV_RECEIPT flag to ensure that we get what we expect. 51 | for (const auto &signum : signalsToWatch) 52 | { 53 | struct kevent sigevent; 54 | EV_SET(&sigevent, signum, EVFILT_SIGNAL, EV_ADD | EV_RECEIPT, 0, 0, NULL); 55 | int changeCount = kevent(kq, &sigevent, 1, &sigevent, 1, NULL); 56 | assert(changeCount == 1); // check that we get an event back 57 | assert(sigevent.flags & EV_ERROR); // and that it contains error information 58 | assert(sigevent.data == 0); // with no error 59 | } 60 | 61 | // Wrap the kqueue in a CFFileDescriptor (new in Mac OS X 10.5!). Then 62 | // create a run-loop source from the CFFileDescriptor and add that to the 63 | // runloop. 64 | static const CFFileDescriptorContext kContext = { 0, NULL, NULL, NULL, NULL }; 65 | CFFileDescriptorRef kqRef = CFFileDescriptorCreate(NULL, kq, true, HandleSignalFromRunLoop, &kContext); 66 | assert(kqRef != NULL); 67 | 68 | CFRunLoopSourceRef kqSource = CFFileDescriptorCreateRunLoopSource(NULL, kqRef, 0); 69 | assert(kqSource != NULL); 70 | 71 | CFRunLoopAddSource(CFRunLoopGetCurrent(), kqSource, kCFRunLoopDefaultMode); 72 | 73 | CFFileDescriptorEnableCallBacks(kqRef, kCFFileDescriptorReadCallBack); 74 | 75 | // Clean up. We can release kqSource and kqRef because they're all being 76 | // kept live by the fact that the kqSource is added to the runloop. We 77 | // must not close kq because file descriptors are not reference counted 78 | // and kqRef now 'owns' this descriptor. 79 | CFRelease(kqSource); 80 | CFRelease(kqRef); 81 | } 82 | 83 | void HandleSignalFromRunLoop(CFFileDescriptorRef f, CFOptionFlags callBackTypes, void *info) 84 | // Called from the runloop when the process receives a SIGTERM. We log 85 | // this occurence (which is safe to do because we're not in an actual signal 86 | // handler, courtesy of the 'magic' in InstallHandleSIGTERMFromRunLoop) 87 | // and then tell the app to quit. 88 | { 89 | #pragma unused(f) 90 | #pragma unused(callBackTypes) 91 | #pragma unused(info) 92 | 93 | Logger::getInstance().log(LogLevel::INFO, "(☞゚ヮ゚)☞ Interrupt signal () received, exiting ฅ^•ﻌ•^ฅ."); 94 | CFRunLoopStop(CFRunLoopGetCurrent()); 95 | } 96 | -------------------------------------------------------------------------------- /Common/Tools/Tools-ES.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Tools-ES.hpp 3 | // 4 | // 5 | // Created by Jozef on 18/05/2020. 6 | // 7 | 8 | #ifndef Tools_ES_hpp 9 | #define Tools_ES_hpp 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | extern const std::map g_eventTypeToStrMap; 17 | extern const std::map g_respondResultToStrMap; 18 | 19 | // MARK: - Custom Casts 20 | @interface NSString (alternativeConstructorsEs) 21 | + (NSString*)stringFromEsString:(es_string_token_t const &)esString; 22 | @end 23 | 24 | std::string to_string(const es_string_token_t &esString); 25 | std::vector paths_from_event(const es_message_t * const msg); 26 | std::any getDefaultESResponse(const es_message_t * const msg); 27 | 28 | // MARK: - Endpoint Security Logging 29 | // MARK: Process Events 30 | std::ostream & operator << (std::ostream &out, const es_event_exec_t &event); 31 | std::ostream & operator << (std::ostream &out, const es_event_exit_t &event); 32 | std::ostream & operator << (std::ostream &out, const es_event_fork_t &event); 33 | // MARK: File System Events 34 | std::ostream & operator << (std::ostream &out, const es_event_access_t &event); 35 | std::ostream & operator << (std::ostream &out, const es_event_clone_t &event); 36 | std::ostream & operator << (std::ostream &out, const es_event_close_t &event); 37 | std::ostream & operator << (std::ostream &out, const es_event_create_t &event); 38 | std::ostream & operator << (std::ostream &out, const es_event_file_provider_materialize_t &event); 39 | std::ostream & operator << (std::ostream &out, const es_event_file_provider_update_t &event); 40 | std::ostream & operator << (std::ostream &out, const es_event_exchangedata_t &event); 41 | std::ostream & operator << (std::ostream &out, const es_event_link_t &event); 42 | std::ostream & operator << (std::ostream &out, const es_event_mount_t &event); 43 | std::ostream & operator << (std::ostream &out, const es_event_open_t &event); 44 | std::ostream & operator << (std::ostream &out, const es_event_readdir_t &event); 45 | std::ostream & operator << (std::ostream &out, const es_event_readlink_t &event); 46 | std::ostream & operator << (std::ostream &out, const es_event_rename_t &event); 47 | std::ostream & operator << (std::ostream &out, const es_event_truncate_t &event); 48 | std::ostream & operator << (std::ostream &out, const es_event_unlink_t &event); 49 | std::ostream & operator << (std::ostream &out, const es_event_unmount_t &event); 50 | std::ostream & operator << (std::ostream &out, const es_event_write_t &event); 51 | // MARK: System Events 52 | std::ostream & operator << (std::ostream &out, const es_event_iokit_open_t &event); 53 | std::ostream & operator << (std::ostream &out, const es_event_kextload_t &event); 54 | std::ostream & operator << (std::ostream &out, const es_event_kextunload_t &event); 55 | // MARK: ES Types 56 | std::ostream & operator << (std::ostream &out, const es_message_t * const msg); 57 | std::ostream & operator << (std::ostream &out, const es_string_token_t &esString); 58 | std::ostream & operator << (std::ostream &out, const es_file_t * const file); 59 | std::ostream & operator << (std::ostream &out, const es_statfs_t * const stats); 60 | std::ostream & operator << (std::ostream &out, const es_process_t * const proc); 61 | 62 | #endif /* Tools_ES_hpp */ 63 | -------------------------------------------------------------------------------- /Common/Tools/Tools.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Tools.hpp 3 | // 4 | // 5 | // Created by Jozef on 18/05/2020. 6 | // 7 | 8 | #ifndef Tools_hpp 9 | #define Tools_hpp 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // MARK: - Custom Casts 16 | @interface NSString (alternativeConstructorsCpp) 17 | + (NSString*)stringFromCppString:(std::string const &)cppString; 18 | - (std::string)cppString; 19 | @end 20 | 21 | std::string to_string(const NSString *nsString); 22 | 23 | uint64_t mach_time_to_msecs(uint64_t mach_time); 24 | uint64_t msecs_to_mach_time(uint64_t ms); 25 | std::string convert_to_time_and_date(std::chrono::time_point time); 26 | std::string current_time_and_date(); 27 | char *esfflagstostr(uint32_t flags); 28 | char *csflagstostr(uint32_t flags); 29 | std::string faflagstostr(uint32_t flags); 30 | 31 | 32 | // TODO: demagler 33 | // https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html 34 | template 35 | constexpr std::string_view type_name() 36 | { 37 | std::string_view name, prefix, suffix; 38 | #ifdef __clang__ 39 | name = __PRETTY_FUNCTION__; 40 | prefix = "std::string_view type_name() [T = "; 41 | suffix = "]"; 42 | #elif defined(__GNUC__) 43 | name = __PRETTY_FUNCTION__; 44 | prefix = "constexpr std::string_view type_name() [with T = "; 45 | suffix = "; std::string_view = std::basic_string_view]"; 46 | #elif defined(_MSC_VER) 47 | name = __FUNCSIG__; 48 | prefix = "class std::basic_string_view > __cdecl type_name<"; 49 | suffix = ">(void)"; 50 | #endif 51 | name.remove_prefix(prefix.size()); 52 | name.remove_suffix(suffix.size()); 53 | return name; 54 | } 55 | 56 | #endif /* Tools_hpp */ 57 | -------------------------------------------------------------------------------- /Common/Tools/Tools.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Tools.mm 3 | // 4 | // 5 | // Created by Jozef on 18/05/2020. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Tools.hpp" 18 | 19 | // MARK: - Custom Casts 20 | @implementation NSString (alternativeConstructorsCpp) 21 | 22 | +(NSString*)stringFromCppString:(std::string const &)cppString 23 | { 24 | return [[NSString alloc] initWithCString:cppString.c_str() encoding:NSStringEncodingConversionAllowLossy]; 25 | } 26 | 27 | -(std::string)cppString 28 | { 29 | return std::string([self cStringUsingEncoding:NSStringEncodingConversionAllowLossy]); 30 | } 31 | 32 | @end 33 | 34 | std::string to_string(const NSString *nsString) 35 | { 36 | return std::string([nsString cStringUsingEncoding:NSStringEncodingConversionAllowLossy]); 37 | } 38 | 39 | 40 | // https://gist.github.com/leiless/de908154e4c1952186069fe330680b70 41 | uint64_t mach_time_to_msecs(uint64_t mach_time) 42 | { 43 | mach_timebase_info_data_t tb; 44 | kern_return_t e = mach_timebase_info(&tb); 45 | if (e != KERN_SUCCESS) 46 | throw std::invalid_argument("Could not convert mach time to msecs!"); 47 | return (mach_time * tb.numer) / (tb.denom * NSEC_PER_MSEC); 48 | } 49 | 50 | uint64_t msecs_to_mach_time(uint64_t ms) 51 | { 52 | mach_timebase_info_data_t tb; 53 | kern_return_t e = mach_timebase_info(&tb); 54 | if (e != KERN_SUCCESS) 55 | throw std::invalid_argument("Could not convert mach time to msecs!"); 56 | return (ms * tb.denom * NSEC_PER_MSEC) / tb.numer; 57 | } 58 | 59 | //https://stackoverflow.com/questions/17223096/outputting-date-and-time-in-c-using-stdchrono 60 | std::string convert_to_time_and_date(std::chrono::time_point time) 61 | { 62 | auto in_time_t = std::chrono::system_clock::to_time_t(time); 63 | 64 | std::stringstream ss; 65 | ss << std::put_time(std::localtime(&in_time_t), "%Y%m%d%H%M%S"); 66 | return ss.str(); 67 | } 68 | 69 | std::string current_time_and_date() 70 | { 71 | auto now = std::chrono::system_clock::now(); 72 | return convert_to_time_and_date(now); 73 | } 74 | 75 | 76 | #define longestesfflaglen 11 77 | static struct { 78 | char name[longestesfflaglen + 1]; 79 | uint32_t flag; 80 | } const esmapping[] = { 81 | { "FREAD", FREAD }, 82 | { "FWRITE", FWRITE }, 83 | { "FAPPEND", FAPPEND }, 84 | { "FASYNC", FASYNC }, 85 | { "FFSYNC", FFSYNC }, 86 | { "FFDSYNC", FFDSYNC }, 87 | { "FNONBLOCK", FNONBLOCK }, 88 | { "FNDELAY", FNDELAY }, 89 | { "O_NDELAY", O_NDELAY }, 90 | { "O_SHLOCK", O_SHLOCK }, 91 | { "O_EXLOCK", O_EXLOCK }, 92 | { "O_NOFOLLOW", O_NOFOLLOW }, 93 | { "O_CREAT", O_CREAT }, 94 | { "O_TRUNC", O_TRUNC }, 95 | { "O_EXCL", O_EXCL }, 96 | { "O_DIRECTORY", O_DIRECTORY }, 97 | { "O_SYMLINK", O_SYMLINK }, 98 | }; 99 | #define nesmappings (sizeof(esmapping) / sizeof(esmapping[0])) 100 | 101 | // Based on freebsd/lib/libc/gen/strtofflags.c 102 | char *esfflagstostr(uint32_t flags) 103 | { 104 | char *string; 105 | const char *sp; 106 | char *dp; 107 | uint32_t setflags; 108 | u_int i; 109 | 110 | if ((string = (char *)malloc(nesmappings * (longestesfflaglen + 1))) == NULL) 111 | return (NULL); 112 | 113 | setflags = flags; 114 | dp = string; 115 | for (i = 0; i < nesmappings; i++) { 116 | if (setflags & esmapping[i].flag) { 117 | if (dp > string) 118 | *dp++ = ','; 119 | for (sp = esmapping[i].name; *sp; *dp++ = *sp++) ; 120 | setflags &= ~esmapping[i].flag; 121 | } 122 | } 123 | *dp = '\0'; 124 | return (string); 125 | } 126 | 127 | 128 | #define longestcsflaglen 25 129 | static struct { 130 | char name[longestcsflaglen + 1]; 131 | uint32_t flag; 132 | } const csmapping[] = { 133 | { "CS_VALID", CS_VALID }, 134 | { "CS_ADHOC", CS_ADHOC }, 135 | { "CS_GET_TASK_ALLOW", CS_GET_TASK_ALLOW }, 136 | { "CS_INSTALLER", CS_INSTALLER }, 137 | { "CS_FORCED_LV", CS_FORCED_LV }, 138 | { "CS_INVALID_ALLOWED", CS_INVALID_ALLOWED }, 139 | { "CS_HARD", CS_HARD }, 140 | { "CS_KILL", CS_KILL }, 141 | { "CS_CHECK_EXPIRATION", CS_CHECK_EXPIRATION }, 142 | { "CS_RESTRICT", CS_RESTRICT }, 143 | { "CS_ENFORCEMENT", CS_ENFORCEMENT }, 144 | { "CS_REQUIRE_LV", CS_REQUIRE_LV }, 145 | { "CS_ENTITLEMENTS_VALIDATED", CS_ENTITLEMENTS_VALIDATED }, 146 | { "CS_NVRAM_UNRESTRICTED", CS_NVRAM_UNRESTRICTED }, 147 | { "CS_RUNTIME", CS_RUNTIME }, 148 | { "CS_EXEC_SET_HARD", CS_EXEC_SET_HARD }, 149 | { "CS_EXEC_SET_KILL", CS_EXEC_SET_KILL }, 150 | { "CS_EXEC_SET_ENFORCEMENT", CS_EXEC_SET_ENFORCEMENT }, 151 | { "CS_EXEC_INHERIT_SIP", CS_EXEC_INHERIT_SIP }, 152 | { "CS_KILLED", CS_KILLED }, 153 | { "CS_DYLD_PLATFORM", CS_DYLD_PLATFORM }, 154 | { "CS_PLATFORM_BINARY", CS_PLATFORM_BINARY }, 155 | { "CS_PLATFORM_PATH", CS_PLATFORM_PATH }, 156 | { "CS_DEBUGGED", CS_DEBUGGED }, 157 | { "CS_SIGNED", CS_SIGNED }, 158 | { "CS_DEV_CODE", CS_DEV_CODE }, 159 | { "CS_DATAVAULT_CONTROLLER", CS_DATAVAULT_CONTROLLER }, 160 | }; 161 | #define ncsmappings (sizeof(csmapping) / sizeof(csmapping[0])) 162 | 163 | char *csflagstostr(uint32_t flags) 164 | { 165 | char *string; 166 | const char *sp; 167 | char *dp; 168 | uint32_t setflags; 169 | u_int i; 170 | 171 | if ((string = (char *)malloc(ncsmappings * (longestcsflaglen + 1))) == NULL) 172 | return (NULL); 173 | 174 | setflags = flags; 175 | dp = string; 176 | for (i = 0; i < ncsmappings; i++) { 177 | if (setflags & csmapping[i].flag) { 178 | if (dp > string) 179 | *dp++ = ','; 180 | for (sp = csmapping[i].name; *sp; *dp++ = *sp++) ; 181 | setflags &= ~csmapping[i].flag; 182 | } 183 | } 184 | *dp = '\0'; 185 | return (string); 186 | } 187 | 188 | 189 | static struct { 190 | std::string name; 191 | uint32_t flag; 192 | } const famapping[] = { 193 | {"F_OK", F_OK}, 194 | {"X_OK", X_OK}, 195 | {"R_OK", R_OK}, 196 | {"_READ_OK", _READ_OK}, 197 | {"_WRITE_OK", _WRITE_OK}, 198 | {"_EXECUTE_OK", _EXECUTE_OK}, 199 | {"_DELETE_OK", _DELETE_OK}, 200 | {"_APPEND_OK", _APPEND_OK}, 201 | {"_RMFILE_OK", _RMFILE_OK}, 202 | {"_RATTR_OK", _RATTR_OK}, 203 | {"_WATTR_OK", _WATTR_OK}, 204 | {"_REXT_OK", _REXT_OK}, 205 | {"_WEXT_OK", _WEXT_OK}, 206 | {"_RPERM_OK", _RPERM_OK}, 207 | {"_WPERM_OK", _WPERM_OK}, 208 | {"_CHOWN_OK", _CHOWN_OK}, 209 | }; 210 | 211 | std::string faflagstostr(uint32_t flags) 212 | { 213 | if (flags == F_OK) 214 | return "F_OK"; 215 | 216 | std::string string; 217 | 218 | for (unsigned long i=0; i < sizeof(famapping) || !flags; ++i) { 219 | if (famapping[i].flag & flags) { 220 | if (!string.empty()) 221 | string += ","; 222 | 223 | string += famapping[i].name; 224 | flags &= ~famapping[i].flag; 225 | } 226 | } 227 | 228 | return string; 229 | } 230 | -------------------------------------------------------------------------------- /Common/logger.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file logger.hpp 3 | * @brief An universal logger 4 | * @author Jozef Zuzelka 5 | * @date 6 | * - Created: 07.12.2018 16:58 7 | * - Edited: 21.05.2020 20:25 8 | * @version 1.0.0 9 | * @par g++: Apple LLVM version 10.0.0 (clang-1000.11.45.5) 10 | * @bug 11 | * @todo 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | #include 18 | #include 19 | #include "Tools/Tools.hpp" 20 | 21 | #define CLR "\x1B[0m" //!< Terminal normal color escape sequence 22 | #define RED "\x1B[31m" //!< Terminal red color escape sequence 23 | #define GRN "\x1B[32m" //!< Terminal green color escape sequence 24 | 25 | #define DEBUG_ARGS __FILE__, ":", __LINE__, ":<", RED, __func__, CLR, ">: " 26 | 27 | #ifdef DEBUG_BUILD 28 | 29 | /*! 30 | * @brief Debug that calls #printArray function 31 | * @param[in] bitArray Array to be printed 32 | * @param[in] dataSize Size of the array 33 | */ 34 | #define D_ARRAY(bitArray, dataSize) printArray(bitArray, dataSize) 35 | /*! 36 | * @brief Variadic debug macro that prints everything to the standard error output 37 | * @note Arguments must be delimited with << 38 | */ 39 | #define D(...) \ 40 | do { \ 41 | std::lock_guard guard(m_debugPrint); \ 42 | std::cerr << "DEBUG: " << __FILE__ << ":" << __LINE__ << ":<" << RED << __func__ << CLR << ">: "; \ 43 | std::cerr << __VA_ARGS__ << std::endl; \ 44 | } while (0) 45 | 46 | #else // DEBUG_BUILD 47 | 48 | /*! 49 | * @brief Debug macro which is substituted to nothing 50 | * @param[in] x Array to be printed 51 | * @param[in] y Size of the array 52 | */ 53 | #define D_ARRAY(x,y) 54 | /*! 55 | * @brief Variadic debug macro which is substituted to nothing 56 | */ 57 | #define D(...) 58 | 59 | #endif // DEBUG_BUILD 60 | 61 | /*! 62 | * @enum LogLevel 63 | * @brief An enum representing debug prints verbosity 64 | */ 65 | enum class LogLevel : uint8_t 66 | { 67 | VERBOSE, //!< Debug messages 68 | INFO, //!< Informational messages 69 | WARNING, //!< Warning messages 70 | ERR, //!< Error messages 71 | NONE, //!< Nothing is printed 72 | }; 73 | 74 | 75 | //! Array of prefixes of debug messages 76 | const char * const msgPrefix[] = {"[DD]", "[II]", "[WW]", "[EE]", ""}; 77 | 78 | 79 | /*! 80 | * @class Logger 81 | * @brief Class for logging 82 | */ 83 | class Logger 84 | { 85 | std::atomic m_logLevel; 86 | std::mutex m_debugPrint; 87 | 88 | Logger(const Logger&) = delete; 89 | Logger(LogLevel ll = LogLevel::WARNING) : m_logLevel(ll) { }; 90 | ~Logger() {}; 91 | 92 | public: 93 | /*! 94 | * @brief Singleton pattern 95 | * @return A single instance of the logger 96 | */ 97 | static Logger &getInstance() 98 | { 99 | static Logger logger; 100 | return logger; 101 | } 102 | 103 | /*! 104 | * @brief Function prints array in hexadecimal 105 | * @param[in] bitArray Array to be printed 106 | * @param[in] dataSize Amount of data to be printed 107 | */ 108 | inline void printArray(const uint8_t *bitArray, const size_t dataSize) 109 | { 110 | std::lock_guard guard(m_debugPrint); 111 | std::cerr << "(" << dataSize << "B): 0x"; 112 | for (unsigned int i=0; i != dataSize; i++) 113 | std::cerr << std::hex << (bitArray[i]>>4) << (bitArray[i]&0x0f) << std::dec; 114 | std::cerr << std::endl; 115 | } 116 | 117 | /*! 118 | * @brief Function that prints log messages 119 | * @param[in] ll Verbosity level 120 | * @todo Improve param description 121 | * @param[in] args Variadic parametes 122 | */ 123 | template 124 | void log(LogLevel ll, Ts&&... args) 125 | { 126 | if (ll >= m_logLevel) 127 | { 128 | std::lock_guard guard(m_debugPrint); 129 | std::cerr << current_time_and_date(); 130 | std::cerr << " " << msgPrefix[static_cast(ll)] << " "; 131 | (std::cerr << ... << args) << std::endl; 132 | } 133 | } 134 | 135 | /*! 136 | * @brief Gets m_logLevel; 137 | * @return Current LogLevel 138 | */ 139 | LogLevel getLogLevel() 140 | { 141 | return m_logLevel; 142 | } 143 | 144 | /*! 145 | * @brief Sets m_logLevel; 146 | * @param[in] ll LogLevel 147 | */ 148 | void setLogLevel(LogLevel ll) 149 | { 150 | m_logLevel = ll; 151 | } 152 | 153 | /*! 154 | * @brief Sets m_logLevel; 155 | * @param[in] ll Integer value 0-4 156 | */ 157 | void setLogLevel(std::string ll) 158 | { 159 | switch (stoi(ll)) 160 | { 161 | case 0: 162 | setLogLevel(LogLevel::NONE); 163 | break; 164 | case 1: 165 | setLogLevel(LogLevel::ERR); 166 | break; 167 | case 2: 168 | setLogLevel(LogLevel::WARNING); 169 | break; 170 | case 3: 171 | setLogLevel(LogLevel::INFO); 172 | break; 173 | case 4: 174 | setLogLevel(LogLevel::VERBOSE); 175 | break; 176 | default: 177 | log(LogLevel::ERR, "Invalid verbosity level (", ll, ")."); 178 | setLogLevel(LogLevel::INFO); 179 | } 180 | } 181 | }; 182 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Demos showing use of different macOS frameworks. 2 | Codes are inspired by various examples on the internet and in the books. Sources are listed at the beginning of relevant files. 3 | 4 | Currently working: 5 | - DiskArbitration 6 | - ESF 7 | - FSEvents (API) 8 | - FSEvents (dev) 9 | - IOKit 10 | - IOKit driver 11 | - OpenBSM 12 | - kext (generic) 13 | - Kauth 14 | 15 | 16 | Needs to be finished: 17 | - Dtrace 18 | - dext 19 | - kdebug 20 | - MACF 21 | - Proper README 22 | -------------------------------------------------------------------------------- /demos/DTrace demo/demo.d: -------------------------------------------------------------------------------- 1 | #! /usr/sbin/dtrace -C -s 2 | #pragma D option quiet 3 | 4 | #source: http://www.brendangregg.com/DTrace/dtrace_oneliners.txt 5 | 6 | 7 | # New processes with arguments 8 | proc:::exec-success { trace(curpsinfo->pr_psargs); } 9 | 10 | # Files opened by process 11 | syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); } 12 | 13 | # Syscall count by program 14 | syscall:::entry { @num[execname] = count(); } 15 | 16 | # Successful signal details, 17 | proc:::signal-send /pid/ { printf("%s -%d %d",execname,args[2],args[1]->pr_pid); } 18 | -------------------------------------------------------------------------------- /demos/DiskArbitration demo/DiskArbitration demo.xcodeproj/xcshareddata/xcschemes/DiskArbitration demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /demos/DiskArbitration demo/DiskArbitration demo/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // DiskArbitration demo 4 | // 5 | // Created by Jozef on 12/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Sources: 9 | // - https://developer.apple.com/library/archive/documentation/DriversKernelHardware/Conceptual/DiskArbitrationProgGuide/ArbitrationBasics/ArbitrationBasics.html 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include // MAXPATHLEN 16 | 17 | #include "../../../Common/SignalHandler.hpp" 18 | 19 | void got_disk(DADiskRef disk, void *context); 20 | void got_disk_removal(DADiskRef disk, void *context); 21 | void got_rename(DADiskRef disk, CFArrayRef keys, void *context); 22 | DADissenterRef allow_mount(DADiskRef disk, void *context); 23 | 24 | 25 | int main() 26 | { 27 | InstallHandleSignalFromRunLoop(); 28 | 29 | const char* demoName = "DiskArbitration"; 30 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 31 | 32 | std::cout << "(" << demoName << ") Hello, World!\n"; 33 | std::cout << "Point of interest: " << "All the external USB devices!" << std::endl << std::endl; 34 | 35 | 36 | DASessionRef session = DASessionCreate(kCFAllocatorDefault); 37 | 38 | // Watch only USB devices 39 | CFMutableDictionaryRef matchingDict = CFDictionaryCreateMutable( 40 | kCFAllocatorDefault, 41 | 0, 42 | &kCFTypeDictionaryKeyCallBacks, 43 | &kCFTypeDictionaryValueCallBacks); 44 | 45 | CFDictionaryAddValue(matchingDict, 46 | kDADiskDescriptionDeviceProtocolKey, 47 | CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)); 48 | 49 | void *context = NULL; 50 | DARegisterDiskAppearedCallback(session, 51 | kDADiskDescriptionMatchVolumeMountable, 52 | got_disk, 53 | context); 54 | 55 | /* Match all volumes */ 56 | CFDictionaryRef matchingdictionary = NULL; 57 | 58 | /* No context needed here. */ 59 | DARegisterDiskDisappearedCallback(session, 60 | matchingdictionary, 61 | got_disk_removal, 62 | context); 63 | 64 | CFMutableArrayRef keys = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); 65 | CFArrayAppendValue(keys, kDADiskDescriptionVolumeNameKey); 66 | 67 | DARegisterDiskDescriptionChangedCallback(session, 68 | matchingdictionary, /* match all disks */ 69 | keys, /* match the keys specified above */ 70 | got_rename, 71 | context); 72 | 73 | DARegisterDiskMountApprovalCallback(session, 74 | NULL, /* Match all disks */ 75 | allow_mount, 76 | NULL); /* No context */ 77 | 78 | 79 | /* Schedule a disk arbitration session. */ 80 | DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 81 | 82 | 83 | 84 | /* Start the run loop. (Don't do this if you already have 85 | a running Core Foundation or Cocoa run loop.) */ 86 | CFRunLoopRun(); 87 | 88 | 89 | DAUnregisterCallback(session, (void *)got_disk, context); 90 | DAUnregisterApprovalCallback(session, (void *)allow_mount, context); 91 | DAUnregisterCallback(session, (void *)got_disk_removal, context); 92 | DAUnregisterCallback(session, (void *)got_rename, context); 93 | 94 | /* Clean up a session. */ 95 | DASessionUnscheduleFromRunLoop(session, 96 | CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 97 | CFRelease(session); 98 | 99 | return EXIT_SUCCESS; 100 | } 101 | 102 | 103 | void got_disk(DADiskRef disk, void *context) 104 | { 105 | std::cout << "New disk appeared >" << (DADiskGetBSDName(disk) ? DADiskGetBSDName(disk) : "") << "<." << std::endl; 106 | } 107 | 108 | void got_disk_removal(DADiskRef disk, void *context) 109 | { 110 | std::cout << "Disk removed: >" << (DADiskGetBSDName(disk) ? DADiskGetBSDName(disk) : "") << "<." << std::endl; 111 | } 112 | 113 | void got_rename(DADiskRef disk, CFArrayRef keys, void *context) 114 | { 115 | CFDictionaryRef dict = DADiskCopyDescription(disk); 116 | CFURLRef fspath = (CFURLRef)CFDictionaryGetValue(dict, kDADiskDescriptionVolumePathKey); 117 | 118 | char buf[MAXPATHLEN]; 119 | if (CFURLGetFileSystemRepresentation(fspath, false, (UInt8 *)buf, sizeof(buf))) { 120 | std::cout << "Disk " << DADiskGetBSDName(disk) << " is now at " << buf << "\nChanged keys:" << std::endl; 121 | CFShow(keys); 122 | } else { 123 | /* Something is *really* wrong. */ 124 | } 125 | } 126 | 127 | DADissenterRef allow_mount(DADiskRef disk, void *context) 128 | { 129 | int allow = 0; 130 | if (allow) { 131 | /* Return NULL to allow */ 132 | std::cerr << "allow_mount: allowing mount >" << (DADiskGetBSDName(disk) ? DADiskGetBSDName(disk) : "") << "<." << std::endl; 133 | return NULL; 134 | } else { 135 | /* Return a dissenter to deny */ 136 | std::cerr << "allow_mount: refusing mount >" << (DADiskGetBSDName(disk) ? DADiskGetBSDName(disk) : "") << "<." << std::endl; 137 | return DADissenterCreate( 138 | kCFAllocatorDefault, 139 | kDAReturnExclusiveAccess, 140 | CFSTR("USB Not Allowed To Mount!")); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /demos/ESF demo/ESF demo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.endpoint-security.client 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/ESF demo/ESF demo.xcodeproj/xcshareddata/xcschemes/ESF demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /demos/ESF demo/ESF demo/Makefile: -------------------------------------------------------------------------------- 1 | # @file Makefile 2 | # @brief Brief description 3 | # @author Jozef Zuzelka 4 | # @date 5 | # - Created: 18.05.2020 10:38 6 | # - Edited: 19.05.2020 11:03 7 | # @version 1.0.0 8 | # @par make: GNU Make 3.81 9 | # @bug 10 | # @todo 11 | 12 | 13 | ######################## Compiler & flags ########################## 14 | CXX=clang++ 15 | CXXFLAGS=-std=c++17 -pedantic -Wall -Wextra -g 16 | LDFLAGS= 17 | FRAMEWORKS=-framework Foundation -framework SystemConfiguration /usr/lib/libEndpointSecurity.dylib /usr/lib/libbsm.dylib 18 | 19 | 20 | ######################## Variables ########################## 21 | SHELL:=/bin/bash 22 | SRCDIRS=. ../../../Common 23 | OBJDIR=obj 24 | BINDIR=. 25 | 26 | BIN=ESF-demo 27 | SRC=$(shell for dir in $(SRCDIRS); do find $$dir -type f \( -iname '*.mm' -o -iname '*.cpp' -o -iname '*.m' \); done) 28 | OBJ=$(patsubst %.m,%.o, $(patsubst %.mm,%.o, $(patsubst %.cpp,%.o, $(addprefix $(OBJDIR)/,$(notdir $(SRC)))))) 29 | 30 | .PHONY: clean 31 | 32 | space := 33 | space += 34 | VPATH := $(subst $(space),:,$(shell find $(SRCDIRS) -type d)) 35 | 36 | ###################### ####################### 37 | $(OBJDIR)/%.o: %.mm 38 | $(CXX) $(CXXFLAGS) -c $< -o $@ 39 | 40 | $(OBJDIR)/%.o: %.cpp 41 | $(CXX) $(CXXFLAGS) -c $< -o $@ 42 | 43 | all: directories $(BIN) 44 | 45 | $(BIN): $(OBJ) 46 | $(CXX) $(LDFLAGS) $(FRAMEWORKS) -o $(BINDIR)/$@ $^ 47 | directories: 48 | @mkdir -p $(BINDIR) $(OBJDIR) 49 | 50 | 51 | clean: 52 | rm -rf $(OBJDIR) $(BINDIR)/$(BIN) 53 | -------------------------------------------------------------------------------- /demos/ESF demo/ESF demo/main.mm: -------------------------------------------------------------------------------- 1 | // 2 | // main.mm 3 | // ESF demo 4 | // 5 | // Created by Jozef on 15/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Source: https://gist.github.com/Omar-Ikram/8e6721d8e83a3da69b31d4c2612a68ba/ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include // FREAD, FWRITE, FFLAGS 18 | #include 19 | #import 20 | 21 | #include "../../../Common/Tools/Tools.hpp" 22 | #include "../../../Common/Tools/Tools-ES.hpp" 23 | 24 | // From 25 | /* convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE */ 26 | #define FFLAGS(oflags) ((oflags) + 1) 27 | #define OFLAGS(fflags) ((fflags) - 1) 28 | 29 | es_client_t *g_client = nullptr; 30 | std::vector g_blockedPaths; // thread safe for reading 31 | 32 | const inline static es_event_type_t g_eventsOfInterest[] = { 33 | // Process 34 | ES_EVENT_TYPE_AUTH_EXEC, 35 | ES_EVENT_TYPE_NOTIFY_EXIT, 36 | ES_EVENT_TYPE_NOTIFY_FORK, 37 | // File System 38 | ES_EVENT_TYPE_NOTIFY_ACCESS, 39 | ES_EVENT_TYPE_AUTH_CLONE, 40 | ES_EVENT_TYPE_NOTIFY_CLOSE, 41 | ES_EVENT_TYPE_AUTH_CREATE, 42 | ES_EVENT_TYPE_AUTH_FILE_PROVIDER_MATERIALIZE, 43 | ES_EVENT_TYPE_AUTH_FILE_PROVIDER_UPDATE, 44 | ES_EVENT_TYPE_NOTIFY_EXCHANGEDATA, 45 | ES_EVENT_TYPE_AUTH_LINK, 46 | ES_EVENT_TYPE_AUTH_MOUNT, 47 | ES_EVENT_TYPE_AUTH_OPEN, 48 | ES_EVENT_TYPE_AUTH_READDIR, 49 | ES_EVENT_TYPE_AUTH_READLINK, 50 | ES_EVENT_TYPE_AUTH_RENAME, 51 | ES_EVENT_TYPE_AUTH_TRUNCATE, 52 | ES_EVENT_TYPE_AUTH_UNLINK, 53 | ES_EVENT_TYPE_NOTIFY_UNMOUNT, 54 | ES_EVENT_TYPE_NOTIFY_WRITE, 55 | // System 56 | ES_EVENT_TYPE_NOTIFY_IOKIT_OPEN, 57 | ES_EVENT_TYPE_NOTIFY_KEXTLOAD, 58 | ES_EVENT_TYPE_NOTIFY_KEXTUNLOAD, 59 | }; 60 | 61 | void notify_event_handler(const es_message_t *msg); 62 | uint32_t flags_event_handler(const es_message_t *msg); 63 | es_auth_result_t auth_event_handler(const es_message_t *msg); 64 | 65 | void signalHandler(int signum) 66 | { 67 | if(g_client) { 68 | es_unsubscribe_all(g_client); 69 | es_delete_client(g_client); 70 | } 71 | 72 | // Not safe, but whatever 73 | std::cerr << "Interrupt signal (" << signum << ") received, exiting." << std::endl; 74 | exit(signum); 75 | } 76 | 77 | 78 | int main() { 79 | // No runloop, no problem 80 | signal(SIGINT, signalHandler); 81 | signal(SIGTERM, signalHandler); 82 | signal(SIGABRT, signalHandler); 83 | 84 | const char* demoName = "ESF"; 85 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 86 | 87 | std::cout << "(" << demoName << ") Hello, World!\n"; 88 | std::cout << "Point of interest: " << demoPath << std::endl << std::endl; 89 | 90 | 91 | @autoreleasepool { 92 | g_blockedPaths.push_back(demoPath); 93 | 94 | // Handler blocking file operations working with demoPath and monitoring mount operations 95 | es_handler_block_t handler = ^(es_client_t *clt, const es_message_t *msg) { 96 | //std::cout << msg << std::endl; 97 | 98 | // Handle subscribed AUTH events: 99 | if (msg->action_type == ES_ACTION_TYPE_AUTH) { 100 | es_respond_result_t res; 101 | 102 | if (msg->event_type == ES_EVENT_TYPE_AUTH_OPEN) { 103 | res = es_respond_flags_result(clt, msg, flags_event_handler(msg), false); 104 | } else { 105 | res = es_respond_auth_result(clt, msg, auth_event_handler(msg), false); 106 | } 107 | 108 | if (res != ES_RESPOND_RESULT_SUCCESS) 109 | std::cerr << "es_respond_auth_result: " << g_respondResultToStrMap.at(res) << std::endl; 110 | } else { 111 | notify_event_handler(msg); 112 | } 113 | }; 114 | 115 | es_new_client_result_t res = es_new_client(&g_client, handler); 116 | 117 | if (ES_NEW_CLIENT_RESULT_SUCCESS != res) { 118 | if(ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED == res) 119 | std::cerr << "Application requires 'com.apple.developer.endpoint-security.client' entitlement\n"; 120 | else if(ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED == res) 121 | std::cerr << "Application needs to run as root (and SIP disabled).\n"; 122 | else 123 | std::cerr << "es_new_client: " << res << std::endl; 124 | 125 | return EXIT_FAILURE; 126 | } 127 | 128 | // Cache needs to be explicitly cleared between program invocations 129 | es_clear_cache_result_t resCache = es_clear_cache(g_client); 130 | if (ES_CLEAR_CACHE_RESULT_SUCCESS != resCache) { 131 | std::cerr << "es_clear_cache: " << resCache << std::endl; 132 | return EXIT_FAILURE; 133 | } 134 | 135 | 136 | // Subscribe to the events we're interested in 137 | es_return_t subscribed = es_subscribe(g_client, 138 | g_eventsOfInterest, 139 | (sizeof(g_eventsOfInterest) / sizeof((g_eventsOfInterest)[0])) // Event count 140 | ); 141 | 142 | if (subscribed == ES_RETURN_ERROR) { 143 | std::cerr << "es_subscribe: ES_RETURN_ERROR\n"; 144 | return EXIT_FAILURE; 145 | } 146 | 147 | dispatch_main(); 148 | } 149 | 150 | return EXIT_SUCCESS; 151 | } 152 | 153 | 154 | static const auto find_occurence = [](const std::string& str) { 155 | for (const auto &path : g_blockedPaths) { 156 | if (str.find(path) != std::string::npos) { 157 | std::cout << "*** Occurence found: " << str << std::endl; 158 | return true; 159 | } 160 | } 161 | return false; 162 | }; 163 | 164 | void notify_event_handler(const es_message_t *msg) 165 | { 166 | switch(msg->event_type) { 167 | // Process 168 | case ES_EVENT_TYPE_NOTIFY_EXIT: 169 | case ES_EVENT_TYPE_NOTIFY_FORK: 170 | // System 171 | case ES_EVENT_TYPE_NOTIFY_IOKIT_OPEN: 172 | break; 173 | case ES_EVENT_TYPE_NOTIFY_KEXTLOAD: 174 | case ES_EVENT_TYPE_NOTIFY_KEXTUNLOAD: 175 | // File System 176 | case ES_EVENT_TYPE_NOTIFY_UNMOUNT: 177 | std::cout << "NOTIFY OPERATION: " << g_eventTypeToStrMap.at(msg->event_type) << std::endl; 178 | std::cout << msg << std::endl; 179 | break; 180 | // File System 181 | case ES_EVENT_TYPE_NOTIFY_ACCESS: 182 | case ES_EVENT_TYPE_NOTIFY_CLOSE: 183 | case ES_EVENT_TYPE_NOTIFY_EXCHANGEDATA: 184 | case ES_EVENT_TYPE_NOTIFY_WRITE: 185 | { 186 | const std::vector eventPaths = paths_from_event(msg); 187 | 188 | // Block if path is in our blocked paths list 189 | if (std::any_of(eventPaths.cbegin(), eventPaths.cend(), find_occurence)) { 190 | std::cout << " " << (msg->action_type == ES_ACTION_TYPE_AUTH ? "BLOCKING: " : "NOTIFY: ") 191 | << g_eventTypeToStrMap.at(msg->event_type) << " at " 192 | << (long long) msg->mach_time << " of mach time." << std::endl; 193 | std::cout << msg << std::endl; 194 | } 195 | break; 196 | } 197 | default: 198 | std::cout << "DEFAULT: " << g_eventTypeToStrMap.at(msg->event_type) << std::endl; 199 | break; 200 | } 201 | } 202 | 203 | uint32_t flags_event_handler(const es_message_t *msg) 204 | { 205 | uint32_t res = msg->event.open.fflag; 206 | 207 | switch(msg->event_type) { 208 | case ES_EVENT_TYPE_AUTH_OPEN: 209 | { 210 | const std::vector eventPaths = paths_from_event(msg); 211 | 212 | // Block if path is in our blocked paths list 213 | if (std::any_of(eventPaths.cbegin(), eventPaths.cend(), find_occurence)) { 214 | std::cout << " " << (msg->action_type == ES_ACTION_TYPE_AUTH ? "BLOCKING: " : "NOTIFY: ") 215 | << g_eventTypeToStrMap.at(msg->event_type) << " at " 216 | << (long long) msg->mach_time << " of mach time." << std::endl; 217 | std::cout << msg << std::endl; 218 | res = FFLAGS(O_RDONLY); 219 | } 220 | break; 221 | } 222 | default: 223 | std::cout << "DEFAULT: " << g_eventTypeToStrMap.at(msg->event_type) << std::endl; 224 | break; 225 | } 226 | 227 | return res; 228 | } 229 | 230 | // Simple handler to make AUTH (allow or block) decisions. 231 | // Returns either an ES_AUTH_RESULT_ALLOW or ES_AUTH_RESULT_DENY. 232 | es_auth_result_t auth_event_handler(const es_message_t *msg) 233 | { 234 | switch(msg->event_type) { 235 | // Process 236 | case ES_EVENT_TYPE_AUTH_EXEC: 237 | break; 238 | // System 239 | // File System 240 | case ES_EVENT_TYPE_AUTH_MOUNT: 241 | std::cout << "ALLOWING OPERATION: " << g_eventTypeToStrMap.at(msg->event_type) << std::endl; 242 | std::cout << msg << std::endl; 243 | break; 244 | // File System 245 | case ES_EVENT_TYPE_AUTH_CREATE: 246 | case ES_EVENT_TYPE_AUTH_CLONE: 247 | case ES_EVENT_TYPE_AUTH_FILE_PROVIDER_MATERIALIZE: 248 | case ES_EVENT_TYPE_AUTH_FILE_PROVIDER_UPDATE: 249 | case ES_EVENT_TYPE_AUTH_LINK: 250 | case ES_EVENT_TYPE_AUTH_READDIR: 251 | case ES_EVENT_TYPE_AUTH_READLINK: 252 | case ES_EVENT_TYPE_AUTH_RENAME: 253 | case ES_EVENT_TYPE_AUTH_TRUNCATE: 254 | case ES_EVENT_TYPE_AUTH_UNLINK: 255 | { 256 | const std::vector eventPaths = paths_from_event(msg); 257 | 258 | // Block if path is in our blocked paths list 259 | if (std::any_of(eventPaths.cbegin(), eventPaths.cend(), find_occurence)) { 260 | std::cout << " " << (msg->action_type == ES_ACTION_TYPE_AUTH ? "BLOCKING: " : "NOTIFY: ") 261 | << g_eventTypeToStrMap.at(msg->event_type) << " at " 262 | << (long long) msg->mach_time << " of mach time." << std::endl; 263 | std::cout << msg << std::endl; 264 | 265 | return ES_AUTH_RESULT_DENY; 266 | } 267 | break; 268 | } 269 | default: 270 | std::cout << "DEFAULT: " << g_eventTypeToStrMap.at(msg->event_type) << std::endl; 271 | break; 272 | } 273 | 274 | return ES_AUTH_RESULT_ALLOW; 275 | } 276 | -------------------------------------------------------------------------------- /demos/ESF demo/sign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | APP=ESF-demo 3 | PATH_TO_APP="ESF demo" 4 | ENTITLEMENTS="ESF demo.entitlements" 5 | CERT_ID="-" 6 | 7 | echo "\n\n**** Previous entitlements of $APP ****" 8 | codesign -d --ent :- "$PATH_TO_APP/$APP" 9 | 10 | 11 | echo "\n\n**** Signing $APP ****" 12 | codesign --force -vvvv --entitlements "$ENTITLEMENTS" -s "$CERT_ID" "$PATH_TO_APP/$APP" 13 | 14 | echo "\n\n**** Final entitlements of $APP ****" 15 | codesign -d --ent :- "$PATH_TO_APP/$APP" 16 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo.xcodeproj/xcshareddata/xcschemes/FSEvents-API demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo.xcodeproj/xcshareddata/xcschemes/FSEvents-dev demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo/FSEvents-API.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FSEvents-API.cpp 3 | // FSEvents demo 4 | // 5 | // Created by Jozef on 11/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../../../Common/SignalHandler.hpp" 14 | 15 | static inline const std::map g_streamEventFlags = { 16 | {kFSEventStreamEventFlagNone, "kFSEventStreamEventFlagNone"}, 17 | {kFSEventStreamEventFlagMustScanSubDirs, "kFSEventStreamEventFlagMustScanSubDirs"}, 18 | {kFSEventStreamEventFlagUserDropped, "kFSEventStreamEventFlagUserDropped"}, 19 | {kFSEventStreamEventFlagKernelDropped, "kFSEventStreamEventFlagKernelDropped"}, 20 | {kFSEventStreamEventFlagEventIdsWrapped, "kFSEventStreamEventFlagEventIdsWrapped"}, 21 | {kFSEventStreamEventFlagHistoryDone, "kFSEventStreamEventFlagHistoryDone"}, 22 | {kFSEventStreamEventFlagRootChanged, "kFSEventStreamEventFlagRootChanged"}, 23 | {kFSEventStreamEventFlagMount, "kFSEventStreamEventFlagMount"}, 24 | {kFSEventStreamEventFlagUnmount, "kFSEventStreamEventFlagUnmount"}, 25 | {kFSEventStreamEventFlagItemCreated, "kFSEventStreamEventFlagItemCreated"}, 26 | {kFSEventStreamEventFlagItemRemoved, "kFSEventStreamEventFlagItemRemoved"}, 27 | {kFSEventStreamEventFlagItemInodeMetaMod, "kFSEventStreamEventFlagItemInodeMetaMod"}, 28 | {kFSEventStreamEventFlagItemRenamed, "kFSEventStreamEventFlagItemRenamed"}, 29 | {kFSEventStreamEventFlagItemModified, "kFSEventStreamEventFlagItemModified"}, 30 | {kFSEventStreamEventFlagItemFinderInfoMod, "kFSEventStreamEventFlagItemFinderInfoMod"}, 31 | {kFSEventStreamEventFlagItemChangeOwner, "kFSEventStreamEventFlagItemChangeOwner"}, 32 | {kFSEventStreamEventFlagItemXattrMod, "kFSEventStreamEventFlagItemXattrMod"}, 33 | {kFSEventStreamEventFlagItemIsFile, "kFSEventStreamEventFlagItemIsFile"}, 34 | {kFSEventStreamEventFlagItemIsDir, "kFSEventStreamEventFlagItemIsDir"}, 35 | {kFSEventStreamEventFlagItemIsSymlink, "kFSEventStreamEventFlagItemIsSymlink"}, 36 | {kFSEventStreamEventFlagOwnEvent, "kFSEventStreamEventFlagOwnEvent"}, 37 | {kFSEventStreamEventFlagItemIsHardlink, "kFSEventStreamEventFlagItemIsHardlink"}, 38 | {kFSEventStreamEventFlagItemIsLastHardlink, "kFSEventStreamEventFlagItemIsLastHardlink"}, 39 | {kFSEventStreamEventFlagItemCloned, "kFSEventStreamEventFlagItemCloned"}, 40 | }; 41 | 42 | void eventCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]); 43 | 44 | int main() 45 | { 46 | InstallHandleSignalFromRunLoop(); 47 | 48 | const char* demoName = "FSEvents-API"; 49 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 50 | 51 | std::cout << "(" << demoName << ") Hello, World!\n"; 52 | std::cout << "Point of interest: " << demoPath << std::endl << std::endl; 53 | 54 | // Init source paths to watch 55 | CFStringRef path = CFStringCreateWithCString(kCFAllocatorDefault, demoPath.c_str(), kCFStringEncodingUTF8); 56 | CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorDefault, (const void **)&path, 1, NULL); 57 | // Set context passed to the stream callback 58 | FSEventStreamContext *ctx = nullptr; 59 | // Set latency in seconds 60 | CFAbsoluteTime latency = 3.0; 61 | 62 | FSEventStreamRef stream = FSEventStreamCreate(kCFAllocatorDefault, 63 | eventCallback, 64 | ctx, 65 | pathsToWatch, 66 | kFSEventStreamEventIdSinceNow, // Or a previous event ID 67 | latency, 68 | kFSEventStreamCreateFlagIgnoreSelf | kFSEventStreamCreateFlagFileEvents); 69 | 70 | FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 71 | 72 | // Tell the daemon to send notifications to our client 73 | FSEventStreamStart(stream); 74 | 75 | CFRunLoopRun(); 76 | 77 | // Stop receaving the notifications 78 | FSEventStreamStop(stream); 79 | // Unschedule the stream from all run loops 80 | FSEventStreamInvalidate(stream); 81 | // Release resources 82 | FSEventStreamRelease(stream); 83 | CFRelease(path); 84 | CFRelease(pathsToWatch); 85 | 86 | return 0; 87 | } 88 | 89 | void eventCallback(ConstFSEventStreamRef streamRef, // The stream for which event(s) occured. 90 | void *clientCallBackInfo, // Context. 91 | size_t numEvents, // The number of events being reported in this callback. 92 | void *eventPaths, // An array of paths to the directories in which event(s) occured. 93 | const FSEventStreamEventFlags eventFlags[], 94 | const FSEventStreamEventId eventIds[]) 95 | { 96 | const char * const *paths = (char**)eventPaths; 97 | 98 | for (int i=0; i 15 | #include // O_RDONLY 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include // for _IOW, a macro required by FSEVENTS_CLONE 21 | #include // for sysctl, KERN_PROC, etc. 22 | #include // geteuid, read, close 23 | #include "fsevents.h" // copied from xnu/bsd/sys/fsevents.h 24 | 25 | std::atomic g_shouldStop {false}; 26 | 27 | #define BUFSIZE 1024*1024 28 | 29 | static inline const std::map g_kfseNames = { 30 | {FSE_CREATE_FILE, "FSE_CREATE_FILE"}, 31 | {FSE_DELETE, "FSE_DELETE"}, 32 | {FSE_STAT_CHANGED, "FSE_STAT_CHANGED"}, 33 | {FSE_RENAME, "FSE_RENAME"}, 34 | {FSE_CONTENT_MODIFIED, "FSE_CONTENT_MODIFIED"}, 35 | {FSE_CREATE_DIR, "FSE_CREATE_DIR"}, 36 | {FSE_CHOWN, "FSE_CHOWN"}, 37 | {FSE_EXCHANGE, "FSE_EXCHANGE"}, 38 | {FSE_FINDER_INFO_CHANGED, "FSE_FINDER_INFO_CHANGED"}, 39 | {FSE_XATTR_MODIFIED, "FSE_XATTR_MODIFIED"}, 40 | {FSE_XATTR_REMOVED, "FSE_XATTR_REMOVED"}, 41 | {FSE_DOCID_CREATED, "FSE_DOCID_CREATED"}, 42 | {FSE_DOCID_CHANGED, "FSE_DOCID_CHANGED"}, 43 | }; 44 | 45 | static inline const std::map g_kfseArgNames = { 46 | {0, "Unknown"}, 47 | {FSE_ARG_VNODE, "FSE_ARG_VNODE"}, 48 | {FSE_ARG_STRING, "FSE_ARG_STRING"}, 49 | {FSE_ARG_PATH, "FSE_ARG_PATH"}, 50 | {FSE_ARG_INT32, "FSE_ARG_INT32"}, 51 | {FSE_ARG_INT64, "FSE_ARG_INT64"}, 52 | {FSE_ARG_RAW, "FSE_ARG_RAW"}, 53 | {FSE_ARG_INO, "FSE_ARG_INO"}, 54 | {FSE_ARG_UID, "FSE_ARG_UID"}, 55 | {FSE_ARG_DEV, "FSE_ARG_DEV"}, 56 | {FSE_ARG_MODE, "FSE_ARG_MODE"}, 57 | {FSE_ARG_GID, "FSE_ARG_GID"}, 58 | {FSE_ARG_FINFO, "FSE_ARG_FINFO"}, 59 | }; 60 | 61 | struct kfs_event_arg_t { 62 | /* argument type */ 63 | u_int16_t type; 64 | 65 | /* size of argument data that follows this field */ 66 | u_int16_t len; 67 | 68 | union { 69 | struct vnode *vp; 70 | char *str; 71 | void *ptr; 72 | int32_t int32; 73 | int64_t int64; 74 | dev_t dev; 75 | ino_t ino; 76 | int32_t mode; 77 | uid_t uid; 78 | gid_t gid; 79 | uint64_t timestamp; 80 | } data; 81 | }; 82 | 83 | #define KFS_NUM_ARGS FSE_MAX_ARGS 84 | // an event 85 | struct kfs_event { 86 | int32_t type; // Event type 87 | pid_t pid; // pid of the process that performed the operation 88 | kfs_event_arg_t args[KFS_NUM_ARGS]; // event arguments 89 | }; 90 | 91 | // for pretty-printing of vnode types 92 | enum vtype { 93 | VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD, VSTR, VCPLX 94 | }; 95 | 96 | enum vtype iftovt_tab[] = { 97 | VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, 98 | VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, 99 | }; 100 | 101 | static const char *vtypeNames[] = { 102 | "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", 103 | "VSOCK", "VFIFO", "VBAD", "VSTR", "VCPLX", 104 | }; 105 | #define VTYPE_MAX (sizeof(vtypeNames)/sizeof(char *)) 106 | 107 | static char *getProcName(long pid); 108 | 109 | void signalHandler(int signum) 110 | { 111 | // Not safe, but whatever 112 | std::cerr << "Interrupt signal (" << signum << ") received, exiting." << std::endl; 113 | g_shouldStop = true; 114 | } 115 | 116 | 117 | int main() 118 | { 119 | // No runloop, no problem 120 | signal(SIGINT, signalHandler); 121 | signal(SIGTERM, signalHandler); 122 | signal(SIGABRT, signalHandler); 123 | 124 | const char* demoName = "FSEvents-dev"; 125 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 126 | 127 | std::cout << "(" << demoName << ") Hello, World!\n"; 128 | std::cout << "Point of interest: " << "All the events!" << std::endl << std::endl; 129 | 130 | int fsed, cloned_fsed; 131 | // Open the device 132 | fsed = open ("/dev/fsevents", O_RDONLY); 133 | 134 | if (geteuid()) 135 | std::cerr << "Opening /dev/fsevents requires root permissions\n"; 136 | 137 | if (fsed < 0) { 138 | std::cerr << "Could not open the device\n"; 139 | return EXIT_FAILURE; 140 | } 141 | 142 | // Prepare event mask list. In our simple example, we want everything 143 | // (i.e. all events, so we say "FSE_REPORT" all). Otherwise, we 144 | // would have to specifically toggle FSE_IGNORE for each: 145 | // 146 | // e.g. 147 | // events[FSE_XATTR_MODIFIED] = FSE_IGNORE; 148 | // events[FSE_XATTR_REMOVED] = FSE_IGNORE; 149 | // etc.. 150 | int8_t events[FSE_MAX_EVENTS]; 151 | for (int i=0; i < FSE_MAX_EVENTS; i++) 152 | events[i] = FSE_REPORT; 153 | 154 | fsevent_clone_args clone_args; 155 | 156 | // Get ready to clone the descriptor: 157 | memset(&clone_args, '\0', sizeof(clone_args)); 158 | clone_args.fd = &cloned_fsed; // This is the descriptor we get back 159 | clone_args.event_queue_depth = 100; // Makes all the difference 160 | clone_args.event_list = events; 161 | clone_args.num_events = FSE_MAX_EVENTS; 162 | 163 | // Do it. 164 | ssize_t rc = ioctl (fsed, FSEVENTS_CLONE, &clone_args); 165 | // We no longer need original.. 166 | close(fsed); 167 | 168 | if (rc < 0) { 169 | std::cerr << "ioctl error.\n"; 170 | return EXIT_FAILURE; 171 | } 172 | 173 | u_int32_t is_fse_arg_vnode = 0; 174 | char buf[BUFSIZE]; 175 | // And now we simply read, ad infinitum (aut nauseam) 176 | while ((rc = read (cloned_fsed, buf, BUFSIZE)) > 0 && !g_shouldStop) { // event-processing loop 177 | // rc returns the count of bytes for one or more events: 178 | int off = 0; 179 | 180 | while (off < rc) { 181 | std::cout << "----" << off << "/" << rc << " bytes.\n"; 182 | 183 | kfs_event *kfse = (kfs_event *)((char*)buf + off); 184 | off += sizeof(kfse->type) + sizeof(kfse->pid); 185 | 186 | 187 | if (kfse->type == FSE_EVENTS_DROPPED) { 188 | std::cout << "#Event\n" << "\ttype = " << "EVENTS DROPPED" << "\n\tpid = " << kfse->pid << std::endl; 189 | off += sizeof(u_int16_t); // FSE_ARG_DONE: sizeof(type) 190 | continue; 191 | } 192 | 193 | if (kfse->type < FSE_MAX_EVENTS && kfse->type >= -1) { 194 | std::cout << "#Event\n" << "\ttype = " << g_kfseNames.at(kfse->type) << "\n\tpid = " << kfse->pid << " (" << (getProcName(kfse->pid) ? getProcName(kfse->pid) : "?") << ")" << std::endl; 195 | } 196 | 197 | std::cout << "\t#Details\n\tType\t\tLength\tData" << std::endl; 198 | kfs_event_arg_t *kea = kfse->args; 199 | 200 | int i = 0; 201 | while ((off < rc) && (i <= FSE_MAX_ARGS)) { // process arguments 202 | i++; 203 | 204 | if (kea->type == FSE_ARG_DONE) { // no more arguments 205 | std::cout << "\t" << "FSE_ARG_DONE\t" << kea->type << std::endl; 206 | off += sizeof(kea->type); 207 | break; 208 | } 209 | 210 | int eoff = sizeof(kea->type) + sizeof(kea->len) + kea->len; 211 | off += eoff; 212 | 213 | int32_t arg_id = (kea->type > FSE_MAX_ARGS) ? 0 : kea->type; 214 | std::cout << "\t" << g_kfseArgNames.at(arg_id) << "\t\t" << kea->len << "\t"; 215 | 216 | switch (kea->type) { // handle based on argument type 217 | case FSE_ARG_VNODE: // a vnode (string) pointer 218 | is_fse_arg_vnode = 1; 219 | std::cout << "path = " << (char*)&(kea->data.vp) << std::endl; 220 | break; 221 | case FSE_ARG_STRING: // a string pointer 222 | std::cout << "string = " << (char*)&(kea->data.str) << std::endl; 223 | break; 224 | case FSE_ARG_INT32: 225 | std::cout << "int32 = " << kea->data.int32 << std::endl; 226 | break; 227 | case FSE_ARG_INT64: 228 | std::cout << "int64 = " << kea->data.int64 << std::endl; 229 | break; 230 | case FSE_ARG_RAW: // a void pointer 231 | std::cout << "ptr = " << std::hex << "0x" << (long)(kea->data.ptr) << std::dec << std::endl; 232 | break; 233 | case FSE_ARG_INO: // an inode number 234 | std::cout << "ino = " << kea->data.ino << std::endl; 235 | break; 236 | case FSE_ARG_UID: // a user ID 237 | { 238 | struct passwd *p = getpwuid(kea->data.uid); 239 | std::cout << "uid = " << kea->data.uid << "(" << ((p) ? p->pw_name : "?") << ")" << std::endl; 240 | break; 241 | } 242 | case FSE_ARG_DEV: // a file system ID or a device number 243 | if (is_fse_arg_vnode) { 244 | std::cout << "fsid = " << std::hex << kea->data.dev << std::dec << std::endl; 245 | is_fse_arg_vnode = 0; 246 | } else { 247 | std::cout << "dev = " << std::hex << kea->data.dev << std::dec << "(major " << major(kea->data.dev) << " minor " << minor(kea->data.dev) << ")" << std::endl; 248 | } 249 | break; 250 | case FSE_ARG_MODE: // a combination of file mode and file type 251 | { 252 | mode_t va_mode = (kea->data.mode & 0x0000ffff); 253 | u_int32_t va_type = (kea->data.mode & 0xfffff000); 254 | char fileModeString[11+1]; 255 | 256 | strmode(va_mode, fileModeString); 257 | va_type = iftovt_tab[(va_type * S_IFMT) >> 12]; 258 | std::cout << "mode = " << fileModeString << "(" << std::hex << kea->data.mode << ", vnode type " << std::dec << ((va_type < VTYPE_MAX) ? vtypeNames[va_type] : "?") << ")" << std::endl; 259 | break; 260 | } 261 | default: 262 | std::cout << "unknown" << std::endl; 263 | break; 264 | } 265 | kea = (kfs_event_arg_t *) ((char *)kea + eoff); // next 266 | } // for each argument 267 | } // for each event 268 | } // forever 269 | 270 | close(cloned_fsed); 271 | return EXIT_SUCCESS; 272 | } 273 | 274 | 275 | static char *getProcName(long pid) 276 | { 277 | static long lastPID = 0; 278 | static char procName[4096]; 279 | size_t len = 1000; 280 | int rc; 281 | int mib[4]; 282 | 283 | // minor optimization 284 | if (pid != lastPID) { 285 | memset(procName, '\0', 4096); 286 | 287 | mib[0] = CTL_KERN; 288 | mib[1] = KERN_PROC; 289 | mib[2] = KERN_PROC_PID; 290 | mib[3] = static_cast(pid); 291 | 292 | if ((rc = sysctl(mib, 4, procName, &len, NULL,0)) < 0) { 293 | perror("trace facility failure, KERN_PROC_PID\n"); 294 | exit(2); 295 | } 296 | 297 | //printf ("GOT PID: %d and rc: %d - %s\n", mib[3], rc, ((struct kinfo_proc *)procName)->kp_proc.p_comm); 298 | lastPID = pid; 299 | } 300 | return (((struct kinfo_proc *)procName)->kp_proc.p_comm); 301 | } 302 | -------------------------------------------------------------------------------- /demos/FSEvents demo/FSEvents demo/fsevents.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2014 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. The rights granted to you under the License 10 | * may not be used to create, or enable the creation or redistribution of, 11 | * unlawful or unlicensed copies of an Apple operating system, or to 12 | * circumvent, violate, or enable the circumvention or violation of, any 13 | * terms of an Apple operating system software license agreement. 14 | * 15 | * Please obtain a copy of the License at 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 | * 18 | * The Original Code and all software distributed under the License are 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 | * Please see the License for the specific language governing rights and 24 | * limitations under the License. 25 | * 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 | */ 28 | #ifndef FSEVENT_H 29 | #define FSEVENT_H 1 30 | 31 | // Event types that you can ask to listen for 32 | #define FSE_INVALID -1 33 | #define FSE_CREATE_FILE 0 34 | #define FSE_DELETE 1 35 | #define FSE_STAT_CHANGED 2 36 | #define FSE_RENAME 3 37 | #define FSE_CONTENT_MODIFIED 4 38 | #define FSE_EXCHANGE 5 39 | #define FSE_FINDER_INFO_CHANGED 6 40 | #define FSE_CREATE_DIR 7 41 | #define FSE_CHOWN 8 42 | #define FSE_XATTR_MODIFIED 9 43 | #define FSE_XATTR_REMOVED 10 44 | #define FSE_DOCID_CREATED 11 45 | #define FSE_DOCID_CHANGED 12 46 | #define FSE_UNMOUNT_PENDING 13 // iOS-only: client must respond via FSEVENTS_UNMOUNT_PENDING_ACK 47 | #define FSE_CLONE 14 48 | 49 | #define FSE_MAX_EVENTS 15 50 | #define FSE_ALL_EVENTS 998 51 | 52 | #define FSE_EVENTS_DROPPED 999 53 | 54 | // 55 | // These defines only apply if you've asked for extended 56 | // type info. In that case the type field's low 12-bits 57 | // contain the basic types defined above and the top 4 58 | // bits contain flags that indicate if an event had other 59 | // events combined with it or if it represents a directory 60 | // that has dropped events below it. 61 | // 62 | #define FSE_TYPE_MASK 0x0fff 63 | #define FSE_FLAG_MASK 0xf000 64 | #define FSE_FLAG_SHIFT 12 65 | #define FSE_GET_FLAGS(type) (((type) >> 12) & 0x000f) 66 | 67 | #define FSE_COMBINED_EVENTS 0x0001 68 | #define FSE_CONTAINS_DROPPED_EVENTS 0x0002 69 | 70 | 71 | // Actions for each event type 72 | #define FSE_IGNORE 0 73 | #define FSE_REPORT 1 74 | #define FSE_ASK 2 // Not implemented yet 75 | 76 | // The types of each of the arguments for an event 77 | // Each type is followed by the size and then the 78 | // data. FSE_ARG_VNODE is just a path string 79 | #define FSE_ARG_VNODE 0x0001 // next arg is a vnode pointer 80 | #define FSE_ARG_STRING 0x0002 // next arg is length followed by string ptr 81 | #define FSE_ARG_PATH 0x0003 // next arg is a full path 82 | #define FSE_ARG_INT32 0x0004 // next arg is a 32-bit int 83 | #define FSE_ARG_INT64 0x0005 // next arg is a 64-bit int 84 | #define FSE_ARG_RAW 0x0006 // next arg is a length followed by a void ptr 85 | #define FSE_ARG_INO 0x0007 // next arg is the inode number (ino_t) 86 | #define FSE_ARG_UID 0x0008 // next arg is the file's uid (uid_t) 87 | #define FSE_ARG_DEV 0x0009 // next arg is the file's dev_t 88 | #define FSE_ARG_MODE 0x000a // next arg is the file's mode (as an int32, file type only) 89 | #define FSE_ARG_GID 0x000b // next arg is the file's gid (gid_t) 90 | #define FSE_ARG_FINFO 0x000c // next arg is a packed finfo (dev, ino, mode, uid, gid) 91 | #define FSE_ARG_DONE 0xb33f // no more arguments 92 | 93 | #define FSE_MAX_ARGS 12 94 | 95 | // 96 | // These are special bits that be set in the 32-bit mode 97 | // field that /dev/fsevents provides. 98 | // 99 | #define FSE_MODE_HLINK (1U << 31) // notification is for a hard-link 100 | #define FSE_MODE_LAST_HLINK (1U << 30) // link count == 0 on a hard-link delete 101 | #define FSE_REMOTE_DIR_EVENT (1U << 29) // this is a remotely generated directory-level granularity event 102 | #define FSE_TRUNCATED_PATH (1U << 28) // the path for this item had to be truncated 103 | #define FSE_MODE_CLONE (1U << 27) // notification is for a clone 104 | 105 | // ioctl's on /dev/fsevents 106 | typedef struct fsevent_clone_args { 107 | int8_t *event_list; 108 | int32_t num_events; 109 | int32_t event_queue_depth; 110 | int32_t *fd; 111 | } fsevent_clone_args; 112 | 113 | #define FSEVENTS_CLONE _IOW('s', 1, fsevent_clone_args) 114 | 115 | 116 | // ioctl's on the cloned fd 117 | #pragma pack(push, 4) 118 | typedef struct fsevent_dev_filter_args { 119 | uint32_t num_devices; 120 | dev_t *devices; 121 | } fsevent_dev_filter_args; 122 | #pragma pack(pop) 123 | 124 | #define FSEVENTS_DEVICE_FILTER _IOW('s', 100, fsevent_dev_filter_args) 125 | #define FSEVENTS_WANT_COMPACT_EVENTS _IO('s', 101) 126 | #define FSEVENTS_WANT_EXTENDED_INFO _IO('s', 102) 127 | #define FSEVENTS_GET_CURRENT_ID _IOR('s', 103, uint64_t) 128 | #define FSEVENTS_UNMOUNT_PENDING_ACK _IOW('s', 104, dev_t) 129 | 130 | 131 | #ifdef BSD_KERNEL_PRIVATE 132 | 133 | void fsevents_init(void); 134 | void fsevent_unmount(struct mount *mp, vfs_context_t ctx); 135 | struct vnode_attr; 136 | void create_fsevent_from_kevent(vnode_t vp, uint32_t kevents, struct vnode_attr *vap); 137 | 138 | // misc utility functions for fsevent info and pathbuffers... 139 | typedef struct fse_info { 140 | ino64_t ino; 141 | dev_t dev; 142 | int32_t mode;// note: this is not a mode_t (it's 32-bits, not 16) 143 | uid_t uid; 144 | gid_t gid; 145 | uint64_t nlink;// only filled in if the vnode is marked as a hardlink 146 | } fse_info; 147 | 148 | int get_fse_info(struct vnode *vp, fse_info *fse, vfs_context_t ctx); 149 | int vnode_get_fse_info_from_vap(vnode_t vp, fse_info *fse, struct vnode_attr *vap); 150 | 151 | char *get_pathbuff(void); 152 | void release_pathbuff(char *path); 153 | 154 | #endif /* BSD_KERNEL_PRIVATE */ 155 | 156 | #ifdef KERNEL_PRIVATE 157 | 158 | int need_fsevent(int type, vnode_t vp); 159 | int add_fsevent(int type, vfs_context_t, ...); 160 | 161 | #endif /* KERNEL_PRIVATE */ 162 | 163 | #endif /* FSEVENT_H */ 164 | -------------------------------------------------------------------------------- /demos/IDP-dema.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 23 | 25 | 26 | 28 | 29 | 30 | 32 | 33 | 35 | 36 | 38 | 39 | 41 | 42 | 44 | 45 | 47 | 48 | 50 | 51 | 53 | 54 | 56 | 57 | 59 | 60 | 62 | 63 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /demos/IDP-dema.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/IDP-dema.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/IDP-dema.xcworkspace/xcshareddata/xcschemes/Build all.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 57 | 63 | 64 | 65 | 71 | 77 | 78 | 79 | 85 | 91 | 92 | 93 | 99 | 105 | 106 | 107 | 113 | 119 | 120 | 121 | 127 | 133 | 134 | 135 | 141 | 147 | 148 | 149 | 155 | 161 | 162 | 163 | 169 | 175 | 176 | 177 | 178 | 179 | 184 | 185 | 186 | 187 | 197 | 198 | 204 | 205 | 206 | 207 | 213 | 215 | 221 | 222 | 223 | 224 | 226 | 227 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /demos/IOKit demo/IOKit demo.xcodeproj/xcshareddata/xcschemes/IOKit demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /demos/IOKit demo/IOKit demo/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // IOKit demo 4 | // 5 | // Created by Jozef on 09/08/2019. 6 | // Copyright © 2019 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Source: OS X and iOS Kernel Programming 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "../../../Common/SignalHandler.hpp" 17 | 18 | // Structure to describe a driver instance. 19 | struct MyDriverData { 20 | io_service_t service; 21 | io_object_t notification; 22 | } ; 23 | 24 | 25 | class IOKitMonitorTrampoline 26 | { 27 | public: 28 | static void DeviceAdded( void* _Nonnull context, io_iterator_t iterator); 29 | static void DeviceNotification ( void* _Nonnull context, io_service_t service, natural_t messageType, void* _Nonnull messageArgument); 30 | }; 31 | 32 | class IOKitMonitor 33 | { 34 | _Nullable CFDictionaryRef matching_dict = NULL; 35 | /// Iterator which is set when a IOService match is found 36 | io_iterator_t iter = 0; 37 | /// Notification port used for both device arrival and driver state changes 38 | _Nullable IONotificationPortRef notification_port = NULL; 39 | /// A run loop source used for receiving device notifications 40 | _Nullable CFRunLoopSourceRef event_source = NULL; 41 | 42 | public: 43 | void DeviceAdded(void* _Nonnull context, io_iterator_t iterator); 44 | void DeviceNotification (void* _Nonnull context, io_service_t service, natural_t messageType, void* _Nonnull messageArgument); 45 | void Init(); 46 | void Uninit(); 47 | 48 | }; 49 | 50 | 51 | void IOKitMonitorTrampoline::DeviceAdded(void* context, io_iterator_t iterator) 52 | { 53 | if (context == nullptr) 54 | return; 55 | static_cast(context)->DeviceAdded(context, iterator); 56 | } 57 | 58 | void IOKitMonitorTrampoline::DeviceNotification(void* context, io_service_t service, natural_t messageType, void* messageArgument) 59 | { 60 | if (context == nullptr) 61 | return; 62 | 63 | // Context contains a pointer to pair of pointers to IOKit monitor class and driver data, respectively. 64 | auto *data = static_cast *>(context); 65 | IOKitMonitor * const iokit_monitor = data->first; 66 | 67 | if (iokit_monitor == nullptr) 68 | return; 69 | 70 | iokit_monitor->DeviceNotification(data, service, messageType, messageArgument); 71 | } 72 | 73 | 74 | void IOKitMonitor::Init() 75 | { 76 | // Create a matching dictionary that will find any USB device 77 | matching_dict = IOServiceMatching("IOUSBDevice"); 78 | if (!matching_dict) 79 | return; 80 | 81 | notification_port = IONotificationPortCreate(kIOMasterPortDefault); 82 | event_source = IONotificationPortGetRunLoopSource(notification_port); 83 | CFRunLoopAddSource(CFRunLoopGetCurrent(), event_source, kCFRunLoopDefaultMode); 84 | IOServiceAddMatchingNotification(notification_port, kIOFirstMatchNotification, 85 | matching_dict, IOKitMonitorTrampoline::DeviceAdded, this, &iter); 86 | 87 | // Remove our interest in the source. Now the run loop is responsible for retaining it until it's done 88 | CFRelease(event_source); 89 | 90 | // Arm the notification 91 | IOKitMonitorTrampoline::DeviceAdded(this, iter); 92 | } 93 | 94 | void IOKitMonitor::Uninit() 95 | { 96 | // Release the iterator 97 | if (iter) { 98 | IOObjectRelease(iter); 99 | iter = 0; 100 | } 101 | 102 | if (notification_port) { 103 | // http://web.archive.org/web/20140115103252/https://lists.apple.com/archives/darwin-drivers/2004/Sep/msg00058.html 104 | // We should call IONotificationPortDestroy() since it releases the runloop source. However we 105 | // got this source by calling IONotificationPortGetRunLoopSource() and following 106 | // "The Create Rule" we are not supposed to release it \o/. 107 | // So DO NOT call IONotificationPortDestroy(notification_port);! 108 | notification_port = NULL; 109 | } 110 | 111 | if (event_source) { 112 | //CFRunLoopRemoveSource Removes the source from the specific run loop you specify. 113 | // -- this might cause a crash if the runloop does not exist during this call (i.e. this 114 | // thread received a signal? - and uninit is called when runloop is closed) 115 | 116 | //CFRunLoopSourceInvalidate Renders the source invalid, and will remove it from all the run 117 | // loops where was added. 118 | // -- this removes the source from all the run loops it was added to, ignoring run loops that 119 | // now do not exist anymore. 120 | CFRunLoopSourceInvalidate(event_source); 121 | 122 | // The caller should not release this CFRunLoopSource. Just call IONotificationPortDestroy 123 | // to dispose of the IONotificationPortRef and the CFRunLoopSource when done. 124 | // (!!! documentation is wrong at this point (see releasing of notification_port comment below) 125 | // So DO NOT call CFRelease(event_source);! 126 | event_source = NULL; 127 | } 128 | } 129 | 130 | void IOKitMonitor::DeviceAdded(void* refCon, io_iterator_t iterator) 131 | { 132 | io_service_t service = 0; 133 | // Iterate over all matching objects. 134 | while ((service = IOIteratorNext(iterator)) != 0) 135 | { 136 | CFStringRef className; 137 | // List all IOUSBDevice objects, ignoring objects that subclass IOUSBDevice. 138 | className = IOObjectCopyClass(service); 139 | 140 | // Because of calling this function during inicialization to arm notifications, devices which are not USBs 141 | // might appear here as well. 142 | if (CFEqual(className, CFSTR("IOUSBDevice")) == true) 143 | { 144 | io_name_t name; 145 | IORegistryEntryGetName(service, name); 146 | std::cout << "Found device with name: " << name << std::endl; 147 | 148 | std::pair> *data = new std::pair>(this, std::make_unique()); 149 | // Save the io_service_t for this driver instance. 150 | data->second->service = service; 151 | // Install a callback to receive notification of driver state changes. 152 | kern_return_t kr = IOServiceAddInterestNotification(notification_port, 153 | service, // driver object 154 | kIOGeneralInterest, 155 | IOKitMonitorTrampoline::DeviceNotification, // callback 156 | data, // refCon passed to callback 157 | &(data->second->notification)); 158 | if (kr != KERN_SUCCESS) { 159 | delete data; 160 | continue; 161 | } 162 | } 163 | CFRelease(className); 164 | } 165 | } 166 | 167 | void IOKitMonitor::DeviceNotification(void* refCon, io_service_t service, natural_t messageType, 168 | void* messageArgument) 169 | { 170 | if (refCon == nullptr) 171 | return; 172 | 173 | auto *myDriverData = static_cast> *>(refCon); 174 | 175 | // Only handle driver termination notifications. 176 | if (messageType == kIOMessageServiceIsTerminated) 177 | { 178 | // Print the name of the removed device. 179 | io_name_t name; 180 | IORegistryEntryGetName(service, name); 181 | std::cout << "Device removed: " << name << std::endl;; 182 | 183 | // Remove the driver state change notification. 184 | IOObjectRelease(myDriverData->second->notification); 185 | // Release our reference to the driver object. 186 | IOObjectRelease(myDriverData->second->service); 187 | // Release our structure that holds the driver connection. 188 | delete myDriverData; 189 | } 190 | } 191 | 192 | int main(int argc, const char * argv[]) 193 | { 194 | InstallHandleSignalFromRunLoop(); 195 | 196 | const char* demoName = "IOKit"; 197 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 198 | 199 | std::cout << "(" << demoName << ") Hello, World!\n"; 200 | std::cout << "Point of interest: " << "All the external USB devices!\n" << std::endl; 201 | 202 | IOKitMonitor iom; 203 | iom.Init(); 204 | 205 | CFRunLoopRun(); 206 | 207 | iom.Uninit(); 208 | return 0; 209 | } 210 | -------------------------------------------------------------------------------- /demos/IOKit-driver demo/IOKit-driver demo.xcodeproj/xcshareddata/xcschemes/IOKit-driver demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /demos/IOKit-driver demo/IOKit-driver demo/IOKit_driver_demo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // IOKit_driver_demo.cpp 3 | // IOKit-driver demo 4 | // 5 | // Created by Jozef on 24/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Sources: 9 | // https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptIOKit/iokit_tutorial.html 10 | 11 | #include 12 | #include "IOKit_driver_demo.hpp" 13 | 14 | // This required macro defines the class's constructors, destructors, 15 | // and several other methods I/O Kit requires. 16 | OSDefineMetaClassAndStructors(com_test_driver_IOKit_driver_demo, IOService) 17 | 18 | // Define the driver's superclass. 19 | #define super IOService 20 | 21 | static const char* g_demoName = "IOKit-driver"; 22 | // The first instance method called on each instance of the driver class. 23 | // It's called only once on each instance. 24 | bool com_test_driver_IOKit_driver_demo::init(OSDictionary *dict) 25 | { 26 | if (!super::init(dict)) { 27 | IOLog("%s demo: super::init() failed.\n", g_demoName); 28 | return false; 29 | } 30 | 31 | IOLog("(%s) Hello, World!\n", g_demoName); 32 | IOLog("%s demo: Initializing\n", g_demoName); 33 | return true; 34 | } 35 | 36 | // The last method called on any objects. 37 | void com_test_driver_IOKit_driver_demo::free(void) 38 | { 39 | IOLog("%s demo: Freeing\n", g_demoName); 40 | super::free(); 41 | } 42 | 43 | // Called to communicate with hardware to determine wheter there is a match. 44 | // Leave the hardware in a good state upon return for other probing drivers. 45 | IOService *com_test_driver_IOKit_driver_demo::probe(IOService *provider, 46 | SInt32 *score) 47 | { 48 | IOService *result = super::probe(provider, score); 49 | IOLog("%s demo: Probing...\n", g_demoName); 50 | 51 | bool shouldBlock = true; // I.e., ask user.. 52 | if (shouldBlock) { 53 | (*score) = INT32_MAX; 54 | IOLog("%s demo: Blocking with score %d...\n", g_demoName, *score); 55 | return this; 56 | } 57 | 58 | // I ain't takin' it! 59 | return nullptr; 60 | } 61 | 62 | // Place for driver to set up its functionality. 63 | // After it's called, the driver can begin routing I/O, publishing nubs, and vending services. 64 | bool com_test_driver_IOKit_driver_demo::start(IOService *provider) 65 | { 66 | if (!super::start(provider)) { 67 | IOLog("%s demo: super::start() failed.\n", g_demoName); 68 | return false; 69 | } 70 | 71 | IOLog("%s demo: Starting\n", g_demoName); 72 | return true; 73 | } 74 | 75 | // The first method called before the driver is unloaded. Clean up! 76 | void com_test_driver_IOKit_driver_demo::stop(IOService *provider) 77 | { 78 | IOLog("(%s) Goodbye, World!\n", g_demoName); 79 | IOLog("%s demo: Stopping\n", g_demoName); 80 | super::stop(provider); 81 | } 82 | -------------------------------------------------------------------------------- /demos/IOKit-driver demo/IOKit-driver demo/IOKit_driver_demo.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // IOKit_driver_demo.hpp 3 | // IOKit-driver demo 4 | // 5 | // Created by Jozef on 28/05/2019. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | 9 | #include 10 | class com_test_driver_IOKit_driver_demo : public IOService 11 | { 12 | OSDeclareDefaultStructors(com_test_driver_IOKit_driver_demo) 13 | public: 14 | virtual bool init(OSDictionary *dictionary = 0) override; 15 | virtual void free(void) override; 16 | virtual IOService *probe(IOService *provider, SInt32 *score) override; 17 | virtual bool start(IOService *provider) override; 18 | virtual void stop(IOService *provider) override; 19 | }; 20 | -------------------------------------------------------------------------------- /demos/IOKit-driver demo/IOKit-driver demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | IOKitPersonalities 22 | 23 | PCI_driver 24 | 25 | IOClass 26 | ExampleIntel82558 27 | IOPCIMatch 28 | 0x12298086 29 | IOProbeScore 30 | 400 31 | IOProviderClass 32 | IOPCIDevice 33 | 34 | USB_driver 35 | 36 | CFBundleIdentifier 37 | $(PRODUCT_BUNDLE_IDENTIFIER) 38 | IOClass 39 | com_test_driver_IOKit_driver_demo 40 | IOKitDebug 41 | 65535 42 | IOMatchCategory 43 | com_test_driver_IOKit_driver_demo 44 | IOProviderClass 45 | IOUSBDevice 46 | idProduct 47 | * 48 | idVendor 49 | * 50 | 51 | 52 | NSHumanReadableCopyright 53 | Copyright © 2020 Jozef Zuzelka. All rights reserved. 54 | OSBundleLibraries 55 | 56 | com.apple.kpi.iokit 57 | 19.4 58 | com.apple.kpi.libkern 59 | 19.4 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /demos/OpenBSM demo/OpenBSM demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 09F7F908246C0E3100BB0662 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09F7F907246C0E3100BB0662 /* main.cpp */; }; 11 | 09F7F910246C1EC700BB0662 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 09F7F90F246C1EB900BB0662 /* libbsm.tbd */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 09F7F902246C0E3100BB0662 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 09F7F904246C0E3100BB0662 /* OpenBSM demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "OpenBSM demo"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 09F7F907246C0E3100BB0662 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 29 | 09F7F90F246C1EB900BB0662 /* libbsm.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbsm.tbd; path = usr/lib/libbsm.tbd; sourceTree = SDKROOT; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | 09F7F901246C0E3100BB0662 /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | 09F7F910246C1EC700BB0662 /* libbsm.tbd in Frameworks */, 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 09F7F8FB246C0E3100BB0662 = { 45 | isa = PBXGroup; 46 | children = ( 47 | 09F7F906246C0E3100BB0662 /* OpenBSM demo */, 48 | 09F7F905246C0E3100BB0662 /* Products */, 49 | 09F7F90E246C1EB900BB0662 /* Frameworks */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | 09F7F905246C0E3100BB0662 /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 09F7F904246C0E3100BB0662 /* OpenBSM demo */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | 09F7F906246C0E3100BB0662 /* OpenBSM demo */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 09F7F907246C0E3100BB0662 /* main.cpp */, 65 | ); 66 | path = "OpenBSM demo"; 67 | sourceTree = ""; 68 | }; 69 | 09F7F90E246C1EB900BB0662 /* Frameworks */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 09F7F90F246C1EB900BB0662 /* libbsm.tbd */, 73 | ); 74 | name = Frameworks; 75 | sourceTree = ""; 76 | }; 77 | /* End PBXGroup section */ 78 | 79 | /* Begin PBXNativeTarget section */ 80 | 09F7F903246C0E3100BB0662 /* OpenBSM demo */ = { 81 | isa = PBXNativeTarget; 82 | buildConfigurationList = 09F7F90B246C0E3100BB0662 /* Build configuration list for PBXNativeTarget "OpenBSM demo" */; 83 | buildPhases = ( 84 | 09F7F900246C0E3100BB0662 /* Sources */, 85 | 09F7F901246C0E3100BB0662 /* Frameworks */, 86 | 09F7F902246C0E3100BB0662 /* CopyFiles */, 87 | ); 88 | buildRules = ( 89 | ); 90 | dependencies = ( 91 | ); 92 | name = "OpenBSM demo"; 93 | productName = "OpenBSM demo"; 94 | productReference = 09F7F904246C0E3100BB0662 /* OpenBSM demo */; 95 | productType = "com.apple.product-type.tool"; 96 | }; 97 | /* End PBXNativeTarget section */ 98 | 99 | /* Begin PBXProject section */ 100 | 09F7F8FC246C0E3100BB0662 /* Project object */ = { 101 | isa = PBXProject; 102 | attributes = { 103 | LastUpgradeCheck = 1150; 104 | ORGANIZATIONNAME = "Jozef Zuzelka"; 105 | TargetAttributes = { 106 | 09F7F903246C0E3100BB0662 = { 107 | CreatedOnToolsVersion = 11.4.1; 108 | }; 109 | }; 110 | }; 111 | buildConfigurationList = 09F7F8FF246C0E3100BB0662 /* Build configuration list for PBXProject "OpenBSM demo" */; 112 | compatibilityVersion = "Xcode 9.3"; 113 | developmentRegion = en; 114 | hasScannedForEncodings = 0; 115 | knownRegions = ( 116 | en, 117 | Base, 118 | ); 119 | mainGroup = 09F7F8FB246C0E3100BB0662; 120 | productRefGroup = 09F7F905246C0E3100BB0662 /* Products */; 121 | projectDirPath = ""; 122 | projectRoot = ""; 123 | targets = ( 124 | 09F7F903246C0E3100BB0662 /* OpenBSM demo */, 125 | ); 126 | }; 127 | /* End PBXProject section */ 128 | 129 | /* Begin PBXSourcesBuildPhase section */ 130 | 09F7F900246C0E3100BB0662 /* Sources */ = { 131 | isa = PBXSourcesBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | 09F7F908246C0E3100BB0662 /* main.cpp in Sources */, 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXSourcesBuildPhase section */ 139 | 140 | /* Begin XCBuildConfiguration section */ 141 | 09F7F909246C0E3100BB0662 /* Debug */ = { 142 | isa = XCBuildConfiguration; 143 | buildSettings = { 144 | ALWAYS_SEARCH_USER_PATHS = NO; 145 | CLANG_ANALYZER_NONNULL = YES; 146 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 147 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 148 | CLANG_CXX_LIBRARY = "libc++"; 149 | CLANG_ENABLE_MODULES = YES; 150 | CLANG_ENABLE_OBJC_ARC = YES; 151 | CLANG_ENABLE_OBJC_WEAK = YES; 152 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 153 | CLANG_WARN_BOOL_CONVERSION = YES; 154 | CLANG_WARN_COMMA = YES; 155 | CLANG_WARN_CONSTANT_CONVERSION = YES; 156 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 157 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 158 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 159 | CLANG_WARN_EMPTY_BODY = YES; 160 | CLANG_WARN_ENUM_CONVERSION = YES; 161 | CLANG_WARN_INFINITE_RECURSION = YES; 162 | CLANG_WARN_INT_CONVERSION = YES; 163 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 164 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 165 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 166 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 167 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 168 | CLANG_WARN_STRICT_PROTOTYPES = YES; 169 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 170 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 171 | CLANG_WARN_UNREACHABLE_CODE = YES; 172 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 173 | COPY_PHASE_STRIP = NO; 174 | DEBUG_INFORMATION_FORMAT = dwarf; 175 | ENABLE_STRICT_OBJC_MSGSEND = YES; 176 | ENABLE_TESTABILITY = YES; 177 | GCC_C_LANGUAGE_STANDARD = gnu11; 178 | GCC_DYNAMIC_NO_PIC = NO; 179 | GCC_NO_COMMON_BLOCKS = YES; 180 | GCC_OPTIMIZATION_LEVEL = 0; 181 | GCC_PREPROCESSOR_DEFINITIONS = ( 182 | "DEBUG=1", 183 | "$(inherited)", 184 | ); 185 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 186 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 187 | GCC_WARN_UNDECLARED_SELECTOR = YES; 188 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 189 | GCC_WARN_UNUSED_FUNCTION = YES; 190 | GCC_WARN_UNUSED_VARIABLE = YES; 191 | MACOSX_DEPLOYMENT_TARGET = 10.15; 192 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 193 | MTL_FAST_MATH = YES; 194 | ONLY_ACTIVE_ARCH = YES; 195 | SDKROOT = macosx; 196 | }; 197 | name = Debug; 198 | }; 199 | 09F7F90A246C0E3100BB0662 /* Release */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | ALWAYS_SEARCH_USER_PATHS = NO; 203 | CLANG_ANALYZER_NONNULL = YES; 204 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 205 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 206 | CLANG_CXX_LIBRARY = "libc++"; 207 | CLANG_ENABLE_MODULES = YES; 208 | CLANG_ENABLE_OBJC_ARC = YES; 209 | CLANG_ENABLE_OBJC_WEAK = YES; 210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_COMMA = YES; 213 | CLANG_WARN_CONSTANT_CONVERSION = YES; 214 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INFINITE_RECURSION = YES; 220 | CLANG_WARN_INT_CONVERSION = YES; 221 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 223 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 225 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 226 | CLANG_WARN_STRICT_PROTOTYPES = YES; 227 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 228 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 229 | CLANG_WARN_UNREACHABLE_CODE = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | COPY_PHASE_STRIP = NO; 232 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 233 | ENABLE_NS_ASSERTIONS = NO; 234 | ENABLE_STRICT_OBJC_MSGSEND = YES; 235 | GCC_C_LANGUAGE_STANDARD = gnu11; 236 | GCC_NO_COMMON_BLOCKS = YES; 237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 238 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 239 | GCC_WARN_UNDECLARED_SELECTOR = YES; 240 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 241 | GCC_WARN_UNUSED_FUNCTION = YES; 242 | GCC_WARN_UNUSED_VARIABLE = YES; 243 | MACOSX_DEPLOYMENT_TARGET = 10.15; 244 | MTL_ENABLE_DEBUG_INFO = NO; 245 | MTL_FAST_MATH = YES; 246 | SDKROOT = macosx; 247 | }; 248 | name = Release; 249 | }; 250 | 09F7F90C246C0E3100BB0662 /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 254 | CODE_SIGN_IDENTITY = "-"; 255 | CODE_SIGN_STYLE = Automatic; 256 | DEVELOPMENT_TEAM = VN555WY3S4; 257 | ENABLE_HARDENED_RUNTIME = YES; 258 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.openbsm-demo"; 259 | PRODUCT_NAME = "$(TARGET_NAME)"; 260 | }; 261 | name = Debug; 262 | }; 263 | 09F7F90D246C0E3100BB0662 /* Release */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 267 | CODE_SIGN_IDENTITY = "-"; 268 | CODE_SIGN_STYLE = Automatic; 269 | DEVELOPMENT_TEAM = VN555WY3S4; 270 | ENABLE_HARDENED_RUNTIME = YES; 271 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.openbsm-demo"; 272 | PRODUCT_NAME = "$(TARGET_NAME)"; 273 | }; 274 | name = Release; 275 | }; 276 | /* End XCBuildConfiguration section */ 277 | 278 | /* Begin XCConfigurationList section */ 279 | 09F7F8FF246C0E3100BB0662 /* Build configuration list for PBXProject "OpenBSM demo" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | 09F7F909246C0E3100BB0662 /* Debug */, 283 | 09F7F90A246C0E3100BB0662 /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | defaultConfigurationName = Release; 287 | }; 288 | 09F7F90B246C0E3100BB0662 /* Build configuration list for PBXNativeTarget "OpenBSM demo" */ = { 289 | isa = XCConfigurationList; 290 | buildConfigurations = ( 291 | 09F7F90C246C0E3100BB0662 /* Debug */, 292 | 09F7F90D246C0E3100BB0662 /* Release */, 293 | ); 294 | defaultConfigurationIsVisible = 0; 295 | defaultConfigurationName = Release; 296 | }; 297 | /* End XCConfigurationList section */ 298 | }; 299 | rootObject = 09F7F8FC246C0E3100BB0662 /* Project object */; 300 | } 301 | -------------------------------------------------------------------------------- /demos/OpenBSM demo/OpenBSM demo.xcodeproj/xcshareddata/xcschemes/OpenBSM demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /demos/OpenBSM demo/OpenBSM demo/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // OpenBSM demo 4 | // 5 | // Created by Jozef on 13/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Source: https://github.com/meliot/filewatcher 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include // geteuid 16 | 17 | std::atomic g_shouldStop {false}; 18 | 19 | FILE *initPipe(); 20 | void readPrintToken(FILE* auditFile); 21 | 22 | void signalHandler(int signum) 23 | { 24 | // Not safe, but whatever 25 | std::cerr << "Interrupt signal (" << signum << ") received, exiting." << std::endl; 26 | g_shouldStop = true; 27 | } 28 | 29 | int main() 30 | { 31 | // No runloop, no problem 32 | signal(SIGINT, signalHandler); 33 | signal(SIGTERM, signalHandler); 34 | signal(SIGABRT, signalHandler); 35 | 36 | const char* demoName = "OpenBSM"; 37 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 38 | 39 | std::cout << "(" << demoName << ") Hello, World!\n"; 40 | std::cout << "Point of interest: " << "All the events!" << std::endl << std::endl; 41 | 42 | FILE *auditFile = initPipe(); 43 | 44 | while(!g_shouldStop) 45 | readPrintToken(auditFile); 46 | 47 | fclose(auditFile); 48 | return EXIT_SUCCESS; 49 | } 50 | 51 | 52 | FILE *initPipe() 53 | { 54 | // Open the device 55 | FILE* auditFile = fopen("/dev/auditpipe", "r"); 56 | 57 | if (geteuid()) 58 | std::cerr << "Opening /dev/auditpipe requires root permissions\n"; 59 | 60 | if (auditFile == nullptr) { 61 | std::cerr << "Could not open the device\n"; 62 | exit(1); 63 | } 64 | int auditFileDescriptor = fileno(auditFile); 65 | 66 | 67 | 68 | // Configure the audit pipe 69 | int mode = AUDITPIPE_PRESELECT_MODE_LOCAL; 70 | int ioctlReturn = ioctl(auditFileDescriptor, 71 | AUDITPIPE_SET_PRESELECT_MODE, 72 | &mode); 73 | if (ioctlReturn == -1) { 74 | std::cerr << "Unable to set the audit pipe mode to local.\n"; 75 | perror("Error "); 76 | return nullptr; 77 | } 78 | 79 | int queueLength; 80 | ioctlReturn = ioctl(auditFileDescriptor, 81 | AUDITPIPE_GET_QLIMIT_MAX, 82 | &queueLength); 83 | if (ioctlReturn == -1) { 84 | std::cerr << "Unable to get the maximum queue length of the audit pipe.\n"; 85 | perror("Error "); 86 | return nullptr; 87 | } 88 | 89 | ioctlReturn = ioctl(auditFileDescriptor, 90 | AUDITPIPE_SET_QLIMIT, 91 | &queueLength); 92 | if (ioctlReturn == -1) { 93 | std::cerr << "Unable to set the queue length of the audit pipe.\n"; 94 | perror("Error "); 95 | return nullptr; 96 | } 97 | 98 | // According with /etc/security/audit_class 99 | u_int attributableEventsMask = 100 | //0x00000000 | // Invalid Class (no) 101 | 0x00000001 | // File read (fr) 102 | 0x00000002 | // File write (fw) 103 | 0x00000004 | // File attribute access (fa) 104 | 0x00000008 | // File attribute modify (fm) 105 | 0x00000010 | // File create (fc) 106 | 0x00000020 | // File delete (fd) 107 | 0x00000040 ; // File close (cl) 108 | //0x00000080 | // Process (pc) 109 | //0x00000100 | // Network (nt) 110 | //0x00000200 | // IPC (ip) 111 | //0x00000400 | // Non attributable (na) 112 | //0x00000800 | // Administrative (ad) 113 | //0x00001000 | // Login/Logout (lo) 114 | //0x00002000 | // Authentication and authorization (aa) 115 | //0x00004000 | // Application (ap) 116 | //0x20000000 | // ioctl (io) 117 | //0x40000000 | // exec (ex) 118 | //0x80000000 | // Miscellaneous (ot) 119 | //0xffffffff ; // All flags set (all) 120 | ioctlReturn = ioctl(auditFileDescriptor, 121 | AUDITPIPE_SET_PRESELECT_FLAGS, 122 | &attributableEventsMask); 123 | if (ioctlReturn == -1) { 124 | std::cerr << "Unable to set the attributable events preselection mask.\n"; 125 | perror("Error "); 126 | return nullptr; 127 | } 128 | 129 | u_int nonAttributableEventsMask = attributableEventsMask; 130 | ioctlReturn = ioctl(auditFileDescriptor, 131 | AUDITPIPE_SET_PRESELECT_NAFLAGS, 132 | &nonAttributableEventsMask); 133 | if (ioctlReturn == -1) { 134 | std::cerr << "Unable to set the non-attributable events preselection mask.\n"; 135 | perror("Error "); 136 | return nullptr; 137 | } 138 | 139 | return auditFile; 140 | } 141 | 142 | void readPrintToken(FILE* auditFile) 143 | { 144 | u_char* buffer; 145 | int recordLength = au_read_rec(auditFile, &buffer); 146 | if (recordLength == -1) 147 | return; 148 | 149 | int recordBalance = recordLength; 150 | int processedLength = 0; 151 | tokenstr_t token; 152 | 153 | while (recordBalance) { 154 | // Extract a token from the record 155 | int fetchToken = au_fetch_tok(&token, buffer + processedLength, recordBalance); 156 | if (fetchToken == -1) { 157 | std::cerr << "Error fetching token.\n"; 158 | break; 159 | } 160 | 161 | char* dlmtr = "\n"; 162 | au_print_flags_tok(stdout, &token, dlmtr, AU_OFLAG_XML); 163 | std::cout << std::endl; 164 | processedLength += token.len; 165 | recordBalance -= token.len; 166 | } 167 | std::cout << std::endl; 168 | std::cout << std::endl; 169 | free(buffer); 170 | } 171 | -------------------------------------------------------------------------------- /demos/dev-blocker demo/Makefile: -------------------------------------------------------------------------------- 1 | # @file Makefile 2 | # @brief Brief description 3 | # @author Jozef Zuzelka 4 | # @date 5 | # - Created: 04.06.2020 15:43 6 | # - Edited: 04.06.2020 15:43 7 | # @version 1.0.0 8 | # @par make: GNU Make 3.81 9 | # @bug 10 | # @todo 11 | 12 | 13 | TARGET=test 14 | 15 | CXX=g++ 16 | CXXFLAGS=-std=c++17 -pedantic -Wall -Wextra -g 17 | LDFLAGS= 18 | .PHONY: clean 19 | 20 | #$(TARGET): $(TARGET).o 21 | # $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) 22 | 23 | #%: %.cpp 24 | # $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) 25 | 26 | all : $(TARGET) 27 | 28 | clean: 29 | -rm $(TARGET) $(TARGET).o 30 | -------------------------------------------------------------------------------- /demos/dev-blocker demo/test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test.c 3 | * @brief Brief description 4 | * @author Jozef Zuzelka 5 | * @date 6 | * - Created: 01.06.2020 01:45 7 | * - Edited: 04.06.2020 15:50 8 | * @version 1.0.0 9 | * @par gcc: Apple clang version 11.0.3 (clang-1103.0.32.62) 10 | * @bug 11 | * @todo 12 | */ 13 | 14 | #include 15 | #include 16 | #include // fopen(3) 17 | #include // close(2) 18 | #include // open(2) 19 | 20 | int main() 21 | { 22 | #if 0 23 | FILE* f1 = fopen("/dev/disk2", "r"); 24 | if (f1 == NULL) 25 | perror("disk2"); 26 | int res1 = flock(fileno(f1), LOCK_EX | LOCK_NB); 27 | if (res1) 28 | perror("disk2 flock"); 29 | 30 | FILE* f2 = fopen("/dev/disk2s1", "r"); 31 | if (f2 == NULL) 32 | perror("disk2s1"); 33 | int res2 = flock(fileno(f2), LOCK_EX | LOCK_NB); 34 | if (res2) 35 | perror("disk2s1 flock"); 36 | 37 | while (1) 38 | ; 39 | 40 | fclose(f1); 41 | fclose(f2); 42 | #else 43 | 44 | int f1 = open("/dev/disk2", O_RDWR | O_EXLOCK); 45 | if (f1 == -1) 46 | perror("disk2"); 47 | 48 | int f2 = open("/dev/disk2s1", O_RDWR | O_EXLOCK); 49 | if (f2 == -1) 50 | perror("disk2s1"); 51 | 52 | while (1) 53 | ; 54 | 55 | close(f1); 56 | close(f2); 57 | #endif 58 | return 0; 59 | } 60 | 61 | 62 | /* vim: set ts=4 sw=4 tw=0 et :*/ 63 | -------------------------------------------------------------------------------- /demos/dext demo/dext demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | IOKitPersonalities 22 | 23 | dext_demo 24 | 25 | CFBundleIdentifier 26 | $(PRODUCT_BUNDLE_IDENTIFIER) 27 | CFBundleIdentifierKernel 28 | com.apple.kpi.iokit 29 | IOClass 30 | IOUserService 31 | IOMatchCategory 32 | com.apple.null.driver 33 | IOProviderClass 34 | IOUserResources 35 | IOResourceMatch 36 | IOKit 37 | IOUserClass 38 | dext_demo 39 | IOUserServerName 40 | com.apple.null.driver 41 | 42 | 43 | OSBundleUsageDescription 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /demos/dext demo/dext demo/dext_demo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // dext_demo.cpp 3 | // dext demo 4 | // 5 | // Created by Jozef on 06/06/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Sources: 9 | // https://github.com/knightsc/USBApp/ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | //#include 17 | //#include 18 | 19 | #include "dext_demo.h" 20 | 21 | 22 | #define __Require(assertion, exceptionLabel) \ 23 | do { \ 24 | if ( __builtin_expect(!(assertion), 0) ) { \ 25 | goto exceptionLabel; \ 26 | } \ 27 | } while (0) 28 | 29 | #define __Require_Action(assertion, exceptionLabel, action) \ 30 | do { \ 31 | if ( __builtin_expect(!(assertion), 0) ) { \ 32 | { \ 33 | action; \ 34 | } \ 35 | goto exceptionLabel; \ 36 | } \ 37 | } while (0) 38 | 39 | static const uint32_t kMyEndpointAddress = 1; 40 | 41 | struct dext_demo_IVars 42 | { 43 | IOUSBHostInterface *interface; 44 | IOUSBHostPipe *inPipe; 45 | OSAction *ioCompleteCallback; 46 | IOBufferMemoryDescriptor *inData; 47 | uint16_t maxPacketSize; 48 | }; 49 | 50 | bool dext_demo::init() 51 | { 52 | bool result = false; 53 | 54 | os_log(OS_LOG_DEFAULT, "%s", __FUNCTION__); 55 | 56 | result = super::init(); 57 | __Require(true == result, Exit); 58 | 59 | ivars = /*(IOService_IVars *)*/ IONewZero(dext_demo_IVars, 1); 60 | __Require_Action(NULL != ivars, Exit, result = false); 61 | 62 | Exit: 63 | return result; 64 | } 65 | 66 | kern_return_t IMPL(dext_demo, Start) 67 | { 68 | kern_return_t ret; 69 | IOUSBStandardEndpointDescriptors descriptors; 70 | 71 | os_log(OS_LOG_DEFAULT, "%s", __FUNCTION__); 72 | dext_demo_IVars *ivars_local = (dext_demo_IVars *) ivars; 73 | 74 | ret = Start(provider, SUPERDISPATCH); 75 | __Require(kIOReturnSuccess == ret, Exit); 76 | os_log(OS_LOG_DEFAULT, "Hello World"); 77 | 78 | // ivars_local->interface = OSDynamicCast(IOUSBHostInterface, provider); 79 | // __Require_Action(NULL != ivars_local->interface, Exit, ret = kIOReturnNoDevice); 80 | // 81 | // ret = ivars_local->interface->Open(this, 0, NULL); 82 | // __Require(kIOReturnSuccess == ret, Exit); 83 | // 84 | // ret = ivars_local->interface->CopyPipe(kMyEndpointAddress, &ivars_local->inPipe); 85 | // __Require(kIOReturnSuccess == ret, Exit); 86 | // 87 | // ret = ivars_local->interface->CreateIOBuffer(kIOMemoryDirectionIn, 88 | // ivars_local->maxPacketSize, 89 | // &ivars_local->inData); 90 | // __Require(kIOReturnSuccess == ret, Exit); 91 | 92 | // ret = OSAction::Create(this, 93 | // MyUserUSBInterfaceDriver_ReadComplete_ID, 94 | // IOUSBHostPipe_CompleteAsyncIO_ID, 95 | // 0, 96 | // &ivars_local->ioCompleteCallback); 97 | // __Require(kIOReturnSuccess == ret, Exit); 98 | // 99 | // ret = ivars_local->inPipe->AsyncIO(ivars_local->inData, 100 | // ivars_local->maxPacketSize, 101 | // ivars_local->ioCompleteCallback, 102 | // 0); 103 | // __Require(kIOReturnSuccess == ret, Exit); 104 | 105 | // WWDC slides don't show the full function https://developer.apple.com/videos/play/wwdc2019/702/?time=1418 106 | // i.e. this is still unfinished 107 | 108 | Exit: 109 | return ret; 110 | } 111 | 112 | kern_return_t IMPL(dext_demo, Stop) 113 | { 114 | kern_return_t ret = kIOReturnSuccess; 115 | 116 | os_log(OS_LOG_DEFAULT, "%s", __FUNCTION__); 117 | 118 | return ret; 119 | } 120 | 121 | void dext_demo::free() 122 | { 123 | os_log(OS_LOG_DEFAULT, "%s", __FUNCTION__); 124 | } 125 | 126 | void IMPL(dext_demo, ReadComplete) 127 | { 128 | os_log(OS_LOG_DEFAULT, "%s", __FUNCTION__); 129 | 130 | os_log(OS_LOG_DEFAULT, "Spinning forever\n"); 131 | bool loop = true; 132 | while (true == loop) { } 133 | 134 | os_log(OS_LOG_DEFAULT, "Goodbye\n"); 135 | *(volatile uint32_t *)0 = 0xdeadbeef; 136 | } 137 | -------------------------------------------------------------------------------- /demos/dext demo/dext demo/dext_demo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.driverkit 6 | 7 | com.apple.security.app-sandbox 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demos/dext demo/dext demo/dext_demo.iig: -------------------------------------------------------------------------------- 1 | // 2 | // dext_demo.iig 3 | // dext demo 4 | // 5 | // Created by Jozef on 06/06/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | 9 | #ifndef dext_demo_h 10 | #define dext_demo_h 11 | 12 | #include 13 | #include 14 | 15 | //class OSAction; 16 | class dext_demo: public IOService 17 | { 18 | public: 19 | virtual bool init() override; 20 | virtual kern_return_t Start(IOService *provider) override; 21 | virtual kern_return_t Stop(IOService *provider) override; 22 | virtual void free() override; 23 | 24 | protected: 25 | virtual void ReadComplete(OSAction *actifon, 26 | IOReturn statfus, 27 | uint32_t actufalByteCount, 28 | uint64_t complfetionTimestamp); 29 | //TYPE(IOUSBHostPipe::CompleteAsyncIO); 30 | // says: Assertion failed: (meth->typeMethod), function Construct, file iig/iig.cpp, line 998. 31 | 32 | 33 | }; 34 | 35 | #endif /* dext_demo_h */ 36 | -------------------------------------------------------------------------------- /demos/generic-kext demo/generic-kext demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 09275C3F247FCA8F0057A737 /* generic_kext_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 09275C3E247FCA8F0057A737 /* generic_kext_demo.c */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | 09275C3B247FCA8F0057A737 /* generic-kext demo.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "generic-kext demo.kext"; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | 09275C3E247FCA8F0057A737 /* generic_kext_demo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = generic_kext_demo.c; sourceTree = ""; }; 16 | 09275C40247FCA8F0057A737 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 17 | 09275C47247FCE260057A737 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; 18 | /* End PBXFileReference section */ 19 | 20 | /* Begin PBXFrameworksBuildPhase section */ 21 | 09275C38247FCA8F0057A737 /* Frameworks */ = { 22 | isa = PBXFrameworksBuildPhase; 23 | buildActionMask = 2147483647; 24 | files = ( 25 | ); 26 | runOnlyForDeploymentPostprocessing = 0; 27 | }; 28 | /* End PBXFrameworksBuildPhase section */ 29 | 30 | /* Begin PBXGroup section */ 31 | 09275C31247FCA8F0057A737 = { 32 | isa = PBXGroup; 33 | children = ( 34 | 09275C3D247FCA8F0057A737 /* generic-kext demo */, 35 | 09275C3C247FCA8F0057A737 /* Products */, 36 | 09275C46247FCE260057A737 /* Frameworks */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | 09275C3C247FCA8F0057A737 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 09275C3B247FCA8F0057A737 /* generic-kext demo.kext */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | 09275C3D247FCA8F0057A737 /* generic-kext demo */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 09275C3E247FCA8F0057A737 /* generic_kext_demo.c */, 52 | 09275C40247FCA8F0057A737 /* Info.plist */, 53 | ); 54 | path = "generic-kext demo"; 55 | sourceTree = ""; 56 | }; 57 | 09275C46247FCE260057A737 /* Frameworks */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 09275C47247FCE260057A737 /* Kernel.framework */, 61 | ); 62 | name = Frameworks; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXHeadersBuildPhase section */ 68 | 09275C36247FCA8F0057A737 /* Headers */ = { 69 | isa = PBXHeadersBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXHeadersBuildPhase section */ 76 | 77 | /* Begin PBXNativeTarget section */ 78 | 09275C3A247FCA8F0057A737 /* generic-kext demo */ = { 79 | isa = PBXNativeTarget; 80 | buildConfigurationList = 09275C43247FCA8F0057A737 /* Build configuration list for PBXNativeTarget "generic-kext demo" */; 81 | buildPhases = ( 82 | 09275C36247FCA8F0057A737 /* Headers */, 83 | 09275C37247FCA8F0057A737 /* Sources */, 84 | 09275C38247FCA8F0057A737 /* Frameworks */, 85 | 09275C39247FCA8F0057A737 /* Resources */, 86 | ); 87 | buildRules = ( 88 | ); 89 | dependencies = ( 90 | ); 91 | name = "generic-kext demo"; 92 | productName = "generic-kext demo"; 93 | productReference = 09275C3B247FCA8F0057A737 /* generic-kext demo.kext */; 94 | productType = "com.apple.product-type.kernel-extension"; 95 | }; 96 | /* End PBXNativeTarget section */ 97 | 98 | /* Begin PBXProject section */ 99 | 09275C32247FCA8F0057A737 /* Project object */ = { 100 | isa = PBXProject; 101 | attributes = { 102 | LastUpgradeCheck = 1150; 103 | ORGANIZATIONNAME = "Jozef Zuzelka"; 104 | TargetAttributes = { 105 | 09275C3A247FCA8F0057A737 = { 106 | CreatedOnToolsVersion = 11.5; 107 | }; 108 | }; 109 | }; 110 | buildConfigurationList = 09275C35247FCA8F0057A737 /* Build configuration list for PBXProject "generic-kext demo" */; 111 | compatibilityVersion = "Xcode 9.3"; 112 | developmentRegion = en; 113 | hasScannedForEncodings = 0; 114 | knownRegions = ( 115 | en, 116 | Base, 117 | ); 118 | mainGroup = 09275C31247FCA8F0057A737; 119 | productRefGroup = 09275C3C247FCA8F0057A737 /* Products */; 120 | projectDirPath = ""; 121 | projectRoot = ""; 122 | targets = ( 123 | 09275C3A247FCA8F0057A737 /* generic-kext demo */, 124 | ); 125 | }; 126 | /* End PBXProject section */ 127 | 128 | /* Begin PBXResourcesBuildPhase section */ 129 | 09275C39247FCA8F0057A737 /* Resources */ = { 130 | isa = PBXResourcesBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | /* End PBXResourcesBuildPhase section */ 137 | 138 | /* Begin PBXSourcesBuildPhase section */ 139 | 09275C37247FCA8F0057A737 /* Sources */ = { 140 | isa = PBXSourcesBuildPhase; 141 | buildActionMask = 2147483647; 142 | files = ( 143 | 09275C3F247FCA8F0057A737 /* generic_kext_demo.c in Sources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXSourcesBuildPhase section */ 148 | 149 | /* Begin XCBuildConfiguration section */ 150 | 09275C41247FCA8F0057A737 /* Debug */ = { 151 | isa = XCBuildConfiguration; 152 | buildSettings = { 153 | ALWAYS_SEARCH_USER_PATHS = NO; 154 | CLANG_ANALYZER_NONNULL = YES; 155 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 156 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 157 | CLANG_CXX_LIBRARY = "libc++"; 158 | CLANG_ENABLE_MODULES = YES; 159 | CLANG_ENABLE_OBJC_ARC = YES; 160 | CLANG_ENABLE_OBJC_WEAK = YES; 161 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 162 | CLANG_WARN_BOOL_CONVERSION = YES; 163 | CLANG_WARN_COMMA = YES; 164 | CLANG_WARN_CONSTANT_CONVERSION = YES; 165 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 166 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 167 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 168 | CLANG_WARN_EMPTY_BODY = YES; 169 | CLANG_WARN_ENUM_CONVERSION = YES; 170 | CLANG_WARN_INFINITE_RECURSION = YES; 171 | CLANG_WARN_INT_CONVERSION = YES; 172 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 173 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 174 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 175 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 176 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 177 | CLANG_WARN_STRICT_PROTOTYPES = YES; 178 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 179 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 180 | CLANG_WARN_UNREACHABLE_CODE = YES; 181 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 182 | COPY_PHASE_STRIP = NO; 183 | DEBUG_INFORMATION_FORMAT = dwarf; 184 | ENABLE_STRICT_OBJC_MSGSEND = YES; 185 | ENABLE_TESTABILITY = YES; 186 | GCC_C_LANGUAGE_STANDARD = gnu11; 187 | GCC_DYNAMIC_NO_PIC = NO; 188 | GCC_NO_COMMON_BLOCKS = YES; 189 | GCC_OPTIMIZATION_LEVEL = 0; 190 | GCC_PREPROCESSOR_DEFINITIONS = ( 191 | "DEBUG=1", 192 | "$(inherited)", 193 | ); 194 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 195 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 196 | GCC_WARN_UNDECLARED_SELECTOR = YES; 197 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 198 | GCC_WARN_UNUSED_FUNCTION = YES; 199 | GCC_WARN_UNUSED_VARIABLE = YES; 200 | MACOSX_DEPLOYMENT_TARGET = 10.15; 201 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 202 | MTL_FAST_MATH = YES; 203 | ONLY_ACTIVE_ARCH = YES; 204 | SDKROOT = macosx; 205 | }; 206 | name = Debug; 207 | }; 208 | 09275C42247FCA8F0057A737 /* Release */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | CLANG_ANALYZER_NONNULL = YES; 213 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 214 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 215 | CLANG_CXX_LIBRARY = "libc++"; 216 | CLANG_ENABLE_MODULES = YES; 217 | CLANG_ENABLE_OBJC_ARC = YES; 218 | CLANG_ENABLE_OBJC_WEAK = YES; 219 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 220 | CLANG_WARN_BOOL_CONVERSION = YES; 221 | CLANG_WARN_COMMA = YES; 222 | CLANG_WARN_CONSTANT_CONVERSION = YES; 223 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 224 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 225 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 226 | CLANG_WARN_EMPTY_BODY = YES; 227 | CLANG_WARN_ENUM_CONVERSION = YES; 228 | CLANG_WARN_INFINITE_RECURSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 231 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 232 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 233 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 234 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 235 | CLANG_WARN_STRICT_PROTOTYPES = YES; 236 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 237 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 238 | CLANG_WARN_UNREACHABLE_CODE = YES; 239 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 240 | COPY_PHASE_STRIP = NO; 241 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 242 | ENABLE_NS_ASSERTIONS = NO; 243 | ENABLE_STRICT_OBJC_MSGSEND = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu11; 245 | GCC_NO_COMMON_BLOCKS = YES; 246 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 248 | GCC_WARN_UNDECLARED_SELECTOR = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 250 | GCC_WARN_UNUSED_FUNCTION = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | MACOSX_DEPLOYMENT_TARGET = 10.15; 253 | MTL_ENABLE_DEBUG_INFO = NO; 254 | MTL_FAST_MATH = YES; 255 | SDKROOT = macosx; 256 | }; 257 | name = Release; 258 | }; 259 | 09275C44247FCA8F0057A737 /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | CODE_SIGN_STYLE = Automatic; 263 | DEVELOPMENT_TEAM = VN555WY3S4; 264 | INFOPLIST_FILE = "generic-kext demo/Info.plist"; 265 | MODULE_NAME = com.test.generic_kext_demo; 266 | MODULE_START = generic_kext_demo_start; 267 | MODULE_STOP = generic_kext_demo_stop; 268 | MODULE_VERSION = 1.0.0d1; 269 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.generic-kext-demo"; 270 | PRODUCT_NAME = "$(TARGET_NAME)"; 271 | WRAPPER_EXTENSION = kext; 272 | }; 273 | name = Debug; 274 | }; 275 | 09275C45247FCA8F0057A737 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | CODE_SIGN_STYLE = Automatic; 279 | DEVELOPMENT_TEAM = VN555WY3S4; 280 | INFOPLIST_FILE = "generic-kext demo/Info.plist"; 281 | MODULE_NAME = com.test.generic_kext_demo; 282 | MODULE_START = generic_kext_demo_start; 283 | MODULE_STOP = generic_kext_demo_stop; 284 | MODULE_VERSION = 1.0.0d1; 285 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.generic-kext-demo"; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | WRAPPER_EXTENSION = kext; 288 | }; 289 | name = Release; 290 | }; 291 | /* End XCBuildConfiguration section */ 292 | 293 | /* Begin XCConfigurationList section */ 294 | 09275C35247FCA8F0057A737 /* Build configuration list for PBXProject "generic-kext demo" */ = { 295 | isa = XCConfigurationList; 296 | buildConfigurations = ( 297 | 09275C41247FCA8F0057A737 /* Debug */, 298 | 09275C42247FCA8F0057A737 /* Release */, 299 | ); 300 | defaultConfigurationIsVisible = 0; 301 | defaultConfigurationName = Release; 302 | }; 303 | 09275C43247FCA8F0057A737 /* Build configuration list for PBXNativeTarget "generic-kext demo" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | 09275C44247FCA8F0057A737 /* Debug */, 307 | 09275C45247FCA8F0057A737 /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | /* End XCConfigurationList section */ 313 | }; 314 | rootObject = 09275C32247FCA8F0057A737 /* Project object */; 315 | } 316 | -------------------------------------------------------------------------------- /demos/generic-kext demo/generic-kext demo.xcodeproj/xcshareddata/xcschemes/generic-kext demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /demos/generic-kext demo/generic-kext demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2020 Jozef Zuzelka. All rights reserved. 23 | OSBundleLibraries 24 | 25 | com.apple.kpi.libkern 26 | 19.4 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /demos/generic-kext demo/generic-kext demo/generic_kext_demo.c: -------------------------------------------------------------------------------- 1 | // 2 | // generic_kext_demo.c 3 | // generic-kext demo 4 | // 5 | // Created by Jozef on 28/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | static const char* g_demoName = "generic-kext"; 13 | // Define endpoints 14 | kern_return_t generic_kext_demo_start(kmod_info_t * ki, void *d); 15 | kern_return_t generic_kext_demo_stop(kmod_info_t *ki, void *d); 16 | 17 | // The extension has been loaded. Register your callbacks.. 18 | kern_return_t generic_kext_demo_start(kmod_info_t * ki, void *d) 19 | { 20 | printf("(%s) Hello, World!\n", g_demoName); 21 | return KERN_SUCCESS; 22 | } 23 | 24 | // Clean up allocated resources. 25 | kern_return_t generic_kext_demo_stop(kmod_info_t *ki, void *d) 26 | { 27 | printf("(%s) Goodbye, World!\n", g_demoName); 28 | return KERN_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /demos/kauth demo/kauth demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 09761D3E24814CEB00D9EA44 /* kauth_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 09761D3D24814CEB00D9EA44 /* kauth_demo.c */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | 09761D3A24814CEB00D9EA44 /* kauth demo.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "kauth demo.kext"; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | 09761D3D24814CEB00D9EA44 /* kauth_demo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kauth_demo.c; sourceTree = ""; }; 16 | 09761D3F24814CEB00D9EA44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 17 | /* End PBXFileReference section */ 18 | 19 | /* Begin PBXFrameworksBuildPhase section */ 20 | 09761D3724814CEB00D9EA44 /* Frameworks */ = { 21 | isa = PBXFrameworksBuildPhase; 22 | buildActionMask = 2147483647; 23 | files = ( 24 | ); 25 | runOnlyForDeploymentPostprocessing = 0; 26 | }; 27 | /* End PBXFrameworksBuildPhase section */ 28 | 29 | /* Begin PBXGroup section */ 30 | 09761D3024814CEB00D9EA44 = { 31 | isa = PBXGroup; 32 | children = ( 33 | 09761D3C24814CEB00D9EA44 /* kauth demo */, 34 | 09761D3B24814CEB00D9EA44 /* Products */, 35 | ); 36 | sourceTree = ""; 37 | }; 38 | 09761D3B24814CEB00D9EA44 /* Products */ = { 39 | isa = PBXGroup; 40 | children = ( 41 | 09761D3A24814CEB00D9EA44 /* kauth demo.kext */, 42 | ); 43 | name = Products; 44 | sourceTree = ""; 45 | }; 46 | 09761D3C24814CEB00D9EA44 /* kauth demo */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | 09761D3D24814CEB00D9EA44 /* kauth_demo.c */, 50 | 09761D3F24814CEB00D9EA44 /* Info.plist */, 51 | ); 52 | path = "kauth demo"; 53 | sourceTree = ""; 54 | }; 55 | /* End PBXGroup section */ 56 | 57 | /* Begin PBXHeadersBuildPhase section */ 58 | 09761D3524814CEB00D9EA44 /* Headers */ = { 59 | isa = PBXHeadersBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXHeadersBuildPhase section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 09761D3924814CEB00D9EA44 /* kauth demo */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 09761D4224814CEB00D9EA44 /* Build configuration list for PBXNativeTarget "kauth demo" */; 71 | buildPhases = ( 72 | 09761D3524814CEB00D9EA44 /* Headers */, 73 | 09761D3624814CEB00D9EA44 /* Sources */, 74 | 09761D3724814CEB00D9EA44 /* Frameworks */, 75 | 09761D3824814CEB00D9EA44 /* Resources */, 76 | ); 77 | buildRules = ( 78 | ); 79 | dependencies = ( 80 | ); 81 | name = "kauth demo"; 82 | productName = "kauth demo"; 83 | productReference = 09761D3A24814CEB00D9EA44 /* kauth demo.kext */; 84 | productType = "com.apple.product-type.kernel-extension"; 85 | }; 86 | /* End PBXNativeTarget section */ 87 | 88 | /* Begin PBXProject section */ 89 | 09761D3124814CEB00D9EA44 /* Project object */ = { 90 | isa = PBXProject; 91 | attributes = { 92 | LastUpgradeCheck = 1150; 93 | ORGANIZATIONNAME = "Jozef Zuzelka"; 94 | TargetAttributes = { 95 | 09761D3924814CEB00D9EA44 = { 96 | CreatedOnToolsVersion = 11.5; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = 09761D3424814CEB00D9EA44 /* Build configuration list for PBXProject "kauth demo" */; 101 | compatibilityVersion = "Xcode 9.3"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | Base, 107 | ); 108 | mainGroup = 09761D3024814CEB00D9EA44; 109 | productRefGroup = 09761D3B24814CEB00D9EA44 /* Products */; 110 | projectDirPath = ""; 111 | projectRoot = ""; 112 | targets = ( 113 | 09761D3924814CEB00D9EA44 /* kauth demo */, 114 | ); 115 | }; 116 | /* End PBXProject section */ 117 | 118 | /* Begin PBXResourcesBuildPhase section */ 119 | 09761D3824814CEB00D9EA44 /* Resources */ = { 120 | isa = PBXResourcesBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXResourcesBuildPhase section */ 127 | 128 | /* Begin PBXSourcesBuildPhase section */ 129 | 09761D3624814CEB00D9EA44 /* Sources */ = { 130 | isa = PBXSourcesBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | 09761D3E24814CEB00D9EA44 /* kauth_demo.c in Sources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXSourcesBuildPhase section */ 138 | 139 | /* Begin XCBuildConfiguration section */ 140 | 09761D4024814CEB00D9EA44 /* Debug */ = { 141 | isa = XCBuildConfiguration; 142 | buildSettings = { 143 | ALWAYS_SEARCH_USER_PATHS = NO; 144 | CLANG_ANALYZER_NONNULL = YES; 145 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 146 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 147 | CLANG_CXX_LIBRARY = "libc++"; 148 | CLANG_ENABLE_MODULES = YES; 149 | CLANG_ENABLE_OBJC_ARC = YES; 150 | CLANG_ENABLE_OBJC_WEAK = YES; 151 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 152 | CLANG_WARN_BOOL_CONVERSION = YES; 153 | CLANG_WARN_COMMA = YES; 154 | CLANG_WARN_CONSTANT_CONVERSION = YES; 155 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 156 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 157 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 158 | CLANG_WARN_EMPTY_BODY = YES; 159 | CLANG_WARN_ENUM_CONVERSION = YES; 160 | CLANG_WARN_INFINITE_RECURSION = YES; 161 | CLANG_WARN_INT_CONVERSION = YES; 162 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 163 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 164 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 165 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 166 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 167 | CLANG_WARN_STRICT_PROTOTYPES = YES; 168 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 169 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 170 | CLANG_WARN_UNREACHABLE_CODE = YES; 171 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 172 | COPY_PHASE_STRIP = NO; 173 | DEBUG_INFORMATION_FORMAT = dwarf; 174 | ENABLE_STRICT_OBJC_MSGSEND = YES; 175 | ENABLE_TESTABILITY = YES; 176 | GCC_C_LANGUAGE_STANDARD = gnu11; 177 | GCC_DYNAMIC_NO_PIC = NO; 178 | GCC_NO_COMMON_BLOCKS = YES; 179 | GCC_OPTIMIZATION_LEVEL = 0; 180 | GCC_PREPROCESSOR_DEFINITIONS = ( 181 | "DEBUG=1", 182 | "$(inherited)", 183 | ); 184 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 185 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 186 | GCC_WARN_UNDECLARED_SELECTOR = YES; 187 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 188 | GCC_WARN_UNUSED_FUNCTION = YES; 189 | GCC_WARN_UNUSED_VARIABLE = YES; 190 | MACOSX_DEPLOYMENT_TARGET = 10.15; 191 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 192 | MTL_FAST_MATH = YES; 193 | ONLY_ACTIVE_ARCH = YES; 194 | SDKROOT = macosx; 195 | }; 196 | name = Debug; 197 | }; 198 | 09761D4124814CEB00D9EA44 /* Release */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_ANALYZER_NONNULL = YES; 203 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 205 | CLANG_CXX_LIBRARY = "libc++"; 206 | CLANG_ENABLE_MODULES = YES; 207 | CLANG_ENABLE_OBJC_ARC = YES; 208 | CLANG_ENABLE_OBJC_WEAK = YES; 209 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 210 | CLANG_WARN_BOOL_CONVERSION = YES; 211 | CLANG_WARN_COMMA = YES; 212 | CLANG_WARN_CONSTANT_CONVERSION = YES; 213 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 214 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 215 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 216 | CLANG_WARN_EMPTY_BODY = YES; 217 | CLANG_WARN_ENUM_CONVERSION = YES; 218 | CLANG_WARN_INFINITE_RECURSION = YES; 219 | CLANG_WARN_INT_CONVERSION = YES; 220 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 222 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 223 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 224 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 225 | CLANG_WARN_STRICT_PROTOTYPES = YES; 226 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 227 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 228 | CLANG_WARN_UNREACHABLE_CODE = YES; 229 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 230 | COPY_PHASE_STRIP = NO; 231 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 232 | ENABLE_NS_ASSERTIONS = NO; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu11; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | MACOSX_DEPLOYMENT_TARGET = 10.15; 243 | MTL_ENABLE_DEBUG_INFO = NO; 244 | MTL_FAST_MATH = YES; 245 | SDKROOT = macosx; 246 | }; 247 | name = Release; 248 | }; 249 | 09761D4324814CEB00D9EA44 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | CODE_SIGN_STYLE = Automatic; 253 | DEVELOPMENT_TEAM = VN555WY3S4; 254 | INFOPLIST_FILE = "kauth demo/Info.plist"; 255 | MODULE_NAME = com.test.kauth_demo; 256 | MODULE_START = kauth_demo_start; 257 | MODULE_STOP = kauth_demo_stop; 258 | MODULE_VERSION = 1.0.0d1; 259 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.kauth-demo"; 260 | PRODUCT_NAME = "$(TARGET_NAME)"; 261 | WRAPPER_EXTENSION = kext; 262 | }; 263 | name = Debug; 264 | }; 265 | 09761D4424814CEB00D9EA44 /* Release */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | CODE_SIGN_STYLE = Automatic; 269 | DEVELOPMENT_TEAM = VN555WY3S4; 270 | INFOPLIST_FILE = "kauth demo/Info.plist"; 271 | MODULE_NAME = com.test.kauth_demo; 272 | MODULE_START = kauth_demo_start; 273 | MODULE_STOP = kauth_demo_stop; 274 | MODULE_VERSION = 1.0.0d1; 275 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.kauth-demo"; 276 | PRODUCT_NAME = "$(TARGET_NAME)"; 277 | WRAPPER_EXTENSION = kext; 278 | }; 279 | name = Release; 280 | }; 281 | /* End XCBuildConfiguration section */ 282 | 283 | /* Begin XCConfigurationList section */ 284 | 09761D3424814CEB00D9EA44 /* Build configuration list for PBXProject "kauth demo" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | 09761D4024814CEB00D9EA44 /* Debug */, 288 | 09761D4124814CEB00D9EA44 /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | 09761D4224814CEB00D9EA44 /* Build configuration list for PBXNativeTarget "kauth demo" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | 09761D4324814CEB00D9EA44 /* Debug */, 297 | 09761D4424814CEB00D9EA44 /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | /* End XCConfigurationList section */ 303 | }; 304 | rootObject = 09761D3124814CEB00D9EA44 /* Project object */; 305 | } 306 | -------------------------------------------------------------------------------- /demos/kauth demo/kauth demo.xcodeproj/xcshareddata/xcschemes/kauth demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /demos/kauth demo/kauth demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2020 Jozef Zuzelka. All rights reserved. 23 | OSBundleLibraries 24 | 25 | com.apple.driver.AppleACPIPlatform 26 | 6.1 27 | com.apple.kpi.bsd 28 | 19.4 29 | com.apple.kpi.libkern 30 | 19.4 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /demos/kdebug demo/kdebug demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 09C7A618248FDEBF00CBDCBE /* kdebug.c in Sources */ = {isa = PBXBuildFile; fileRef = 09C7A617248FDEBF00CBDCBE /* kdebug.c */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 09C7A612248FDEBF00CBDCBE /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 09C7A614248FDEBF00CBDCBE /* kdebug demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "kdebug demo"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 09C7A617248FDEBF00CBDCBE /* kdebug.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kdebug.c; sourceTree = ""; }; 28 | 09C7A61F248FE75300CBDCBE /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 09C7A611248FDEBF00CBDCBE /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 09C7A60B248FDEBF00CBDCBE = { 43 | isa = PBXGroup; 44 | children = ( 45 | 09C7A616248FDEBF00CBDCBE /* kdebug demo */, 46 | 09C7A615248FDEBF00CBDCBE /* Products */, 47 | 09C7A61E248FE75300CBDCBE /* Frameworks */, 48 | ); 49 | sourceTree = ""; 50 | }; 51 | 09C7A615248FDEBF00CBDCBE /* Products */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 09C7A614248FDEBF00CBDCBE /* kdebug demo */, 55 | ); 56 | name = Products; 57 | sourceTree = ""; 58 | }; 59 | 09C7A616248FDEBF00CBDCBE /* kdebug demo */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 09C7A617248FDEBF00CBDCBE /* kdebug.c */, 63 | ); 64 | path = "kdebug demo"; 65 | sourceTree = ""; 66 | }; 67 | 09C7A61E248FE75300CBDCBE /* Frameworks */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 09C7A61F248FE75300CBDCBE /* Kernel.framework */, 71 | ); 72 | name = Frameworks; 73 | sourceTree = ""; 74 | }; 75 | /* End PBXGroup section */ 76 | 77 | /* Begin PBXNativeTarget section */ 78 | 09C7A613248FDEBF00CBDCBE /* kdebug demo */ = { 79 | isa = PBXNativeTarget; 80 | buildConfigurationList = 09C7A61B248FDEBF00CBDCBE /* Build configuration list for PBXNativeTarget "kdebug demo" */; 81 | buildPhases = ( 82 | 09C7A610248FDEBF00CBDCBE /* Sources */, 83 | 09C7A611248FDEBF00CBDCBE /* Frameworks */, 84 | 09C7A612248FDEBF00CBDCBE /* CopyFiles */, 85 | ); 86 | buildRules = ( 87 | ); 88 | dependencies = ( 89 | ); 90 | name = "kdebug demo"; 91 | productName = "kdebug demo"; 92 | productReference = 09C7A614248FDEBF00CBDCBE /* kdebug demo */; 93 | productType = "com.apple.product-type.tool"; 94 | }; 95 | /* End PBXNativeTarget section */ 96 | 97 | /* Begin PBXProject section */ 98 | 09C7A60C248FDEBF00CBDCBE /* Project object */ = { 99 | isa = PBXProject; 100 | attributes = { 101 | LastUpgradeCheck = 1150; 102 | ORGANIZATIONNAME = "Jozef Zuzelka"; 103 | TargetAttributes = { 104 | 09C7A613248FDEBF00CBDCBE = { 105 | CreatedOnToolsVersion = 11.5; 106 | }; 107 | }; 108 | }; 109 | buildConfigurationList = 09C7A60F248FDEBF00CBDCBE /* Build configuration list for PBXProject "kdebug demo" */; 110 | compatibilityVersion = "Xcode 9.3"; 111 | developmentRegion = en; 112 | hasScannedForEncodings = 0; 113 | knownRegions = ( 114 | en, 115 | Base, 116 | ); 117 | mainGroup = 09C7A60B248FDEBF00CBDCBE; 118 | productRefGroup = 09C7A615248FDEBF00CBDCBE /* Products */; 119 | projectDirPath = ""; 120 | projectRoot = ""; 121 | targets = ( 122 | 09C7A613248FDEBF00CBDCBE /* kdebug demo */, 123 | ); 124 | }; 125 | /* End PBXProject section */ 126 | 127 | /* Begin PBXSourcesBuildPhase section */ 128 | 09C7A610248FDEBF00CBDCBE /* Sources */ = { 129 | isa = PBXSourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | 09C7A618248FDEBF00CBDCBE /* kdebug.c in Sources */, 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | /* End PBXSourcesBuildPhase section */ 137 | 138 | /* Begin XCBuildConfiguration section */ 139 | 09C7A619248FDEBF00CBDCBE /* Debug */ = { 140 | isa = XCBuildConfiguration; 141 | buildSettings = { 142 | ALWAYS_SEARCH_USER_PATHS = NO; 143 | CLANG_ANALYZER_NONNULL = YES; 144 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 145 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 146 | CLANG_CXX_LIBRARY = "libc++"; 147 | CLANG_ENABLE_MODULES = YES; 148 | CLANG_ENABLE_OBJC_ARC = YES; 149 | CLANG_ENABLE_OBJC_WEAK = YES; 150 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 151 | CLANG_WARN_BOOL_CONVERSION = YES; 152 | CLANG_WARN_COMMA = YES; 153 | CLANG_WARN_CONSTANT_CONVERSION = YES; 154 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 155 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 156 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 157 | CLANG_WARN_EMPTY_BODY = YES; 158 | CLANG_WARN_ENUM_CONVERSION = YES; 159 | CLANG_WARN_INFINITE_RECURSION = YES; 160 | CLANG_WARN_INT_CONVERSION = YES; 161 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 162 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 163 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 164 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 165 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 166 | CLANG_WARN_STRICT_PROTOTYPES = YES; 167 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 168 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 169 | CLANG_WARN_UNREACHABLE_CODE = YES; 170 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 171 | COPY_PHASE_STRIP = NO; 172 | DEBUG_INFORMATION_FORMAT = dwarf; 173 | ENABLE_STRICT_OBJC_MSGSEND = YES; 174 | ENABLE_TESTABILITY = YES; 175 | GCC_C_LANGUAGE_STANDARD = gnu11; 176 | GCC_DYNAMIC_NO_PIC = NO; 177 | GCC_NO_COMMON_BLOCKS = YES; 178 | GCC_OPTIMIZATION_LEVEL = 0; 179 | GCC_PREPROCESSOR_DEFINITIONS = ( 180 | "DEBUG=1", 181 | "$(inherited)", 182 | ); 183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 185 | GCC_WARN_UNDECLARED_SELECTOR = YES; 186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 187 | GCC_WARN_UNUSED_FUNCTION = YES; 188 | GCC_WARN_UNUSED_VARIABLE = YES; 189 | MACOSX_DEPLOYMENT_TARGET = 10.15; 190 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 191 | MTL_FAST_MATH = YES; 192 | ONLY_ACTIVE_ARCH = YES; 193 | SDKROOT = macosx; 194 | }; 195 | name = Debug; 196 | }; 197 | 09C7A61A248FDEBF00CBDCBE /* Release */ = { 198 | isa = XCBuildConfiguration; 199 | buildSettings = { 200 | ALWAYS_SEARCH_USER_PATHS = NO; 201 | CLANG_ANALYZER_NONNULL = YES; 202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 204 | CLANG_CXX_LIBRARY = "libc++"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_ENABLE_OBJC_WEAK = YES; 208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 209 | CLANG_WARN_BOOL_CONVERSION = YES; 210 | CLANG_WARN_COMMA = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 215 | CLANG_WARN_EMPTY_BODY = YES; 216 | CLANG_WARN_ENUM_CONVERSION = YES; 217 | CLANG_WARN_INFINITE_RECURSION = YES; 218 | CLANG_WARN_INT_CONVERSION = YES; 219 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 220 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 221 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 224 | CLANG_WARN_STRICT_PROTOTYPES = YES; 225 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 231 | ENABLE_NS_ASSERTIONS = NO; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | GCC_C_LANGUAGE_STANDARD = gnu11; 234 | GCC_NO_COMMON_BLOCKS = YES; 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 237 | GCC_WARN_UNDECLARED_SELECTOR = YES; 238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 239 | GCC_WARN_UNUSED_FUNCTION = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | MACOSX_DEPLOYMENT_TARGET = 10.15; 242 | MTL_ENABLE_DEBUG_INFO = NO; 243 | MTL_FAST_MATH = YES; 244 | SDKROOT = macosx; 245 | }; 246 | name = Release; 247 | }; 248 | 09C7A61C248FDEBF00CBDCBE /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | CODE_SIGN_STYLE = Automatic; 252 | DEVELOPMENT_TEAM = VN555WY3S4; 253 | ENABLE_HARDENED_RUNTIME = YES; 254 | HEADER_SEARCH_PATHS = "../../_apple-sources/xnu-6153.11.26/bsd/**"; 255 | MACOSX_DEPLOYMENT_TARGET = 10.14; 256 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.kdebug-demo"; 257 | PRODUCT_NAME = "$(TARGET_NAME)"; 258 | SDKROOT = macosx10.14; 259 | }; 260 | name = Debug; 261 | }; 262 | 09C7A61D248FDEBF00CBDCBE /* Release */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | CODE_SIGN_STYLE = Automatic; 266 | DEVELOPMENT_TEAM = VN555WY3S4; 267 | ENABLE_HARDENED_RUNTIME = YES; 268 | HEADER_SEARCH_PATHS = "../../_apple-sources/xnu-6153.11.26/bsd/**"; 269 | MACOSX_DEPLOYMENT_TARGET = 10.14; 270 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.kdebug-demo"; 271 | PRODUCT_NAME = "$(TARGET_NAME)"; 272 | SDKROOT = macosx10.14; 273 | }; 274 | name = Release; 275 | }; 276 | /* End XCBuildConfiguration section */ 277 | 278 | /* Begin XCConfigurationList section */ 279 | 09C7A60F248FDEBF00CBDCBE /* Build configuration list for PBXProject "kdebug demo" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | 09C7A619248FDEBF00CBDCBE /* Debug */, 283 | 09C7A61A248FDEBF00CBDCBE /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | defaultConfigurationName = Release; 287 | }; 288 | 09C7A61B248FDEBF00CBDCBE /* Build configuration list for PBXNativeTarget "kdebug demo" */ = { 289 | isa = XCConfigurationList; 290 | buildConfigurations = ( 291 | 09C7A61C248FDEBF00CBDCBE /* Debug */, 292 | 09C7A61D248FDEBF00CBDCBE /* Release */, 293 | ); 294 | defaultConfigurationIsVisible = 0; 295 | defaultConfigurationName = Release; 296 | }; 297 | /* End XCConfigurationList section */ 298 | }; 299 | rootObject = 09C7A60C248FDEBF00CBDCBE /* Project object */; 300 | } 301 | -------------------------------------------------------------------------------- /demos/kdebug demo/kdebug demo/Makefile: -------------------------------------------------------------------------------- 1 | # @file Makefile 2 | # @brief Brief description 3 | # @author Jozef Zuzelka 4 | # @date 5 | # - Created: 09.06.2020 17:52 6 | # - Edited: 09.06.2020 18:29 7 | # @version 1.0.0 8 | # @par make: GNU Make 3.81 9 | # @bug 10 | # @todo 11 | 12 | 13 | TARGET=kdebug 14 | 15 | CC=gcc 16 | CCFLAGS=-std=c99 -pedantic -Wall -Wextra -g -I ../../../_apple-sources/xnu-6153.11.26/bsd -I /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk 17 | LDFLAGS= 18 | .PHONY: clean 19 | 20 | $(TARGET): $(TARGET).o 21 | $(CC) $(CCFLAGS) -o $@ $< $(LDFLAGS) 22 | 23 | %.o: %.c 24 | $(CC) $(CCFLAGS) -c $< -o $@ 25 | 26 | all : $(TARGET) 27 | 28 | clean: 29 | -rm $(TARGET) $(TARGET).o 30 | -------------------------------------------------------------------------------- /demos/kdebug demo/kdebug demo/kdebug.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // kdebug demo 4 | // 5 | // Created by Jozef on 09/06/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | // Sources: 9 | // Amit Singh - Mac OS X Internals: A System's Approach 10 | 11 | #pragma message("Use attached makefile to build the project.") 12 | 13 | #define PROGNAME "kdebug" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | struct proc; 23 | 24 | // Kernel Debug definitions 25 | #define PRIVATE 26 | #define KERNEL_PRIVATE 27 | //#include 28 | #include 29 | #undef KERNEL_PRIVATE 30 | #undef PRIVATE 31 | 32 | #define KDBG_CPU_MASK 0x0f00000000000000ULL 33 | #define KDBG_CPU_SHIFT 56 34 | 35 | // Configurable parameters 36 | enum { 37 | KDBG_BSD_SYSTEM_CALL_OF_INTEREST = SYS_chdir, 38 | KDBG_SAMPLE_SIZE = 16384, 39 | KDBG_SAMPLE_INTERVAL = 100000 // in microseconds 40 | }; 41 | // Useful constants 42 | enum { 43 | // KDBG_FUNC_MASK = 0xfffffffc, // for extracting function type 44 | KDBG_CLASS_SHIFT = 24 // for extracting class type 45 | }; 46 | 47 | // Global variables 48 | int exiting = 0; // avoid recursion in exit handlers 49 | size_t oldlen; // used while calling sysctl() 50 | int mib[8]; // used while calling sysctl() 51 | pid_t pid = -1; // process ID of the traced process 52 | 53 | // Global flags 54 | int trace_enabled = 0; 55 | int set_remove_flag = 1; 56 | 57 | // Mapping of kdebug class IDs to class names 58 | const char *KDBG_CLASS_NAMES[256] = { 59 | NULL, // 0 60 | "DBG_MACH", // 1 61 | "DBG_NETWORK", // 2 62 | "DBG_FSYSTEM", // 3 63 | "DBG_BSD", // 4 64 | "DBG_IOKIT", // 5 65 | "DBG_DRIVERS", // 6 66 | "DBG_TRACE", // 7 67 | "DBG_DLIL", // 8 68 | "DBG_SECURITY", // 9 69 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 70 | "DBG_MISC", 71 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 72 | "DBG_DYLD", // 31 73 | "DBG_QT", // 32 74 | "DBG_APPS", // 33 75 | NULL, 76 | }; 77 | 78 | // Functions that we implement (the 'u' in ukdbg represents user space) 79 | void ukdbg_exit_handler(int); 80 | void ukdbg_exit(const char *); 81 | void ukdbg_setenable(int); 82 | void ukdbg_clear(); 83 | void ukdbg_reinit(); 84 | void ukdbg_setbuf(int); 85 | void ukdbg_getbuf(kbufinfo_t *); 86 | void ukdbg_setpidcheck(pid_t, int); 87 | void ukdbg_read(char *, size_t *); 88 | void ukdbg_setreg_valcheck(int val1, int val2, int val3, int val4); 89 | void ukdbg_exit_handler(int s) 90 | { 91 | exiting = 1; 92 | if (trace_enabled) 93 | ukdbg_setenable(0); 94 | 95 | if (pid > 0) 96 | ukdbg_setpidcheck(pid, 0); 97 | 98 | if (set_remove_flag) 99 | ukdbg_clear(); 100 | 101 | fprintf(stderr, "cleaning up...\n"); 102 | exit(s); 103 | } 104 | 105 | void ukdbg_exit(const char *msg) 106 | { 107 | if (msg) 108 | perror(msg); 109 | 110 | ukdbg_exit_handler(0); 111 | } 112 | 113 | // Enable or disable trace 114 | // enable=1 enables (trace buffer must already be initialized) 115 | // enable=0 disables 116 | void ukdbg_setenable(int enable) 117 | { 118 | mib[0] = CTL_KERN; 119 | mib[1] = KERN_KDEBUG; 120 | mib[2] = KERN_KDENABLE; 121 | mib[3] = enable; 122 | if ((sysctl(mib, 4, NULL, &oldlen, NULL, 0) < 0) && !exiting) 123 | ukdbg_exit("ukdbg_setenable::sysctl"); 124 | 125 | trace_enabled = enable; 126 | } 127 | 128 | // Clean up relevant buffers 129 | void ukdbg_clear(void) 130 | { 131 | mib[0] = CTL_KERN; 132 | mib[1] = KERN_KDEBUG; 133 | mib[2] = KERN_KDREMOVE; 134 | if ((sysctl(mib, 3, NULL, &oldlen, NULL, 0) < 0) && !exiting) { 135 | set_remove_flag = 0; 136 | ukdbg_exit("ukdbg_clear::sysctl"); 137 | } 138 | } 139 | 140 | // Disable any ongoing trace collection and reinitialize the facility 141 | void ukdbg_reinit(void) 142 | { 143 | mib[0] = CTL_KERN; 144 | mib[1] = KERN_KDEBUG; 145 | mib[2] = KERN_KDSETUP; 146 | if (sysctl(mib, 3, NULL, &oldlen, NULL, 0) < 0) 147 | ukdbg_exit("ukdbg_reinit::sysctl"); 148 | } 149 | 150 | // Set buffer for the desired number of trace entries 151 | // Buffer size is limited to either 25% of physical memory (sane_size), 152 | // or to the maximum mapped address, whichever is smaller 153 | void ukdbg_setbuf(int nbufs) 154 | { 155 | mib[0] = CTL_KERN; 156 | mib[1] = KERN_KDEBUG; 157 | mib[2] = KERN_KDSETBUF; 158 | mib[3] = nbufs; 159 | if (sysctl(mib, 4, NULL, &oldlen, NULL, 0) < 0) 160 | ukdbg_exit("ukdbg_setbuf::sysctl"); 161 | } 162 | 163 | // Turn pid check on or off in the trace buffer 164 | // check=1 turns on pid check for this and all pids 165 | // check=0 turns off pid check for this pid (but not all pids) 166 | void ukdbg_setpidcheck(pid_t pid, int check) 167 | { 168 | kd_regtype kr; 169 | kr.type = KDBG_TYPENONE; 170 | kr.value1 = pid; 171 | kr.value2 = check; 172 | oldlen = sizeof(kd_regtype); 173 | mib[0] = CTL_KERN; 174 | mib[1] = KERN_KDEBUG; 175 | mib[2] = KERN_KDPIDTR; 176 | if ((sysctl(mib, 3, &kr, &oldlen, NULL, 0) < 0) && !exiting) 177 | ukdbg_exit("ukdbg_setpidcheck::sysctl"); 178 | } 179 | 180 | // Set specific value checking 181 | void ukdbg_setreg_valcheck(int val1, int val2, int val3, int val4) 182 | { 183 | kd_regtype kr; 184 | kr.type = KDBG_VALCHECK; 185 | kr.value1 = val1; 186 | kr.value2 = val2; 187 | kr.value3 = val3; 188 | kr.value4 = val4; 189 | oldlen = sizeof(kd_regtype); 190 | mib[0] = CTL_KERN; 191 | mib[1] = KERN_KDEBUG; 192 | mib[2] = KERN_KDSETREG; 193 | if (sysctl(mib, 3, &kr, &oldlen, NULL, 0) < 0) 194 | ukdbg_exit("ukdbg_setreg_valcheck::sysctl"); 195 | } 196 | 197 | // Retrieve trace buffer information from the kernel 198 | void ukdbg_getbuf(kbufinfo_t *bufinfop) 199 | { 200 | oldlen = sizeof(bufinfop); 201 | mib[0] = CTL_KERN; 202 | mib[1] = KERN_KDEBUG; 203 | mib[2] = KERN_KDGETBUF; 204 | if (sysctl(mib, 3, bufinfop, &oldlen, 0, 0) < 0) 205 | ukdbg_exit("ukdbg_getbuf::sysctl"); 206 | } 207 | 208 | // Retrieve some of the trace buffer from the kernel 209 | void ukdbg_read(char *buf, size_t *len) 210 | { 211 | mib[0] = CTL_KERN; 212 | mib[1] = KERN_KDEBUG; 213 | mib[2] = KERN_KDREADTR; 214 | if (sysctl(mib, 3, buf, len, NULL, 0) < 0) 215 | ukdbg_exit("ukdbg_read::sysctl"); 216 | } 217 | 218 | int main(int argc, char **argv) 219 | { 220 | const char* demoName = "kdebug"; 221 | 222 | printf("(%s) Hello, World!\n", demoName); 223 | printf("Point of interest: %s", "All the events!\n"); 224 | 225 | int i, count; 226 | kd_buf *kd; 227 | char *kd_buf_memory; 228 | kbufinfo_t bufinfo = { 0, 0, 0, 0 }; 229 | unsigned short code; 230 | 231 | KDBG_CLASS_NAMES[255] = "DBG_MIG"; 232 | 233 | if (argc > 2) { 234 | fprintf(stderr, "usage: %s []\n", PROGNAME); exit(1); 235 | exit(1); 236 | } 237 | 238 | if (argc == 2) 239 | pid = atoi(argv[1]); 240 | 241 | code = KDBG_BSD_SYSTEM_CALL_OF_INTEREST; 242 | 243 | // Arrange for cleanup 244 | signal(SIGHUP, ukdbg_exit_handler); 245 | signal(SIGINT, ukdbg_exit_handler); 246 | signal(SIGQUIT, ukdbg_exit_handler); 247 | signal(SIGTERM, ukdbg_exit_handler); 248 | 249 | kd_buf_memory = malloc(KDBG_SAMPLE_SIZE * sizeof(kd_buf)); 250 | if (!kd_buf_memory) { 251 | perror("malloc"); 252 | exit(1); 253 | } 254 | 255 | ukdbg_clear(); // Clean up related buffers 256 | ukdbg_setbuf(KDBG_SAMPLE_SIZE); // Set buffer for the desired # of entries 257 | ukdbg_reinit(); // Reinitialize the facility 258 | if (pid > 0) 259 | ukdbg_setpidcheck(pid, 1); // We want this pid 260 | // We want this particular BSD system call 261 | ukdbg_setreg_valcheck(BSDDBG_CODE(DBG_BSD_EXCP_SC, code), 0, 0, 0); 262 | ukdbg_setenable(1); // Enable tracing 263 | while (1) { 264 | ukdbg_getbuf(&bufinfo); // Query information 265 | oldlen = bufinfo.nkdbufs * sizeof(kd_buf); // How much to read? 266 | ukdbg_read(kd_buf_memory, &oldlen); // Read that much 267 | count = oldlen; 268 | 269 | kd = (kd_buf *)kd_buf_memory; 270 | for (i = 0; i < count; i++) { 271 | char *qual = ""; 272 | uint64_t cpu, now; 273 | int debugid, thread, type, class_; 274 | 275 | thread = kd[i].arg5; 276 | debugid = kd[i].debugid; 277 | type = debugid & KDBG_FUNC_MASK; 278 | class_ = (debugid & KDBG_CLASS_MASK) >> KDBG_CLASS_SHIFT; 279 | now = kd[i].timestamp & KDBG_TIMESTAMP_MASK; 280 | cpu = (kd[i].timestamp & KDBG_CPU_MASK) >> KDBG_CPU_SHIFT; 281 | if (debugid & DBG_FUNC_START) 282 | qual = "DBG_FUNC_START"; 283 | else if (debugid & DBG_FUNC_END) 284 | qual = "DBG_FUNC_END"; 285 | 286 | // Note that 'type' should be the system call we were looking for 287 | // (type == BSDDBG_CODE(DBG_BSD_EXCP_SC, code) is true 288 | 289 | printf("%lld: cpu %lld %s code %#x thread %p %s\n", 290 | now, 291 | cpu, 292 | (KDBG_CLASS_NAMES[class_]) ? KDBG_CLASS_NAMES[class_] : "", 293 | type, 294 | (void *)thread, 295 | qual); 296 | } 297 | usleep(KDBG_SAMPLE_INTERVAL); 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /demos/kevent demo/kevent demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 09F7F8B8246AC8EC00BB0662 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09F7F8B7246AC8EC00BB0662 /* main.cpp */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 09F7F8B2246AC8EC00BB0662 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 09F7F8B4246AC8EC00BB0662 /* kevent demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "kevent demo"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 09F7F8B7246AC8EC00BB0662 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 09F7F8B1246AC8EC00BB0662 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 09F7F8AB246AC8EC00BB0662 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 09F7F8B6246AC8EC00BB0662 /* kevent demo */, 45 | 09F7F8B5246AC8EC00BB0662 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 09F7F8B5246AC8EC00BB0662 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 09F7F8B4246AC8EC00BB0662 /* kevent demo */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 09F7F8B6246AC8EC00BB0662 /* kevent demo */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 09F7F8B7246AC8EC00BB0662 /* main.cpp */, 61 | ); 62 | path = "kevent demo"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 09F7F8B3246AC8EC00BB0662 /* kevent demo */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 09F7F8BB246AC8EC00BB0662 /* Build configuration list for PBXNativeTarget "kevent demo" */; 71 | buildPhases = ( 72 | 09F7F8B0246AC8EC00BB0662 /* Sources */, 73 | 09F7F8B1246AC8EC00BB0662 /* Frameworks */, 74 | 09F7F8B2246AC8EC00BB0662 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "kevent demo"; 81 | productName = "kqueue demo"; 82 | productReference = 09F7F8B4246AC8EC00BB0662 /* kevent demo */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 09F7F8AC246AC8EC00BB0662 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 1150; 92 | ORGANIZATIONNAME = "Jozef Zuzelka"; 93 | TargetAttributes = { 94 | 09F7F8B3246AC8EC00BB0662 = { 95 | CreatedOnToolsVersion = 11.4.1; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 09F7F8AF246AC8EC00BB0662 /* Build configuration list for PBXProject "kevent demo" */; 100 | compatibilityVersion = "Xcode 9.3"; 101 | developmentRegion = en; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | Base, 106 | ); 107 | mainGroup = 09F7F8AB246AC8EC00BB0662; 108 | productRefGroup = 09F7F8B5246AC8EC00BB0662 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | 09F7F8B3246AC8EC00BB0662 /* kevent demo */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | 09F7F8B0246AC8EC00BB0662 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | 09F7F8B8246AC8EC00BB0662 /* main.cpp in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | 09F7F8B9246AC8EC00BB0662 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_ENABLE_OBJC_WEAK = YES; 140 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 141 | CLANG_WARN_BOOL_CONVERSION = YES; 142 | CLANG_WARN_COMMA = YES; 143 | CLANG_WARN_CONSTANT_CONVERSION = YES; 144 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 146 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 147 | CLANG_WARN_EMPTY_BODY = YES; 148 | CLANG_WARN_ENUM_CONVERSION = YES; 149 | CLANG_WARN_INFINITE_RECURSION = YES; 150 | CLANG_WARN_INT_CONVERSION = YES; 151 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 152 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 153 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 154 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | GCC_C_LANGUAGE_STANDARD = gnu11; 166 | GCC_DYNAMIC_NO_PIC = NO; 167 | GCC_NO_COMMON_BLOCKS = YES; 168 | GCC_OPTIMIZATION_LEVEL = 0; 169 | GCC_PREPROCESSOR_DEFINITIONS = ( 170 | "DEBUG=1", 171 | "$(inherited)", 172 | ); 173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 174 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 175 | GCC_WARN_UNDECLARED_SELECTOR = YES; 176 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 177 | GCC_WARN_UNUSED_FUNCTION = YES; 178 | GCC_WARN_UNUSED_VARIABLE = YES; 179 | MACOSX_DEPLOYMENT_TARGET = 10.15; 180 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 181 | MTL_FAST_MATH = YES; 182 | ONLY_ACTIVE_ARCH = YES; 183 | SDKROOT = macosx; 184 | }; 185 | name = Debug; 186 | }; 187 | 09F7F8BA246AC8EC00BB0662 /* Release */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_ANALYZER_NONNULL = YES; 192 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 193 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 194 | CLANG_CXX_LIBRARY = "libc++"; 195 | CLANG_ENABLE_MODULES = YES; 196 | CLANG_ENABLE_OBJC_ARC = YES; 197 | CLANG_ENABLE_OBJC_WEAK = YES; 198 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 199 | CLANG_WARN_BOOL_CONVERSION = YES; 200 | CLANG_WARN_COMMA = YES; 201 | CLANG_WARN_CONSTANT_CONVERSION = YES; 202 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 205 | CLANG_WARN_EMPTY_BODY = YES; 206 | CLANG_WARN_ENUM_CONVERSION = YES; 207 | CLANG_WARN_INFINITE_RECURSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 210 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 214 | CLANG_WARN_STRICT_PROTOTYPES = YES; 215 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 216 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 217 | CLANG_WARN_UNREACHABLE_CODE = YES; 218 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 219 | COPY_PHASE_STRIP = NO; 220 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 221 | ENABLE_NS_ASSERTIONS = NO; 222 | ENABLE_STRICT_OBJC_MSGSEND = YES; 223 | GCC_C_LANGUAGE_STANDARD = gnu11; 224 | GCC_NO_COMMON_BLOCKS = YES; 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | MACOSX_DEPLOYMENT_TARGET = 10.15; 232 | MTL_ENABLE_DEBUG_INFO = NO; 233 | MTL_FAST_MATH = YES; 234 | SDKROOT = macosx; 235 | }; 236 | name = Release; 237 | }; 238 | 09F7F8BC246AC8EC00BB0662 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | CODE_SIGN_IDENTITY = "-"; 242 | CODE_SIGN_STYLE = Automatic; 243 | DEVELOPMENT_TEAM = VN555WY3S4; 244 | ENABLE_HARDENED_RUNTIME = YES; 245 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.kevent-demo"; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | }; 248 | name = Debug; 249 | }; 250 | 09F7F8BD246AC8EC00BB0662 /* Release */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | CODE_SIGN_IDENTITY = "-"; 254 | CODE_SIGN_STYLE = Automatic; 255 | DEVELOPMENT_TEAM = VN555WY3S4; 256 | ENABLE_HARDENED_RUNTIME = YES; 257 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.demo.kevent-demo"; 258 | PRODUCT_NAME = "$(TARGET_NAME)"; 259 | }; 260 | name = Release; 261 | }; 262 | /* End XCBuildConfiguration section */ 263 | 264 | /* Begin XCConfigurationList section */ 265 | 09F7F8AF246AC8EC00BB0662 /* Build configuration list for PBXProject "kevent demo" */ = { 266 | isa = XCConfigurationList; 267 | buildConfigurations = ( 268 | 09F7F8B9246AC8EC00BB0662 /* Debug */, 269 | 09F7F8BA246AC8EC00BB0662 /* Release */, 270 | ); 271 | defaultConfigurationIsVisible = 0; 272 | defaultConfigurationName = Release; 273 | }; 274 | 09F7F8BB246AC8EC00BB0662 /* Build configuration list for PBXNativeTarget "kevent demo" */ = { 275 | isa = XCConfigurationList; 276 | buildConfigurations = ( 277 | 09F7F8BC246AC8EC00BB0662 /* Debug */, 278 | 09F7F8BD246AC8EC00BB0662 /* Release */, 279 | ); 280 | defaultConfigurationIsVisible = 0; 281 | defaultConfigurationName = Release; 282 | }; 283 | /* End XCConfigurationList section */ 284 | }; 285 | rootObject = 09F7F8AC246AC8EC00BB0662 /* Project object */; 286 | } 287 | -------------------------------------------------------------------------------- /demos/kevent demo/kevent demo.xcodeproj/xcshareddata/xcschemes/kevent demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /demos/kevent demo/kevent demo/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // kevent demo 4 | // 5 | // Created by Jozef on 12/05/2020. 6 | // Copyright © 2020 Jozef Zuzelka. All rights reserved. 7 | // 8 | 9 | // Sources: 10 | // - https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/FSEvents_ProgGuide/KernelQueues/KernelQueues.html 11 | // - https://developer.apple.com/library/archive/samplecode/FileNotification/Introduction/Intro.html 12 | 13 | #include // std::atomic, 14 | #include // errno 15 | #include // O_EVTONLY 16 | #include // std::cout, std::cerr,... 17 | #include // kqueue, kevent,... 18 | #include // close 19 | 20 | #define NUM_EVENT_SLOTS 1 21 | #define NUM_EVENT_FDS 1 22 | 23 | std::atomic g_shouldStop {false}; 24 | char *flagstring(int flags); 25 | 26 | void signalHandler(int signum) 27 | { 28 | // Not safe, but whatever 29 | std::cerr << "Interrupt signal (" << signum << ") received, exiting." << std::endl; 30 | g_shouldStop = true; 31 | } 32 | 33 | 34 | int main() 35 | { 36 | // No runloop, no problem 37 | signal(SIGINT, signalHandler); 38 | signal(SIGTERM, signalHandler); 39 | signal(SIGABRT, signalHandler); 40 | 41 | const char* demoName = "kevent"; 42 | const std::string demoPath = "/tmp/" + std::string(demoName) + "-demo"; 43 | 44 | std::cout << "(" << demoName << ") Hello, World!\n"; 45 | std::cout << "Point of interest: " << demoPath << std::endl << std::endl; 46 | 47 | /* Open a kernel queue. */ 48 | int kq = kqueue(); 49 | if (kq < 0) { 50 | std::cerr << "Could not open kernel queue. Error was " << strerror(errno) << ".\n"; 51 | return EXIT_FAILURE; 52 | } 53 | 54 | /* 55 | Open a file descriptor for the file/directory that you 56 | want to monitor. 57 | */ 58 | int event_fd = open(demoPath.c_str(), O_EVTONLY); 59 | if (event_fd <=0) { 60 | std::cerr << "The file " << demoPath << " could not be opened for monitoring. Error was " 61 | << strerror(errno) << ".\n"; 62 | return EXIT_FAILURE; 63 | } 64 | 65 | /* 66 | The address in user_data will be copied into a field in the 67 | event. If you are monitoring multiple files, you could, 68 | for example, pass in different data structure for each file. 69 | For this example, the path string is used. 70 | */ 71 | void *user_data = (void *)demoPath.c_str(); 72 | 73 | /* Set the timeout to wake us every 5 and half second. */ 74 | struct timespec timeout { 75 | .tv_sec = 5, // 5 seconds 76 | .tv_nsec = 500000000 // 500 milliseconds 77 | }; 78 | 79 | /* Set up a list of events to monitor. */ 80 | unsigned int vnode_events; 81 | struct kevent events_to_monitor[NUM_EVENT_FDS]; 82 | vnode_events = (NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | NOTE_REVOKE); 83 | EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, vnode_events, 0, user_data); 84 | 85 | /* Handle events. */ 86 | int num_files = 1; 87 | int continue_loop = 40; /* Monitor for twenty seconds. */ 88 | struct kevent event_data[NUM_EVENT_SLOTS]; 89 | while (--continue_loop && !g_shouldStop) { 90 | int event_count = kevent(kq, events_to_monitor, NUM_EVENT_SLOTS, event_data, num_files, &timeout); 91 | if ((event_count < 0) || (event_data[0].flags == EV_ERROR)) { 92 | /* An error occurred. */ 93 | std::cerr << "An error occurred (event count " << event_count << "). The error was " 94 | << strerror(errno) << ".\n"; 95 | break; 96 | } 97 | if (event_count) { 98 | std::cout << "Event " << event_data[0].ident << " occurred." 99 | << " Filter " << event_data[0].filter 100 | << ", flags " << event_data[0].flags 101 | << ", filter flags " << flagstring(event_data[0].fflags) 102 | << ", filter data " << event_data[0].data 103 | << ", path " << (char *)event_data[0].udata << std::endl; 104 | 105 | } else { 106 | std::cout << "No event." << std::endl; 107 | } 108 | 109 | /* Reset the timeout. In case of a signal interrruption, the 110 | values may change. */ 111 | timeout.tv_sec = 5; // 5 seconds 112 | timeout.tv_nsec = 500000000; // 500 milliseconds 113 | } 114 | close(event_fd); 115 | return 0; 116 | } 117 | 118 | 119 | /* A simple routine to return a string for a set of flags. */ 120 | char *flagstring(int flags) 121 | { 122 | static char ret[512]; 123 | char *s_or = ""; 124 | 125 | ret[0]='\0'; // clear the string. 126 | if (flags & NOTE_DELETE) {strcat(ret,s_or);strcat(ret,"NOTE_DELETE");s_or="|";} 127 | if (flags & NOTE_WRITE) {strcat(ret,s_or);strcat(ret,"NOTE_WRITE");s_or="|";} 128 | if (flags & NOTE_EXTEND) {strcat(ret,s_or);strcat(ret,"NOTE_EXTEND");s_or="|";} 129 | if (flags & NOTE_ATTRIB) {strcat(ret,s_or);strcat(ret,"NOTE_ATTRIB");s_or="|";} 130 | if (flags & NOTE_LINK) {strcat(ret,s_or);strcat(ret,"NOTE_LINK");s_or="|";} 131 | if (flags & NOTE_RENAME) {strcat(ret,s_or);strcat(ret,"NOTE_RENAME");s_or="|";} 132 | if (flags & NOTE_REVOKE) {strcat(ret,s_or);strcat(ret,"NOTE_REVOKE");s_or="|";} 133 | 134 | return ret; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /demos/macf demo/macf demo.xcodeproj/xcshareddata/xcschemes/macf demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /demos/macf demo/macf demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2020 Jozef Zuzelka. All rights reserved. 23 | OSBundleLibraries 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demos/macf demo/macf demo/macf_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "macf_demo.h" 5 | 6 | static int openCallaback(kauth_cred_t cred, struct vnode *vp, struct label *label, int acc_mode) 7 | { 8 | 9 | } 10 | 11 | static struct mac_policy_ops mmPolicyOps = { 12 | .mpo_vnode_check_open_t = openCallback, 13 | } 14 | 15 | static struct mac_policy_conf policyConf = { 16 | .mpc_name = m_bundleId, 17 | .mpc_fullname = m_bundleId, 18 | .mpc_labelnames = NULL, 19 | .mpc_labelname_count = 0, 20 | .mpc_ops = &mmPolicyOps, 21 | .mpc_loadtime_flags = MPC_LOADTIME_FLAG_UNLOADOK, 22 | .mpc_field_off = NULL, 23 | .mpc_runtime_flags = 0, 24 | .mpc_list = NULL, 25 | .mpc_data = NULL, 26 | }; 27 | 28 | static mac_policy_handle_t handlep; 29 | 30 | kern_return_t generic_kext_demo_start(kmod_info_t * ki, void *d); 31 | kern_return_t generic_kext_demo_stop(kmod_info_t *ki, void *d); 32 | static const char* g_demoName = "macf"; 33 | static const char* g_demoPath = "/tmp/macf-demo"; 34 | 35 | // The extension has been loaded. Register your callbacks.. 36 | kern_return_t generic_kext_demo_start(kmod_info_t * ki, void *d) 37 | { 38 | printf("(%s) Hello, World!\n", g_demoName); 39 | printf("%s: Point of interest: %s\n", g_demoName, g_demoPath); 40 | 41 | void *ctx; 42 | int status = mac_policy_register(&policyConf, &handlep, ctx); 43 | if (status != KERN_SUCCESS) { 44 | IOLog("%s: failed to register MAC policy (%#x)\n", g_demoName, status); 45 | return status; 46 | } 47 | 48 | return KERN_SUCCESS; 49 | } 50 | 51 | // Clean up allocated resources. 52 | kern_return_t generic_kext_demo_stop(kmod_info_t *ki, void *d) 53 | { 54 | printf("(%s) Goodbye, World!\n", g_demoName); 55 | return mac_policy_unregister(handlep); // Deregistering the policy 56 | return KERN_SUCCESS; 57 | } 58 | --------------------------------------------------------------------------------