← Retour à HackTheBox

HackTheBox | emo

7 novembre 2026•7 min•Facile

emo

Dans emo, le SOC remonte une infection par WearRansom à un document Word reçu par phishing. On dispose de ce document, emo.doc, pour comprendre comment il lance le malware et retrouver le flag.

Scénario du challenge emo sur HackTheBox et archive fournie

Je pars sur une analyse statique, en lisant le document et ses macros sans les exécuter.

Identifier le document

Je commence par vérifier le type du fichier :

file emo.doc

Le résultat indique Composite Document File V2 Document et mentionne Microsoft Office Word. Il s'agit d'un conteneur OLE, le format utilisé par les anciens documents Office. Il peut contenir le texte du document et plusieurs flux dédiés aux macros VBA.

Extraire les macros

J'utilise olevba pour lire les macros sans les lancer :

mkdir -p work/emo-analysis
olevba emo.doc > work/emo-analysis/macros.txt
less work/emo-analysis/macros.txt

L'outil extrait trois modules VBA et des valeurs stockées dans un formulaire. Une procédure attire directement l'attention :

Private Sub Document_open()
Get4ipjzmjfvp.X8twf_cydt6
End Sub

Document_open est un point d'entrée automatique. Si Word autorise les macros, l'ouverture du document déclenche l'appel à X8twf_cydt6.

Identification du format OLE, macro Document_open et lecture du texte du document avec StoryRanges

Le reste du code est rempli de calculs et de noms aléatoires. Je suis les variables qui arrivent jusqu'à la création du processus pour retrouver la commande lancée.

Retrouver la commande cachée dans le document

La fonction appelée lit le texte principal du document :

sss = Dw75ayd2hpcab6.StoryRanges.Item(1)

La macro récupère donc sa commande dans le texte du document. Il faut examiner les deux pour la reconstruire.

Une fonction supprime un marqueur répété :

X4al3i4glox = Replace(Gav481k8nh28, "][(s)]w", Sxybmdt069cn)

Dans ce traitement, la valeur de remplacement est vide. Après suppression de ][(s)]w, une longue chaîne commence par :

POwersheLL -windowstyle hidden -ENCOD

Il reste toutefois une deuxième couche d'obfuscation. La fonction AWLDFu7C7y conserve les 50 premiers caractères puis un caractère sur deux à partir du 51e :

AWLDFu7C7y = Mid(AMUjF5h4uz, 1, 50)
For i = 51 To Len(AMUjF5h4uz) Step 2
    AWLDFu7C7y = AWLDFu7C7y & Mid(AMUjF5h4uz, i, 1)
Next i

Fonction VBA conservant les 50 premiers caractères puis un caractère sur deux à partir du 51e

Le VBA compte les caractères à partir de 1. En Python, le même traitement s'écrit :

command = clean[:50] + clean[50::2]

Les 50 premiers caractères forment le préfixe de la commande. La suite contient le texte Base64 avec des caractères parasites intercalés. Prendre un caractère sur deux permet de retrouver le contenu attendu.

Le document utilise également WMI pour créer un processus, on retrouve les noms reconstruits winmgmts:win32_Process et winmgmts:win32_ProcessStartup. La commande reconstruite est transmise à la méthode Create.

Décoder le PowerShell

La commande demande une fenêtre cachée avec -windowstyle hidden. Le paramètre -ENCOD est une forme abrégée de -EncodedCommand.

Le texte qui suit est en Base64. Pour ce paramètre PowerShell, les octets décodés représentent une chaîne UTF-16LE. Je reproduis ce décodage en Python. Dans cet extrait, command contient la chaîne reconstruite :

encoded = re.split(r'-ENCOD\s+', command, flags=re.I)[1].strip()
powershell = base64.b64decode(encoded, validate=True).decode('utf-16le')

J'enregistre le résultat dans work/emo-analysis/payload.ps1.txt. Le PowerShell reste obfusqué mais on peut maintenant suivre ses appels.

Il crée un objet Net.WebClient, prépare plusieurs URL puis essaie de télécharger un fichier avec DownloadFile. Les chemins construits pointent vers :

$HOME\Jrbevk4\Ccwr_2h\Ale7g_8.exe
$HOME\Jrbevk4\Ccwr_2h\Ale7g_8.conf

Le .exe reçoit la charge téléchargée et le .conf sa configuration.

La liste contient sept adresses. Je les retranscris sous une forme désactivée :

hxxp://da-industrial[.]htb/js/9IdLP/
hxxp://daprofesional[.]htb/data4/hWgWjTV/
hxxps://dagranitegiare[.]htb/wp-admin/tV/
hxxp://www.outspokenvisions[.]htb/wp-includes/aWoM/
hxxp://mobsouk[.]htb/wp-includes/UY30R/
hxxp://biglaughs[.]htb/smallpotatoes/Y/
hxxps://ngllogistics[.]htb/adminer/W3mkB/

Le script parcourt ces URL dans une boucle avec un try/catch. Si un téléchargement échoue, il peut passer à l'adresse suivante. Il vérifie ensuite que le fichier téléchargé fait au moins 45199 octets.

Si le fichier atteint cette taille, le script écrit la configuration puis lance l'exécutable avec Win32_Process.Create. Le document sert donc à télécharger et démarrer la charge suivante. C'est le comportement décrit par le code extrait.

Examiner la configuration

Une variable revient plusieurs fois dans le PowerShell : $FN5ggmsH. Elle est initialisée avec des nombres puis complétée par plusieurs tableaux.

$FN5ggmsH = (182,187,229,146,231,177,151,149,166)

Plus loin, le script transforme les caractères de l'URL utilisée avec un XOR :

[byte][char]${_} -bxor 0xdf

L'URL transformée est ajoutée au tableau puis l'ensemble est encodé en Base64 et écrit dans le fichier .conf. Le XOR permet donc aussi de retrouver le texte des constantes déjà présentes dans ce tableau.

J'extrais les listes numériques affectées à $FN5ggmsH puis j'applique la même clé. powershell contient ici le texte décodé à l'étape précédente :

values = []
for match in re.finditer(
    r'\$FN5ggmsH\s*(?:\+=|=)\s*\(([\d,]+)\)',
    powershell,
    re.I,
):
    values.extend(map(int, match[1].split(',')))

config = bytes(n ^ 0xdf for n in values).decode('ascii')
print(config)

Le décodage donne la configuration suivante :

id:M8nHJyeR;int:3000;jit:500;flag:HTB{*********************};url:;

Le champ url reste vide dans cette sortie. Il est rempli au moment du téléchargement, alors qu'ici je décode seulement les valeurs présentes dans le document.

Résultat du script avec commande PowerShell reconstruite, configuration XOR, flag et sept URL extraites

Le champ flag contient la valeur attendue. La sortie affiche aussi les sept URL préparées pour le téléchargement.

Je soumets la valeur sur HackTheBox et le challenge est validé.

Validation du challenge emo sur HackTheBox le 7 novembre 2026

Ce que je retiens

Le plus important était de suivre la commande entre le texte du document et les macros. Le marqueur répété puis les caractères intercalés cachaient un PowerShell encodé en Base64.

Une fois décodé, il révèle les URL de téléchargement et la configuration du malware. Le XOR utilisé pour cette configuration donne directement le flag.

Voir aussi d'autres catégories...

Ces thèmes pourraient aussi t'intéresser.