├── .gitignore ├── README.md ├── whoexec.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── whoexec.xcscheme └── whoexec ├── EndpointSecurity.h ├── EndpointSecurity.m ├── main.m ├── whoexec.entitlements ├── whoexec.h └── whoexec.m /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 and Xcode5 Source projects 3 | # 4 | # Apple bugs, waiting for Apple to fix/respond: 5 | # 6 | # 15564624 - what does the xccheckout file in Xcode5 do? Where's the documentation? 7 | # 8 | # Version 2.6 9 | # For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 10 | # 11 | # 2015 updates: 12 | # - Fixed typo in "xccheckout" line - thanks to @lyck for pointing it out! 13 | # - Fixed the .idea optional ignore. Thanks to @hashier for pointing this out 14 | # - Finally added "xccheckout" to the ignore. Apple still refuses to answer support requests about this, but in practice it seems you should ignore it. 15 | # - minor tweaks from Jona and Coeur (slightly more precise xc* filtering/names) 16 | # 2014 updates: 17 | #- appended non-standard items DISABLED by default (uncomment if you use those tools) 18 | # - removed the edit that an SO.com moderator made without bothering to ask me 19 | # - researched CocoaPods .lock more carefully, thanks to Gokhan Celiker 20 | # 2013 updates: 21 | # - fixed the broken "save personal Schemes" 22 | # - added line-by-line explanations for EVERYTHING (some were missing) 23 | # 24 | # NB: if you are storing "built" products, this WILL NOT WORK, 25 | # and you should use a different .gitignore (or none at all) 26 | # This file is for SOURCE projects, where there are many extra 27 | # files that we want to exclude 28 | # 29 | ######################### 30 | 31 | ##### 32 | # OS X temporary files that should never be committed 33 | # 34 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 35 | 36 | .DS_Store 37 | 38 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 39 | 40 | .Trashes 41 | 42 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 43 | 44 | *.swp 45 | 46 | # 47 | # *.lock - this is used and abused by many editors for many different things. 48 | # For the main ones I use (e.g. Eclipse), it should be excluded 49 | # from source-control, but YMMV. 50 | # (lock files are usually local-only file-synchronization on the local FS that should NOT go in git) 51 | # c.f. the "OPTIONAL" section at bottom though, for tool-specific variations! 52 | # 53 | # In particular, if you're using CocoaPods, you'll want to comment-out this line: 54 | *.lock 55 | 56 | 57 | # 58 | # profile - REMOVED temporarily (on double-checking, I can't find it in OS X docs?) 59 | #profile 60 | 61 | 62 | #### 63 | # Xcode temporary files that should never be committed 64 | # 65 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 66 | 67 | *~.nib 68 | 69 | 70 | #### 71 | # Xcode build files - 72 | # 73 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 74 | 75 | DerivedData/ 76 | 77 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 78 | 79 | build/ 80 | 81 | 82 | ##### 83 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 84 | # 85 | # This is complicated: 86 | # 87 | # SOMETIMES you need to put this file in version control. 88 | # Apple designed it poorly - if you use "custom executables", they are 89 | # saved in this file. 90 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 91 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 92 | 93 | # .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html 94 | 95 | *.pbxuser 96 | 97 | # .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 98 | 99 | *.mode1v3 100 | 101 | # .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 102 | 103 | *.mode2v3 104 | 105 | # .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file 106 | 107 | *.perspectivev3 108 | 109 | # NB: also, whitelist the default ones, some projects need to use these 110 | !default.pbxuser 111 | !default.mode1v3 112 | !default.mode2v3 113 | !default.perspectivev3 114 | 115 | 116 | #### 117 | # Xcode 4 - semi-personal settings 118 | # 119 | # Apple Shared data that Apple put in the wrong folder 120 | # c.f. http://stackoverflow.com/a/19260712/153422 121 | # FROM ANSWER: Apple says "don't ignore it" 122 | # FROM COMMENTS: Apple is wrong; Apple code is too buggy to trust; there are no known negative side-effects to ignoring Apple's unofficial advice and instead doing the thing that actively fixes bugs in Xcode 123 | # Up to you, but ... current advice: ignore it. 124 | *.xccheckout 125 | 126 | # 127 | # 128 | # OPTION 1: --------------------------------- 129 | # throw away ALL personal settings (including custom schemes! 130 | # - unless they are "shared") 131 | # As per build/ and DerivedData/, this ought to have a trailing slash 132 | # 133 | # NB: this is exclusive with OPTION 2 below 134 | xcuserdata/ 135 | 136 | # OPTION 2: --------------------------------- 137 | # get rid of ALL personal settings, but KEEP SOME OF THEM 138 | # - NB: you must manually uncomment the bits you want to keep 139 | # 140 | # NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X, 141 | # or manually install git over the top of the OS X version 142 | # NB: this is exclusive with OPTION 1 above 143 | # 144 | #xcuserdata/**/* 145 | 146 | # (requires option 2 above): Personal Schemes 147 | # 148 | #!xcuserdata/**/xcschemes/* 149 | 150 | #### 151 | # XCode 4 workspaces - more detailed 152 | # 153 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 154 | # 155 | # Workspace layout is quite spammy. For reference: 156 | # 157 | # /(root)/ 158 | # /(project-name).xcodeproj/ 159 | # project.pbxproj 160 | # /project.xcworkspace/ 161 | # contents.xcworkspacedata 162 | # /xcuserdata/ 163 | # /(your name)/xcuserdatad/ 164 | # UserInterfaceState.xcuserstate 165 | # /xcshareddata/ 166 | # /xcschemes/ 167 | # (shared scheme name).xcscheme 168 | # /xcuserdata/ 169 | # /(your name)/xcuserdatad/ 170 | # (private scheme).xcscheme 171 | # xcschememanagement.plist 172 | # 173 | # 174 | 175 | #### 176 | # Xcode 4 - Deprecated classes 177 | # 178 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 179 | # 180 | # We're using source-control, so this is a "feature" that we do not want! 181 | 182 | *.moved-aside 183 | 184 | #### 185 | # OPTIONAL: Some well-known tools that people use side-by-side with Xcode / iOS development 186 | # 187 | # NB: I'd rather not include these here, but gitignore's design is weak and doesn't allow 188 | # modular gitignore: you have to put EVERYTHING in one file. 189 | # 190 | # COCOAPODS: 191 | # 192 | # c.f. http://guides.cocoapods.org/using/using-cocoapods.html#what-is-a-podfilelock 193 | # c.f. http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 194 | # 195 | #!Podfile.lock 196 | # 197 | # RUBY: 198 | # 199 | # c.f. http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ 200 | # 201 | #!Gemfile.lock 202 | # 203 | # IDEA: 204 | # 205 | # c.f. https://www.jetbrains.com/objc/help/managing-projects-under-version-control.html?search=workspace.xml 206 | # 207 | #.idea/workspace.xml 208 | # 209 | # TEXTMATE: 210 | # 211 | # -- UNVERIFIED: c.f. http://stackoverflow.com/a/50283/153422 212 | # 213 | #tm_build_errors 214 | 215 | #### 216 | # UNKNOWN: recommended by others, but I can't discover what these files are 217 | # 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # whoexec 2 | 3 | 4 | Whoexec is a tool that will monitor every `exec` call inside MacOS by using the latest Endpoint Security Framework, with this it's able to detect any execution of a target file. 5 | 6 | 7 | ## Use cases 8 | 9 | There are many cases for you to use this, you can use this to trace which process call a unknown binary, trace if a malware will attempt to execute some system command or even to check if your cronjob is running properly. 10 | 11 | ## Disclaimer 12 | 13 | I'm not a professional Apple developer (not even close), so I don't have the necessary entitlements to run this project in machines with SIP enabled, so if you want to use this for research porpuse you must disable SIP (you probably already did this), 14 | then you are ready to go, that's also the reason I will not publish any non signed/notorized binary in this repository. 15 | 16 | ### Building 17 | 18 | First, clone this project: 19 | 20 | > git clone https://github.com/AandersonL/whoexec.git 21 | 22 | Make sure to have `Xcode` installed in your machine, after this you can: 23 | 24 | * Open the project in Xcode and build it inside 25 | * Or run the following 26 | * xcodebuild -configuration Debug 27 | * The executable will be at `./build/Debug/whoexec` 28 | 29 | 30 | ## Using & example 31 | 32 | For the sake of simpliticy, you just have 1 argument to pass to this tiny tracer, the binary to be monitored: 33 | 34 | > sudo ./whoexec ps 35 | 36 | Then, after the endpoint security engine start and setup ours handlers, any kind of `exec` call will be logged in the terminal: 37 | 38 | ``` 39 | $ sudo ./whoexec ps 40 | 2021-12-15 18:11:57.518 whoexec[7889:145988] Monitoring exec calls... 41 | 2021-12-15 18:11:58.570 whoexec[7889:146065] ps was executed by /bin/bash PID: 7902 42 | 2021-12-15 18:12:02.683 whoexec[7889:146065] ps was executed by /bin/zsh PID: 7922 43 | ``` 44 | 45 | That's it, very simple and useful! 46 | 47 | Thanks and feel free to contribute and open issues :) 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /whoexec.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A24E0317276A558900FB0125 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A24E0316276A558900FB0125 /* main.m */; }; 11 | A24E031E276A559E00FB0125 /* whoexec.m in Sources */ = {isa = PBXBuildFile; fileRef = A24E031D276A559E00FB0125 /* whoexec.m */; }; 12 | A24E0324276A5C7600FB0125 /* libEndpointSecurity.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A24E0323276A5C7200FB0125 /* libEndpointSecurity.tbd */; }; 13 | A24E0327276A5DAF00FB0125 /* EndpointSecurity.m in Sources */ = {isa = PBXBuildFile; fileRef = A24E0326276A5DAF00FB0125 /* EndpointSecurity.m */; }; 14 | A24E032E276A7A2800FB0125 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A24E032B276A793F00FB0125 /* libbsm.tbd */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXCopyFilesBuildPhase section */ 18 | A24E0311276A558800FB0125 /* CopyFiles */ = { 19 | isa = PBXCopyFilesBuildPhase; 20 | buildActionMask = 2147483647; 21 | dstPath = /usr/share/man/man1/; 22 | dstSubfolderSpec = 0; 23 | files = ( 24 | ); 25 | runOnlyForDeploymentPostprocessing = 1; 26 | }; 27 | /* End PBXCopyFilesBuildPhase section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | A24E0313276A558900FB0125 /* whoexec */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = whoexec; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | A24E0316276A558900FB0125 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | A24E031D276A559E00FB0125 /* whoexec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = whoexec.m; sourceTree = ""; }; 33 | A24E031F276A55AF00FB0125 /* whoexec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = whoexec.h; sourceTree = ""; }; 34 | A24E0321276A5C6A00FB0125 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 35 | A24E0323276A5C7200FB0125 /* libEndpointSecurity.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libEndpointSecurity.tbd; path = usr/lib/libEndpointSecurity.tbd; sourceTree = SDKROOT; }; 36 | A24E0325276A5CF800FB0125 /* EndpointSecurity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EndpointSecurity.h; sourceTree = ""; }; 37 | A24E0326276A5DAF00FB0125 /* EndpointSecurity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EndpointSecurity.m; sourceTree = ""; }; 38 | A24E0328276A737A00FB0125 /* whoexec.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = whoexec.entitlements; sourceTree = ""; }; 39 | A24E0329276A793600FB0125 /* libbsm.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbsm.0.tbd; path = usr/lib/libbsm.0.tbd; sourceTree = SDKROOT; }; 40 | A24E032B276A793F00FB0125 /* libbsm.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbsm.tbd; path = usr/lib/libbsm.tbd; sourceTree = SDKROOT; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | A24E0310276A558800FB0125 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | A24E032E276A7A2800FB0125 /* libbsm.tbd in Frameworks */, 49 | A24E0324276A5C7600FB0125 /* libEndpointSecurity.tbd in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | A24E030A276A558800FB0125 = { 57 | isa = PBXGroup; 58 | children = ( 59 | A24E0315276A558900FB0125 /* whoexec */, 60 | A24E0314276A558900FB0125 /* Products */, 61 | A24E0320276A5C6A00FB0125 /* Frameworks */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | A24E0314276A558900FB0125 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | A24E0313276A558900FB0125 /* whoexec */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | A24E0315276A558900FB0125 /* whoexec */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | A24E0328276A737A00FB0125 /* whoexec.entitlements */, 77 | A24E0316276A558900FB0125 /* main.m */, 78 | A24E031D276A559E00FB0125 /* whoexec.m */, 79 | A24E031F276A55AF00FB0125 /* whoexec.h */, 80 | A24E0325276A5CF800FB0125 /* EndpointSecurity.h */, 81 | A24E0326276A5DAF00FB0125 /* EndpointSecurity.m */, 82 | ); 83 | path = whoexec; 84 | sourceTree = ""; 85 | }; 86 | A24E0320276A5C6A00FB0125 /* Frameworks */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | A24E032B276A793F00FB0125 /* libbsm.tbd */, 90 | A24E0329276A793600FB0125 /* libbsm.0.tbd */, 91 | A24E0323276A5C7200FB0125 /* libEndpointSecurity.tbd */, 92 | A24E0321276A5C6A00FB0125 /* Security.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | A24E0312276A558800FB0125 /* whoexec */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = A24E031A276A558900FB0125 /* Build configuration list for PBXNativeTarget "whoexec" */; 103 | buildPhases = ( 104 | A24E030F276A558800FB0125 /* Sources */, 105 | A24E0310276A558800FB0125 /* Frameworks */, 106 | A24E0311276A558800FB0125 /* CopyFiles */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = whoexec; 113 | productName = whoexec; 114 | productReference = A24E0313276A558900FB0125 /* whoexec */; 115 | productType = "com.apple.product-type.tool"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | A24E030B276A558800FB0125 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | BuildIndependentTargetsInParallel = 1; 124 | LastUpgradeCheck = 1320; 125 | TargetAttributes = { 126 | A24E0312276A558800FB0125 = { 127 | CreatedOnToolsVersion = 13.2; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = A24E030E276A558800FB0125 /* Build configuration list for PBXProject "whoexec" */; 132 | compatibilityVersion = "Xcode 13.0"; 133 | developmentRegion = en; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = A24E030A276A558800FB0125; 140 | productRefGroup = A24E0314276A558900FB0125 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | A24E0312276A558800FB0125 /* whoexec */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXSourcesBuildPhase section */ 150 | A24E030F276A558800FB0125 /* Sources */ = { 151 | isa = PBXSourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | A24E0317276A558900FB0125 /* main.m in Sources */, 155 | A24E0327276A5DAF00FB0125 /* EndpointSecurity.m in Sources */, 156 | A24E031E276A559E00FB0125 /* whoexec.m in Sources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXSourcesBuildPhase section */ 161 | 162 | /* Begin XCBuildConfiguration section */ 163 | A24E0318276A558900FB0125 /* Debug */ = { 164 | isa = XCBuildConfiguration; 165 | buildSettings = { 166 | ALWAYS_SEARCH_USER_PATHS = NO; 167 | CLANG_ANALYZER_NONNULL = YES; 168 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 169 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 170 | CLANG_CXX_LIBRARY = "libc++"; 171 | CLANG_ENABLE_MODULES = YES; 172 | CLANG_ENABLE_OBJC_ARC = YES; 173 | CLANG_ENABLE_OBJC_WEAK = YES; 174 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 175 | CLANG_WARN_BOOL_CONVERSION = YES; 176 | CLANG_WARN_COMMA = YES; 177 | CLANG_WARN_CONSTANT_CONVERSION = YES; 178 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 179 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 180 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 181 | CLANG_WARN_EMPTY_BODY = YES; 182 | CLANG_WARN_ENUM_CONVERSION = YES; 183 | CLANG_WARN_INFINITE_RECURSION = YES; 184 | CLANG_WARN_INT_CONVERSION = YES; 185 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 186 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 187 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 190 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 191 | CLANG_WARN_STRICT_PROTOTYPES = YES; 192 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 193 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 194 | CLANG_WARN_UNREACHABLE_CODE = YES; 195 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 196 | COPY_PHASE_STRIP = NO; 197 | DEBUG_INFORMATION_FORMAT = dwarf; 198 | ENABLE_STRICT_OBJC_MSGSEND = YES; 199 | ENABLE_TESTABILITY = YES; 200 | GCC_C_LANGUAGE_STANDARD = gnu11; 201 | GCC_DYNAMIC_NO_PIC = NO; 202 | GCC_NO_COMMON_BLOCKS = YES; 203 | GCC_OPTIMIZATION_LEVEL = 0; 204 | GCC_PREPROCESSOR_DEFINITIONS = ( 205 | "DEBUG=1", 206 | "$(inherited)", 207 | ); 208 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 209 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 210 | GCC_WARN_UNDECLARED_SELECTOR = YES; 211 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 212 | GCC_WARN_UNUSED_FUNCTION = YES; 213 | GCC_WARN_UNUSED_VARIABLE = YES; 214 | MACOSX_DEPLOYMENT_TARGET = 12.0; 215 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 216 | MTL_FAST_MATH = YES; 217 | ONLY_ACTIVE_ARCH = YES; 218 | SDKROOT = macosx; 219 | }; 220 | name = Debug; 221 | }; 222 | A24E0319276A558900FB0125 /* Release */ = { 223 | isa = XCBuildConfiguration; 224 | buildSettings = { 225 | ALWAYS_SEARCH_USER_PATHS = NO; 226 | CLANG_ANALYZER_NONNULL = YES; 227 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 229 | CLANG_CXX_LIBRARY = "libc++"; 230 | CLANG_ENABLE_MODULES = YES; 231 | CLANG_ENABLE_OBJC_ARC = YES; 232 | CLANG_ENABLE_OBJC_WEAK = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 238 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 239 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 240 | CLANG_WARN_EMPTY_BODY = YES; 241 | CLANG_WARN_ENUM_CONVERSION = YES; 242 | CLANG_WARN_INFINITE_RECURSION = YES; 243 | CLANG_WARN_INT_CONVERSION = YES; 244 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 246 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 247 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 248 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 249 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 250 | CLANG_WARN_STRICT_PROTOTYPES = YES; 251 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 252 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 253 | CLANG_WARN_UNREACHABLE_CODE = YES; 254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 255 | COPY_PHASE_STRIP = NO; 256 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 257 | ENABLE_NS_ASSERTIONS = NO; 258 | ENABLE_STRICT_OBJC_MSGSEND = YES; 259 | GCC_C_LANGUAGE_STANDARD = gnu11; 260 | GCC_NO_COMMON_BLOCKS = YES; 261 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 262 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 263 | GCC_WARN_UNDECLARED_SELECTOR = YES; 264 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 265 | GCC_WARN_UNUSED_FUNCTION = YES; 266 | GCC_WARN_UNUSED_VARIABLE = YES; 267 | MACOSX_DEPLOYMENT_TARGET = 12.0; 268 | MTL_ENABLE_DEBUG_INFO = NO; 269 | MTL_FAST_MATH = YES; 270 | SDKROOT = macosx; 271 | }; 272 | name = Release; 273 | }; 274 | A24E031B276A558900FB0125 /* Debug */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | CODE_SIGN_ENTITLEMENTS = whoexec/whoexec.entitlements; 278 | CODE_SIGN_STYLE = Automatic; 279 | PRODUCT_NAME = "$(TARGET_NAME)"; 280 | }; 281 | name = Debug; 282 | }; 283 | A24E031C276A558900FB0125 /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | CODE_SIGN_ENTITLEMENTS = whoexec/whoexec.entitlements; 287 | CODE_SIGN_STYLE = Automatic; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | }; 290 | name = Release; 291 | }; 292 | /* End XCBuildConfiguration section */ 293 | 294 | /* Begin XCConfigurationList section */ 295 | A24E030E276A558800FB0125 /* Build configuration list for PBXProject "whoexec" */ = { 296 | isa = XCConfigurationList; 297 | buildConfigurations = ( 298 | A24E0318276A558900FB0125 /* Debug */, 299 | A24E0319276A558900FB0125 /* Release */, 300 | ); 301 | defaultConfigurationIsVisible = 0; 302 | defaultConfigurationName = Release; 303 | }; 304 | A24E031A276A558900FB0125 /* Build configuration list for PBXNativeTarget "whoexec" */ = { 305 | isa = XCConfigurationList; 306 | buildConfigurations = ( 307 | A24E031B276A558900FB0125 /* Debug */, 308 | A24E031C276A558900FB0125 /* Release */, 309 | ); 310 | defaultConfigurationIsVisible = 0; 311 | defaultConfigurationName = Release; 312 | }; 313 | /* End XCConfigurationList section */ 314 | }; 315 | rootObject = A24E030B276A558800FB0125 /* Project object */; 316 | } 317 | -------------------------------------------------------------------------------- /whoexec.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /whoexec.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /whoexec.xcodeproj/xcshareddata/xcschemes/whoexec.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 | -------------------------------------------------------------------------------- /whoexec/EndpointSecurity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import 4 | #import 5 | 6 | @interface EndpointSecurity : NSObject 7 | 8 | @property es_client_t* esClient; 9 | @property NSString* lastError; 10 | 11 | - (bool) subscribeClient: (es_event_type_t[]) subs withSize: (int)n andHandler:(es_handler_block_t)handler; 12 | @end 13 | -------------------------------------------------------------------------------- /whoexec/EndpointSecurity.m: -------------------------------------------------------------------------------- 1 | #import "EndpointSecurity.h" 2 | 3 | @implementation EndpointSecurity 4 | 5 | - (bool) subscribeClient:(es_event_type_t*) subs withSize: (int)n andHandler:(es_handler_block_t)handler { 6 | self.esClient = NULL; 7 | es_new_client_result_t newClientResult = es_new_client(&_esClient, handler); 8 | bool ok = newClientResult == ES_NEW_CLIENT_RESULT_SUCCESS; 9 | 10 | if (!ok) { 11 | // Error handler 12 | switch (newClientResult) { 13 | case ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED: 14 | _lastError = @"Extension is not running as root!"; 15 | break; 16 | case ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED: 17 | _lastError = @"Extesion is missing entitlement."; 18 | break; 19 | case ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED: 20 | _lastError = @"Not permitted to execute!"; 21 | break; 22 | case ES_NEW_CLIENT_RESULT_ERR_TOO_MANY_CLIENTS: 23 | _lastError = @"Exceeded the maximum of simultaneously-connected ES clients."; 24 | break; 25 | case ES_NEW_CLIENT_RESULT_ERR_INVALID_ARGUMENT: 26 | _lastError = @"Invalid argument to es_new_client(); client or handler was null."; 27 | break; 28 | case ES_NEW_CLIENT_RESULT_ERR_INTERNAL: 29 | _lastError = @"Failed to connect to the Endpoint security subsystem."; 30 | break; 31 | } 32 | 33 | return ok; 34 | } 35 | 36 | ok = ES_RETURN_SUCCESS == es_subscribe(_esClient, subs, n); 37 | 38 | return ok; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /whoexec/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "whoexec.h" 3 | 4 | 5 | int main(int argc, const char * argv[]) { 6 | int exitCode = EXIT_SUCCESS; 7 | if (argc < 2) { 8 | fprintf(stderr, "Usage: %s EXECUTABLE_FILE\n", argv[0]); 9 | exitCode = EXIT_FAILURE; 10 | goto bye; 11 | 12 | } 13 | 14 | @autoreleasepool { 15 | 16 | NSString* target = [[NSString alloc] initWithUTF8String:argv[1]]; 17 | WhoExec* execTracer = [[WhoExec alloc] init: target]; 18 | 19 | if (execTracer.ok) { 20 | NSLog(@"Monitoring exec calls..."); 21 | [execTracer monitor:^(Executed* executed) { 22 | NSLog(@"%@ was executed by %@ PID: %d\n", target, executed->executor, executed->pid); 23 | }]; 24 | 25 | } else { 26 | NSString* error = [execTracer getLastError]; 27 | NSLog(@"Error: %@\n", error); 28 | 29 | } 30 | } 31 | bye: 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /whoexec/whoexec.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.endpoint-security.client 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /whoexec/whoexec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import 4 | #import "EndpointSecurity.h" 5 | #import 6 | #import 7 | 8 | 9 | // Events that will be subscribed 10 | static es_event_type_t events[] = { 11 | ES_EVENT_TYPE_NOTIFY_EXEC, 12 | }; 13 | 14 | static int eventsSize = 1; 15 | 16 | 17 | typedef struct executed { 18 | NSString* executor; 19 | pid_t pid; 20 | } Executed; 21 | 22 | // WhoExec interface 23 | @interface WhoExec : EndpointSecurity 24 | 25 | @property NSString* targetName; 26 | @property bool ok; 27 | @property void (^callback) (Executed*); 28 | 29 | 30 | - (id) init: (NSString*) target; 31 | - (void) monitor: (void (^)(Executed*))findFileCB; 32 | - (void) handler: (es_client_t*) client withMessage: (const es_message_t*) message; 33 | - (NSString*) getLastError; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /whoexec/whoexec.m: -------------------------------------------------------------------------------- 1 | #import "whoexec.h" 2 | 3 | @implementation WhoExec 4 | 5 | @synthesize targetName; 6 | @synthesize ok; 7 | 8 | 9 | - (id) init: (NSString*) target { 10 | self = [super init]; 11 | self.callback = NULL; 12 | self.ok = [super subscribeClient:events withSize:eventsSize andHandler:^(es_client_t *client, const es_message_t* message) { 13 | // Forward 14 | if (!self.callback) return; 15 | 16 | [self handler:client withMessage:message]; 17 | }]; 18 | self.targetName = target; 19 | return self; 20 | } 21 | 22 | 23 | - (void) monitor:(void (^)(Executed*))findFileCB { 24 | self.callback = findFileCB; 25 | [[NSRunLoop currentRunLoop] run]; 26 | } 27 | 28 | - (void) handler:(es_client_t *)client withMessage:(const es_message_t *)message { 29 | es_process_t* process = message->process; 30 | if (process->is_es_client) return; 31 | 32 | NSString* path; 33 | pid_t execPid = audit_token_to_pid(process->audit_token); 34 | es_event_exec_t exec; 35 | 36 | if (message->event_type == ES_EVENT_TYPE_NOTIFY_EXEC) { 37 | exec = message->event.exec; 38 | path = [[NSString alloc] initWithUTF8String:exec.target->executable->path.data]; 39 | 40 | if (![targetName isEqual:[path lastPathComponent]]) return; 41 | 42 | Executed executed = { 43 | .executor = [[NSString alloc] initWithUTF8String: process->executable->path.data], 44 | .pid = execPid 45 | }; 46 | 47 | self.callback(&executed); 48 | 49 | } 50 | } 51 | 52 | 53 | - (NSString*) getLastError { 54 | return self.lastError; 55 | } 56 | @end 57 | --------------------------------------------------------------------------------