Skip to content
Anti-analyseintermediate

Software Breakpoint Scanning

Le malware scanne ou calcule un checksum de sa propre section de code à la recherche des octets 0xCC (INT3) laissés par les points d'arrêt logiciels d'un débogueur, détectant l'analyse sans aucun appel d'API.

Les points d'arrêt logiciels fonctionnent en remplaçant le premier octet de l'instruction cible par 0xCC (l'opcode INT3) ; le débogueur restaure l'octet original lorsqu'il s'arrête. Le malware exploite cela en lisant sa propre section .text à la recherche d'octets 0xCC parasites, ou en calculant un checksum/CRC sur le code et en le comparant à une valeur « propre » précalculée intégrée au binaire.

Comme la vérification lit directement la mémoire, elle ne nécessite aucun import d'API et reste invisible aux hooks de niveau API.

Fonctionnement

La variante la plus simple scanne une plage de code connue à la recherche de l'opcode INT3. Une variante plus robuste calcule le CRC de toute la région, ce qui déjoue aussi l'altération d'un seul octet et les patchs inline.

c
#include <windows.h>

// Scan [start, end) of our own code for stray software breakpoints.
BOOL HasSoftwareBreakpoint(BYTE *start, BYTE *end)
{
    for (BYTE *p = start; p < end; p++)
        if (*p == 0xCC)          // INT3 left by a debugger
            return TRUE;
    return FALSE;
}

// Integrity variant: compare a checksum against the known-good value.
BOOL CodeWasModified(BYTE *start, SIZE_T len, DWORD expected)
{
    DWORD sum = 0;
    for (SIZE_T i = 0; i < len; i++)
        sum = (sum << 1 | sum >> 31) ^ start[i];   // cheap rolling hash
    return sum != expected;
}

En assembleur, la boucle de scan est sans équivoque : un cmp al, 0CCh (ou un scasb contre 0xCC) dans une boucle serrée parcourant la propre plage d'adresses de la fonction.

Détection & contournement

  • Statique — Recherchez dans IDA/Ghidra l'immédiat 0xCC utilisé dans une comparaison (cmp ..., 0CCh), les boucles scasb/repne scasb, et les références à GetModuleHandle/à la base de section servant à dériver la plage de scan. Les variantes d'intégrité de code référencent une constante de checksum codée en dur comparée après une boucle sur l'image ; cherchez cette valeur magique comme point d'ancrage.
  • Dynamique — Évitez complètement les points d'arrêt logiciels : utilisez des points d'arrêt matériels (DR0–DR3) qui ne modifient jamais les octets de code. Dans x64dbg, posez-les via le type de point d'arrêt « Hardware, on execution ». Pour trouver la vérification, posez un point d'arrêt sur les lectures mémoire de votre propre .text (un point d'arrêt matériel en accès mémoire sur la plage de code) et observez quelle routine la parcourt.
  • Patch / contournement — Laissez le débogueur restaurer les octets originaux avant l'exécution du scan, ou patchez la comparaison : NOP le cmp/je, ou forcez la fonction d'intégrité à return 0/xor eax,eax; ret. Pour la variante CRC, recalculez et réécrivez la constante attendue, ou court-circuitez le saut conditionnel.
  • Outils — ScyllaHide et les workflows utilisant uniquement des points d'arrêt matériels ; x64dbg (utilisez les points d'arrêt matériels), pe-sieve pour confirmer l'intégrité du code en mémoire, et TitanHide pour la furtivité côté noyau.
Votes

Commentaires(0)