2009-09-17 24 views
1

Je suis à la recherche d'une manière soignée de piéger et de tripoter l'instruction CPUID des processus Linux. Joué avec ptrace() et patcher tous les opcodes cpuid dans toutes les régions mmap'ed exécutables créées par un processus, en les remplaçant par int3. Cela ne fonctionnait pas bien puisque les octets de l'opcode CPUID apparaissaient assez souvent comme des parties d'autres opcodes plus longs. Donc, fondamentalement, je cherche un moyen qui me permet de définir un point d'arrêt non pas sur une adresse mémoire spécifique, mais plutôt sur chaque invocation d'un code opération. Quelqu'un a une bonne idée de comment faire cela?Je cherche un moyen de piéger les instructions CPUID

Répondre

1

Pas facile, c'est une bonne façon de le faire, j'en suis conscient.

Une manière méchante pourrait être d'utiliser l'API de script python de GDB pour parcourir automatiquement le programme, en examinant chaque instruction avant de l'exécuter. Une autre manière désagréable pourrait être d'attraper la source pour quelque chose comme Bochs, un émulateur x86 open-source, et de le modifier afin qu'il fasse ce que vous voulez quand les instructions qui vous intéressent sont exécutées.

2

En général, la seule façon de le faire sur le code x86 arbitraire et attraper tous les coins-cas est soit:

  • une seule étape et d'examiner chaque instruction avant qu'il ne soit exécuté (PTRACE_SINGLESTEP, voir ci-dessous); ou
  • émule complètement l'ensemble d'instructions x86.

La première façon est probablement meilleure.

(Essayer de décompiler les opcodes autres que juste-à-temps avec le pas à un seul ne fonctionne pas parce qu'il n'attrape pas les cas comme le code auto-modifiable ou sauter au milieu d'une autre instruction).

Pour mettre en œuvre la méthode unique à pas, chaque fois que le processus tracé arrête, vous devez utiliser PTRACE_GETREGS pour obtenir les registres de l'enfant, puis utilisez %eip la valeur du registre de l'enfant comme une adresse pour passer à PTRACE_PEEKTEXT, obtenir le mot suivant réalisé. Examinez ce mot pour voir s'il s'agit d'une instruction CPUID - si c'est le cas, émulez l'instruction en ajustant l'ensemble de registres de l'enfant (y compris en avançant %eip après l'instruction CPUID). Puis appelez PTRACE_SINGLESTEP pour laisser le processus continuer.