1 Reply
      Latest reply on Apr 24, 2019 12:55 AM by eskimo
      another. Level 1 Level 1 (0 points)

        I'm currently working on a method of detecting apps that might have global access to user keystrokes. Among the currently available APIs(CGEventTap, IOHIDManager) I've also encountered [NSEvent addGlobalMonitorForEventsMatchingMask:handler], which upon further inspection seems to call into InstallEventHandler( found in HIToolbox):

        extern OSStatus 
        InstallEventHandler(
          EventTargetRef         inTarget,
          EventHandlerUPP        inHandler,
          ItemCount              inNumTypes,
          const EventTypeSpec *  inList,
          void *                 inUserData,
          EventHandlerRef *      outRef) 
        
        

        An example of this would be(requires approving the binary in System Preferences -> Accesibility):

        #import <Cocoa/Cocoa.h>
        #import <Carbon/Carbon.h>
        
        //Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/CarbonEvents.h
        extern void RunApplicationEventLoop(void);
        
        OSStatus globalKeyPress(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
        {
            NSEvent *anEvent = [NSEvent eventWithEventRef:theEvent];
            printf("%s", anEvent.characters.UTF8String);
            fflush(stdout);
            return CallNextEventHandler(nextHandler, theEvent);
        }
        
        int main(int argc, const char * argv[]) {
            @autoreleasepool {
                EventTypeSpec espec = {
                    .eventClass = kEventClassKeyboard,
                    .eventKind = kEventRawKeyUp
                };
        
                EventHandlerUPP handlerFunction = NewEventHandlerUPP(globalKeyPress);
                OSStatus err = InstallEventHandler(GetEventMonitorTarget(), handlerFunction, 1, &espec, NULL, NULL);
                if (err) {
                    NSLog(@"InstallEventHandler: %d", err);
                }
        
                RunApplicationEventLoop();
            }
            return 0;
        }
        
        

        The documentation for GetEventMonitorTarget states that:

        The event monitor target is a special event target used to
         *    monitor user input events across all processes. When an event
         *    handler is installed on the event monitor target, the Carbon
         *    Event Manager examines the EventTypeSpec for user input event
         *    types, such as mouse-down, mouse-up, key-down, and so forth. It
         *    then requests that the WindowServer make copies of any of these
         *    events that are sent to any process, and deliver them to the
         *    current process also...
        
        

        I'm guessing that some process must be managing a global list of apps registered for these events.

        How can I inspect the list(ideally by registering a callback, but polling is also fine) of processes which have installed one of these global event handlers?

        • Re: Detecting calls made to InstallEventHandler
          eskimo Apple Staff Apple Staff (11,655 points)

          How can I inspect the list … of processes which have installed one of these global event handlers?

          There’s no API for this.  The HIToolbox event monitor is implemented on top of the window server, and the window server has very few public APIs, none of which directly expose the state of the HIToolbox event monitor.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"