Skip to content
Anti-analyseintermediate

NtSetInformationThread (ThreadHideFromDebugger)

Le malware appelle NtSetInformationThread avec la classe ThreadHideFromDebugger pour détacher un thread du débogueur, empêchant les points d'arrêt et exceptions d'atteindre l'analyste.

NtSetInformationThread expose une classe d'information de thread appelée ThreadHideFromDebugger (valeur 0x11). Lorsqu'un thread positionne ce drapeau sur lui-même, le noyau cesse de transmettre les événements de débogage de ce thread au débogueur attaché. Les exceptions suivantes — la plus importante étant l'exception de point d'arrêt INT3 — ne sont plus routées vers le débogueur, de sorte qu'un point d'arrêt dans le thread masqué fait planter le processus au lieu de l'arrêter.

C'est une technique économique à appel unique, très efficace contre un débogage naïf : l'analyste pose un point d'arrêt, le programme l'atteint, et au lieu de s'arrêter le processus se termine simplement sur une exception non gérée.

Fonctionnement

Le malware résout le stub de syscall depuis ntdll.dll et l'appelle avec la classe de masquage. Aucun tampon n'est requis — la longueur et le pointeur sont tous deux à zéro.

c
#include <windows.h>

#define ThreadHideFromDebugger 0x11

typedef NTSTATUS (NTAPI *pfnNtSIT)(HANDLE, ULONG, PVOID, ULONG);

void HideCurrentThread(void)
{
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pfnNtSIT NtSIT = (pfnNtSIT)GetProcAddress(hNtdll, "NtSetInformationThread");
    // hThread = current thread (-2), class 0x11, buffer NULL, length 0
    NtSIT((HANDLE)-2, ThreadHideFromDebugger, NULL, 0);
}

Sous Windows 10 et versions ultérieures, l'opération est détectable : appeler NtQueryInformationThread avec la même classe ThreadHideFromDebugger renvoie l'état courant du drapeau. Le malware peut ainsi l'utiliser comme vérification d'altération — si le drapeau ne se relit pas comme activé, un hook anti-anti-débogage est suspecté.

Détection & contournement

  • Statique — Recherchez les références d'import ou via GetProcAddress à NtSetInformationThread (ou ZwSetInformationThread). Dans IDA/Ghidra, cherchez la constante 0x11 poussée comme deuxième argument avec un tampon NULL et une longueur nulle ; le pseudo-handle (HANDLE)-2 (0xFFFFFFFE) du thread courant est un indice fort. Croisez avec un NtQueryInformationThread proche pour la vérification d'altération sous Win10+.
  • Dynamique — Dans x64dbg, posez un point d'arrêt sur ntdll!NtSetInformationThread et inspectez le deuxième argument (rdx/pile) pour 0x11. Lorsque vous voyez l'appel, passez par-dessus sans laisser le drapeau prendre effet, ou changez la valeur de classe en une valeur inoffensive avant l'exécution.
  • Patch / contournement — Avalez l'appel : hookez NtSetInformationThread et renvoyez STATUS_SUCCESS pour la classe 0x11 sans exécuter l'opération. Vous pouvez aussi NOP le site d'appel, ou patcher la constante de classe 0x11 poussée vers une valeur inutilisée pour que le noyau l'ignore.
  • Outils — L'option « NtSetInformationThread (ThreadHideFromDebugger) » de ScyllaHide intercepte l'appel automatiquement et spoofe aussi la relecture de NtQueryInformationThread. TitanHide fait de même au niveau noyau. Frida : Interceptor.attach sur l'export et réécriture de args[1] lorsqu'il vaut 0x11.
Votes

Commentaires(0)