macoskeyboardmousechrome-remote-desktop

How to simulate keyboard and mouse events using CGEventPost in login window mac OS?


I have created a pre-login agent which uses CGEventPost for simulating keyboard. FYI I am developing a remote control app similar to teamviewer.

Keyboard

CGEventRef keyEvent = CGEventCreateKeyboardEvent( NULL, keyCode, down ) ;
CGEventPost( kCGHIDEventTap, keyEvent ) ;
CFRelease( keyEvent ) ;

Mouse

CGEventRef event = CGEventCreateMouseEvent(eventSource, eventType, mouseLocation, mouseButton );
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);

Pre-login launch agent

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>my app label</string>
        <key>LimitLoadToSessionType</key>
        <string>LoginWindow</string>
        <key>RunAtLoad</key>
        <true/>
        <key>WorkingDirectory</key>
        <string>My app directory</string>
        <key>ProgramArguments</key>
        <array>
                <string>app absolute path</string>
                <string>service</string>
                <string>myservice</string>
        </array>
        <key>KeepAlive</key>
        <true/>
</dict>
</plist>

CGEventPost is not working, I get the following in the Console logs after login

Untrusted apps are not allowed to connect to
Window Server before login.

I have searched o chromium's remote control (which has keyboard and mouse simulation working) source code. They use CGEventPost for keyboard, but it works in login window.

https://cs.chromium.org/chromium/src/remoting/host/input_injector_mac.cc?rcl=0&l=42

They seem to use a sh file in privileged helper tools directory and use to to load the service, I tried putting our service in privileged helpers tool, but still the event handling fails.

The Deprecated API CGPostMouseEvent, CGPostKeyBoardEvent work without problem , but would really like to know how non deprecated keyboard API works in chromium.


Solution

  • There is undocumented (classic apple , security through obscurity) stuff you should add to binary's sections, in order to make CGEventPost magically work when running in LoginWindow Context.

    If you are using gcc, add the following to the compile flags

    gcc <YOUR SOURCES AND FLAGS> -sectcreate CGPreLoginApp __CGPreLoginApp /dev/null
    

    If you are using XCode, add the following to Other Linker flags in the Build settings of the project:

    "-sectcreate"
    __CGPreLoginApp
    __cgpreloginapp
    /dev/null
    

    Refer https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDFamily.xcodeproj/project.pbxproj project file for the LDFLAGS