Déclencher une exception lors d'accès lecture/écriture

Messages postés
14
Date d'inscription
samedi 24 mars 2007
Statut
Membre
Dernière intervention
12 février 2016
-
Bonjour,

En C++ (win32), J'essaie de lever une exception ou d'exécuter une fonction d'un processus A lorsqu'un processus B accède en lecture ou en écriture à une zone particulière (de taille 4 octets) d'une section PE spécifique du processus A, et que çà marche bien sur X86 et AMD64.

Evidemment, j'ai tenté plusieurs approches:
- breakpoint hardware (registres DR0 à DR3 et DR7): uniquement sur architecture x86, et, puisque Windows (comme beaucoup d'OS actuels) n'utilise pas le task switch matériel, et aussi parce que Windows n'implémente ce type de point d'arrêt que pour le processus appelant, B lit et écrit bien dans la zone spécifique du processus A mais sans que A n'exécute pas le code du gestionnaire d'exception.

Pseudo code partiel du processus A:
ZoneAMonitorer = 1
GetThreadContext(hThreadA, CONTEXT)
CONTEXT.Dr0 = adresseZoneAMonitorer
CONTEXT.Dr7 = 0x000F0001
SetThreadContext(hThreadA, CONTEXT)

Pseudo code partiel du processus B:
int buffer = 0
int transferes = 0
ReadProcessMemory(hThreadA, adresseZoneAMonitorer, &buffer, sizeof(int), &transferes)
buffer += 1 // la valeur n'a pas d'importance
WriteProcessMemory(hThreadA, adresseZoneAMonitorer, &buffer, sizeof(int), &transferes)

Effets:
Dans ce cas, une exception (0x80000004: single step) est levée si A lit ou écrit dans la zone, mais rien si B lit ou écrit cette zone.
En mettant CONTEXT.Dr7 à 0x000F0002 (portée globale du point d'arrêt, mais pas sous Windows), pas d'exception, alors que B lit et écrit bien dans la zone.

- avec VirtualProtect, en utilisant bien la taille de page (obtenue avec GetSystemInfo), avec le paramètre 3 (DWORD flNewProtect) à PAGE_NOACCESS:

Effets:
Dans ce cas, une exception (0xC0000005: violation d'accès) est levée si A lit ou écrit dans la zone, mais rien si B tente de lire ou d'écrire cette zone. B ne lit et n'écrit pas (normal).

- avec VirtualProtect, en utilisant bien la taille de page (obtenue avec GetSystemInfo), avec le paramètre 3 (DWORD flNewProtect) à PAGE_READONLY | PAGE_GUARD:

Effets:
Dans ce cas, une exception (0x80000001: STATUS_GUARD_PAGE_VIOLATION) est levée si A lit ou écrit dans la zone, mais rien si B tente de lire ou d'écrire cette zone. B n'écrit pas (normal aussi). Je ne me souviens plus de si B parvient à lire. Mais c'est pas gênant.

- polling: dans un nouveau thread, dans une boucle infinie, la zone est lue, comparée à son ancienne valeur, une fonction est appelée si différence et on recommence, sinon on recommence.

Effets:
le fonctionnement est correct. Mais c'est du polling, on peut perdre un ou plusieurs changements de la valeur contenue dans la zone en cours de route, et le CPU passe aux alentours de 45% d'utilisation... Et si un Sleep(16) est placé avant chaque lecture, c'est mieux du point de vue de l'utilisation du CPU, mais il y a encore plus de risques de perdre des changements de valeur.


Complément d'infos: j'utilise VS2012 sous Windows 7, je cherche à faire çà sous Vista, 7, 8, 8.1, 10, en userland. A et B sont lancés soit l'un par le débuggeur et l'autre via l'explorateur, ou inversement. Donc, pas de lien de "parenté" proche. Les 2 processus ont bien le privilège SeDebugPrivilege lorsque nécessaire.

Là, je suis à court d'idées.
Je ne vois pas comment faire pour qu'un accès par le processus B à la zone monitorée par le processus A déclenche une exception dans le processus A.

Si quelqu'un avait une idée, çà m'aiderais bien.

Merci !
Afficher la suite