Skip to content

Instantly share code, notes, and snippets.

@ljos
Last active January 6, 2024 07:36
Show Gist options
  • Save ljos/3019549 to your computer and use it in GitHub Desktop.
Save ljos/3019549 to your computer and use it in GitHub Desktop.
Showing how to listen to all keypresses in OS X through the Cocoa API using Python and PyObjC
#!/usr/bin/env python
#
# cocoa_keypress_monitor.py
# Copyright © 2016 Bjarte Johansen <Bjarte.Johansen@gmail.com>
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# “Software”), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Usage:
#
# Goto System Preferences > Security & Privacy > Accessibility and add
# Python to apps allowed to control your computer. If it is not in the
# list, the easiest is to run this file first and it should appear.
from AppKit import NSApplication, NSApp
from Foundation import NSObject, NSLog
from Cocoa import NSEvent, NSKeyDownMask
from PyObjCTools import AppHelper
class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, notification):
mask = NSKeyDownMask
NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, handler)
def handler(event):
try:
NSLog(u"%@", event)
except KeyboardInterrupt:
AppHelper.stopEventLoop()
def main():
app = NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
NSApp().setDelegate_(delegate)
AppHelper.runEventLoop()
if __name__ == '__main__':
main()
@Ali-Razmjoo
Copy link

Hi huys , i enable access for assistive devices , but how can work
without it ? i have a ruby code , it can use without enable this
i need python version please

check this

https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/capture/keylog_recorder.rb

@ljos
Copy link
Author

ljos commented Jul 19, 2014

@G3n3Rall This codes metasploit to do the heavy lifting. My code uses the Cocoa library calls directly and requires that you enable the access to assistive devices because of that. If you need it to work without the assistive devices enabled you will need to figure out how to work with python and metasploit (or figure out how metasploit does that).

@Quentin-M
Copy link

Hey.

Kinda strange because it generates the following exception when using ^C

An uncaught exception was raised <type 'exceptions.KeyboardInterrupt'>: 
(
    0   CoreFoundation                      0x00007fff8f87564c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff88e916de objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8f8751e9 -[NSException raise] + 9
    3   _objc.so                            0x00000001012e1a8b PyObjCErr_ToObjCWithGILState + 46
    4   _objc.so                            0x00000001012ce52d PyObjCFFI_MakeClosure + 5097
    5   libffi.dylib                        0x00007fff8ed73a07 ffi_closure_unix64_inner + 511
    6   libffi.dylib                        0x00007fff8ed730c6 ffi_closure_unix64 + 70
    7   HIToolbox                           0x00007fff8c54232c _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 1260
    8   HIToolbox                           0x00007fff8c54176e _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 386
    9   HIToolbox                           0x00007fff8c5415e2 SendEventToEventTargetWithOptions + 43
    10  HIToolbox                           0x00007fff8c5771fe _ZL29ToolboxEventDispatcherHandlerP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv + 1762
    11  HIToolbox                           0x00007fff8c542a55 _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 3093
    12  HIToolbox                           0x00007fff8c54176e _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 386
    13  HIToolbox                           0x00007fff8c556286 SendEventToEventTarget + 40
    14  AppKit                              0x00007fff94c0debb _DPSNextEvent + 2990
    15  AppKit                              0x00007fff94c0ce80 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
    16  AppKit                              0x00007fff94c00e23 -[NSApplication run] + 594
    17  libffi.dylib                        0x00007fff8ed72f44 ffi_call_unix64 + 76
    18  ???                                 0x00007fba864c94a0 0x0 + 140439093810336
)

@kismet-
Copy link

kismet- commented Jan 21, 2015

What if I want to write the output to a file?

@ljos
Copy link
Author

ljos commented Apr 1, 2015

@Quentin-M I think pyObjC returned a python KeyboardInterrupt before, but it seems it is not doing that anymore. It should be easy to fix, but I think that should be an exercise for the reader.

@kismet- You should be able to use standard python commands to output to a file, or you can use gurgeh/selfspy.

@JacyNewbs
Copy link

What is it supposed to print? I run and get no errors but also get no output, is this normal? It doesn't seem like it is, how do i prevent this?

@ljos
Copy link
Author

ljos commented Mar 8, 2016

@JacyNewbs It should print the event that contains the keyboard press. You probably have to turn on assistive devices and add python to the programs allowed to control your computer.

@jsrini78
Copy link

its working for me. thank you.
However, I have the following issue

  1. unable to stop the code ctl+C
  2. I want to create a log file in addition to display
    could you let me know the step. I tried , since it did not come out of loop I was not able to write in a file

@CrzPhil
Copy link

CrzPhil commented Aug 13, 2016

I get this error :
Traceback (most recent call last):
File "keylogger.py", line 1, in
from AppKit import NSApplication, NSApp
ImportError: No module named AppKit

And before you say somethin bout you gotta install appkit, I have I did all this pip install appkit thingy and it installed I think.
Please HELP!!!!

@skabbit
Copy link

skabbit commented Sep 3, 2016

Unable to stop the code control + C.
And can't get into handler. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment