Map and projects (the most frequently updated page of this blog)

2010/01/20

The hen never laid and the corn never growed

anti-* with the GS register
On thread switch, the GS register value is not restored (32 bits only).
It's a simple statement that leads to anti-* (debugger/tracing/emulator) that defy common sense. (one of my favorite anti-*, since it doesn't call any API and requires to think out of the box).

When stepping, threads are switched, so your debugger might lose the right value.
Try it yourself:
  1. open debugger
  2. set GS to a non-zero value
  3. step, even once
  4. GS might be zero already!

so it's makes an easy anti-stepping:

  1. set GS to a non-zero value
  2. debugger detected if GS is 0

On the other hand, after some time of normal execution, thread switch will happen, and GS will be reset.
  1. set GS to a non-zero value
  2. loop as long as GS is not zero

If an emulator is not resetting GS after some time, execution will be stuck in an infinite loop.

Last, thread switching requires will take some time before it occurs. So, such a 'loop if not zero' used with a timing method can be used to detect a debugging session (with an anti-timer) or an emulator.
  1. check current time
  2. wait for thread switch with the GS loop trick
  3. check current time again
  4. compare both values, shouldn't be too low

There is no 'mov gs, immediate_value' opcode, the only opcodes to modify GS are:
  • mov gs, reg16
  • pop gs

Any code using GS should be taken as suspicious, as it's only used in recent binaries for anti-* purposes, in my opinion.

Source and binaries

[...]

anti-* avec le registre GS
Au moment du changement de thread, la valeur du registre GS n'est pas restaurée (en 32 bits uniquement).
Cette simple phrase permet des anti-* (débogueur/analyse/émulateur) qui défient le bon sens. (c'est un de mes anti-* favoris, car il ne nécessite aucun appel à API et demande de sortir du cadre).

Quand on analyse pas à pas, les threads changent, donc votre débogueur peut perdre la bonne valeur.
Essayez vous-même :
  1. ouvrez le débogueur
  2. donnez à GS une valeur non nulle
  3. faites un juste un pas
  4. il est possible que GS soit déjà nul !

Donc ça fait un anti pas à pas facile:
  1. mettre à GS une valeur non nulle
  2. vérifier que GS est non nul. Sinon, débogueur détecté !

D'autre part, après un certain temps d'exécution normale, le changement de thread va se produire, et GS deviendra nul.
Ce qui nous donne l'anti-émulation suivant:
  1. mettre à GS une valeur non nulle
  2. attendre que GS ne soit pas nul

Si l'émulateur ne remet pas à zero GS au bout d'un certain temps, l'exécution sera bloquée dans une boucle infinie.

Enfin, le changement de thread met un certain temps à se produire. Donc une telle 'attente que GS ne soit pas nul' utilisé avec une méthode de chronométrage peut être utilisée pour trouver un débogueur (avec un anti-timer) ou un émulateur.
  1. regarder l'heure
  2. attendre le changement de thread via la boucle d'attente de GS
  3. regarder l'heure à nouveau
  4. comparer les deux valeurs, elles ne devraient pas être trop proche

Il n'y a pas d'opcode 'mov gs, immediate_value', les seuls opcodes pour modifier GS sont :
  • mov gs, reg16
  • pop gs

Le moindre code utilisant GS devrait vous alerter, car dans des binaires récents, il n'est utilisé que pour les anti-*, à mon avis.

Sources et binaires

No comments:

Post a Comment