Catégorie: Forensique
Points: 257
Description: Notre SoC a détecté qu'un document confidentiel avait été exfiltré ! La méthode utilisée ne semble pas avancée et heureusement, une capture réseau a pu être faite au bon moment... Retrouvez ce document.
Fichiers: Exfiltration.pcap
Un document a ete extrait via des requêtes POST. Un xor sur le fichier retrouvé nous permet de lire le flag dans un document word.
Quand on ouvre le fichier avec wireshark on s'aperçoit qu'il y a 27242 paquets à regarder !
Bon bah... C'est parti !
En survolant les paquets on remarque qu'il y a pas mal de flux TCP.
En parcourant tous les flux TCP on obtient plusieurs échanges intéressants du même type:
Ce qui nous interpelle c'est notamment ce message:
<h1>Welcome to my panel!</h1>
<p>If you see this page, the malware is successfully installed and
working. No further configuration is required.</p>
Et le fait que les requêtes sont faites via la méthode POST avec de la donnée passe en paramètre de la forme:
data=3528706771637b6b6d63b9c7f82d736365637363656373636563786365632c11000f004c4b1116&uuid=80cxgrf7ws5phwlb7z3q
A chaque requête le paramètre data change mais pas l'uuid. l'uuid doit être un identifiant unique pour permettre au serveur distant de reconstituer le fichier exfiltre via le champ data.
Un petit script en python pour récupérer tous ces paquets et les assembler.
>_ cat extract.py
#!/usr/bin/env python3
from scapy.all import *
import binascii
packets = rdpcap('exfiltration.pcap')
data = ''
for packet in packets:
if packet[IP].dst == '198.18.0.10' and packet[IP].src == '192.168.1.26':
if Raw in packet:
p = str(packet[Raw].load.decode("UTF-8"))
p = p.split("&uuid")[0]
p = p.split('data=')[1:]
if p:
p = p[0]
data += p
print(data)
file = open("out.txt", 'wb')
file.write(binascii.unhexlify(data))
>_ ./extract.py
>_ file out.txt
out.txt: data
Malheureusement le fichier extrait est illisible.
Heureusement, lors de la conception du script j'ai oublie de filtrer uniquement sur les paquets qui contenait de la donnée brute (le champ Raw). En le testant, il plantait des qu'un paquet ne contenait pas le champ Raw. Je me suis aperçu que le paquet en question était un paquet ICMP avec une donnée intéressante: config : exfiltered_file_size=4193bytes
Pour en savoir plus on filtre dans wireshark sur les paquets ICMP:
Et on obtient 4 infos intéressantes:
config : exfiltered_file_size=4193bytes
config : file_type=DOCX
config : data_len_for_each_packet=random
config : encryption=XOR
Le fichier fais bien 4193 bytes, donc toute la donnée a bien ete extraite des paquets.
>_ ls -l out.txt
-rw-r--r-- 1 lambdhack users 4193 May 22 20:06 out.txt
Maintenant on sait que le fichier exfiltre est un document word et que le chiffrement utilise est un xor. Pour retrouver la cle on va xorer les premiers bits du fichier avec le magic number des document words. Un petit tour sur File signature table pour trouver le magic number d'un docx.
Après avoir fait un xor, on retrouve la cle qui est ecsc
évidemment !
Maintenant on xor cette cle sur tous le fichier pour retrouver le docx original.
>_ cat xor.py
#!/usr/bin/env python3
import binascii
def xor(file1_b, key):
file_size = len(file1_b)
key_size = len(key)
xord_byte_array = bytearray(file_size)
key_pad = key
for i in range(file_size):
key_pad += key
# XOR between the files
for i in range(file_size):
xord_byte_array[i] = file1_b[i] ^ key_pad[i]
open('data.docx', 'wb').write(xord_byte_array)
if __name__ == '__main__':
key = 'ecsc'.encode()
data = open('out.txt', 'rb').read()
xor(data, key)
>_ file data.docx
data.docx: Microsoft Word 2007+
Le fichier a bien ete déchiffré.
ECSC{v3ry_n01sy_3xf1ltr4t10n}