SOC Prime Bias: Élevé

13 Feb 2026 14:05 UTC

OysterLoader Dévoilé : À l’Intérieur d’un Chargeur d’Évasion à Plusieurs Étapes

Author Photo
Ruslan Mikhalov Chief of Threat Research at SOC Prime linkedin icon Suivre
OysterLoader Dévoilé : À l’Intérieur d’un Chargeur d’Évasion à Plusieurs Étapes
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Résumé

OysterLoader est un chargeur multi-étapes en C++ utilisé pour déployer des rançongiciels et des logiciels malveillants de type Vidar. Il se propage via des sites compromis qui imitent des installateurs de logiciels légitimes et est livré sous forme d’installateur Microsoft (MSI). Pour compliquer l’analyse, il utilise l’inondation d’appels API, la résolution dynamique d’API personnalisée, les vérifications anti-débogage et une routine de décompression LZMA personnalisée. Le chargeur communique avec une infrastructure C2 HTTPS à niveaux en utilisant des en-têtes HTTP obscurcis et un encodage propriétaire de type Base64.

Enquête

Le rapport décrit quatre étapes : un obfuscateur emballé (TextShell), une couche de code shell qui gonfle le contenu avec LZMA, un téléchargeur qui effectue des vérifications de l’environnement et crée un mutex, et une étape finale qui dépose une DLL et installe une tâche planifiée. Le trafic C2 repose sur des IPs/domaines codés en dur, des agents utilisateurs personnalisés, et une livraison de charge utile stéganographique via des icônes PNG. La persistance est maintenue par une tâche planifiée configurée pour s’exécuter toutes les 13 minutes.

Atténuation

Bloquez les installateurs MSI non signés provenant de sources non fiables et surveillez la création de motifs de mutex connus. Signalez les motifs de nom de tâche planifiée et l’utilisation de rundll32.exe pour charger des DLLs depuis %APPDATA%. Lorsque cela est possible, appliquez l’inspection TLS pour identifier les en-têtes HTTP personnalisés et les agents utilisateurs utilisés par le chargeur.

Réponse

Si détecté, isolez l’hôte, terminez la tâche planifiée et supprimez le fichier COPYING3.dll déposé. Cherchez des charges utiles supplémentaires, énumérez les processus correspondant aux valeurs de mutex, bloquez les domaines/IPs C2 répertoriés, et mettez à jour les détections pour le comportement d’inondation d’API et l’encodage Base64 personnalisé.

Flux d’attaque

Exécution Simulation

Prérequis : La vérification préalable de la télémétrie et de la ligne de base doit avoir réussi.

Raisonnement : Cette section détaille l’exécution précise de la technique de l’adversaire (TTP) conçue pour déclencher la règle de détection. Les commandes et le récit DOIVENT refléter directement les TTPs identifiés et viser à générer la télémétrie exacte attendue par la logique de détection. Des exemples abstraits ou non liés entraîneront un diagnostic erroné.

  • Récit & Commandes de l’Attaque :
    L’adversaire, ayant obtenu un premier accès à l’endpoint, déploie la charge utile OysterLoader.

    1. Enregistrement DLL via Rundll32 – Le chargeur copie une DLL malveillante (COPYING3.dll) dans le répertoire temporaire et l’enregistre en utilisant rundll32.exe avec le point d’entrée DllRegisterServer , produisant une ligne de commande qui correspond à selection1.
    2. Vérification Anti-Débogage – Pour échapper à l’analyse, la charge utile charge ntdll.dll et appelle IsDebuggerPresent. Cela génère un enregistrement de processus où Image contient ntdll.dll et la ligne de commande inclut IsDebuggerPresent, satisfaisant selection2.
    3. Allocation Mémoire – Pour une exécution en mémoire, le chargeur invoque NtAllocateVirtualMemory via ntdll.dll. L’événement de création de processus résultant contient NtAllocateVirtualMemory dans la ligne de commande, satisfaisant selection3.
  • Script de Test de Régression :

    # Script de validation de détection OysterLoader – PowerShell
    # ----------------------------------------------------
    # 1. Créer une DLL malveillante factice (fichier vide pour la simulation)
    $dllPath = "$env:TEMPCOPYING3.dll"
    New-Item -Path $dllPath -ItemType File -Force | Out-Null
    
    # 2. Déclencher selection1 – rundll32 avec DllRegisterServer
    Write-Host "Exécution de selection1 (enregistrement DLL rundll32)..."
    Start-Process -FilePath "rundll32.exe" -ArgumentList "`"$dllPath`" DllRegisterServer" -NoNewWindow
    
    # 3. Déclencher selection2 – ntdll avec IsDebuggerPresent
    Write-Host "Exécution de selection2 (IsDebuggerPresent)..."
    $scriptBlock = {
        Add-Type -MemberDefinition @"
            [DllImport("ntdll.dll", SetLastError = true)]
            public static extern bool IsDebuggerPresent();
    "@ -Namespace WinAPI -Name NativeMethods
        [WinAPI.NativeMethods]::IsDebuggerPresent() | Out-Null
    }
    Start-Job -ScriptBlock $scriptBlock | Wait-Job | Receive-Job
    
    # 4. Déclencher selection3 – ntdll avec NtAllocateVirtualMemory
    Write-Host "Exécution de selection3 (NtAllocateVirtualMemory)..."
    $scriptBlock2 = {
        Add-Type -MemberDefinition @"
            [DllImport("ntdll.dll", SetLastError = true)]
            public static extern int NtAllocateVirtualMemory(
                IntPtr ProcessHandle,
                ref IntPtr BaseAddress,
                IntPtr ZeroBits,
                ref UIntPtr RegionSize,
                uint AllocationType,
                uint Protect);
    "@ -Namespace WinAPI -Name NativeMethods
        $process = [System.Diagnostics.Process]::GetCurrentProcess()
        $handle = $process.Handle
        $base = [IntPtr]::Zero
        $size = [UIntPtr]::Zero
        [WinAPI.NativeMethods]::NtAllocateVirtualMemory($handle, [ref]$base, [IntPtr]::Zero, [ref]$size, 0x1000, 0x04) | Out-Null
    }
    Start-Job -ScriptBlock $scriptBlock2 | Wait-Job | Receive-Job
    
    # Nettoyage
    Remove-Item -Path $dllPath -Force
    Write-Host "Simulation terminée."
  • Commandes de Nettoyage :

    # Assurez-vous que tout processus rundll32 résiduel ou travaux sont terminés
    Get-Process -Name "rundll32" -ErrorAction SilentlyContinue | Stop-Process -Force
    Get-Job | Remove-Job -Force
    # Supprimer la DLL temporaire si encore présente
    $tempDll = "$env:TEMPCOPYING3.dll"
    if (Test-Path $tempDll) { Remove-Item $tempDll -Force }