Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
TinyInst — Une bibliothèque légère d'instrumentation dynamique | Kitploit
Outils/GitHubGitHub/googleprojectzero/tinyinst
Analyse Dynamique (Sandboxing)Analyse de CodeRétro-ingénierieDébogueursFuzzingAnalyse de Binaires
GitHubgoogleprojectzero/tinyinst

TinyInst

Une bibliothèque légère d'instrumentation dynamique

Voir le dépôt
1.4k14015il y a 8 joursVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

TinyInst```

Copyright 2020 Google LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

root@kitploit:~
https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

root@kitploit:~
## Qu'est-ce que TinyInst ?

TinyInst est une bibliothèque légère d'instrumentation dynamique qui peut être utilisée pour instrumenter uniquement certains modules sélectionnés dans le processus, tout en laissant le reste du processus s'exécuter de manière native. Elle est conçue pour être facile à comprendre, facile à modifier et facile à utiliser pour le hacking. Elle n'est pas conçue pour être compatible avec toutes les cibles (plus de détails ci-dessous).

### Comment se compare-t-elle à [DynamoRIO](https://dynamorio.org/) et [PIN](https://software.intel.com/en-us/articles/pintool) ?

TinyInst n'est pas destinée à remplacer des frameworks d'instrumentation complexes tels que DynamoRIO et PIN, mais plutôt une alternative pour les scénarios où une solution plus légère suffit. TinyInst suppose que la cible est bien comportée (au sens expliqué ci-dessous), ce qui n'est pas le cas pour les frameworks plus complexes. Ainsi, vous ne pourrez probablement pas exécuter TinyInst avec succès contre des logiciels malveillants comme [cela a été fait avec DynamoRIO précédemment](https://www.slideshare.net/MaximShudrak/fuzzing-malware-for-fun-profit-applying-coverageguided-fuzzing-to-find-bugs-in-modern-malware). D'un autre côté, si une cible ne fonctionne pas avec d'autres frameworks en raison du module qui n'a pas besoin d'être instrumenté, et que le module instrumenté est bien comporté, elle pourrait fonctionner avec TinyInst. Parce qu'avec TinyInst, la majeure partie du processus s'exécutera de manière native, le temps de démarrage du processus sera plus court, et elle pourrait surpasser d'autres solutions dans les cas où le processus cible passe beaucoup de temps dans les modules où l'instrumentation n'est pas nécessaire.

### Comment se compare-t-elle à [Mesos](https://github.com/gamozolabs/mesos) et [TrapFuzz](https://github.com/googleprojectzero/p0tools/tree/master/TrapFuzz) ?

TinyInst est une solution complète de réécriture binaire, donc tout comportement arbitraire peut être modifié dans le module cible. Cela lui permet, par exemple, d'extraire la couverture des arêtes au lieu de seulement des blocs de base. De plus, TinyInst ne dépend pas d'autres logiciels, tels qu'IDA Pro, pour identifier les blocs de base.

### Quel système d'exploitation TinyInst prend-elle en charge ?

TinyInst fonctionne sur Windows (x86 et x64), macOS (x64 et ARM64), Linux (x64 et ARM64) et Android (ARM64). Veuillez consulter le README dans le répertoire correspondant pour chaque système d'exploitation pour des notes supplémentaires et des limitations.

### Quelles cibles sont compatibles avec TinyInst ?

TinyInst suppose que tous les modules instrumentés sont bien comportés, dans le sens où

- Il n'y a pas de code auto-modifiant
- L'adresse de retour sur la pile n'est jamais directement accédée par le programme
OU/ET (selon les paramètres)
- Aucune donnée n'est jamais stockée avant le sommet de la pile (sur des adresses inférieures à celles pointées par ESP/RSP). Cette condition peut être assouplie en "aucune donnée avant (ESP/RSP - décalage_arbitraire)" en utilisant le drapeau `-stack_offset`.

TinyInst nécessite également que DEP/NX soit activé pour le processus cible. Si ce n'est pas déjà le cas, vous pouvez utiliser le drapeau `-force_dep` pour le forcer. Cependant, dans le cas (peu probable) où la cible a réellement besoin de DEP désactivé pour fonctionner correctement, le forcer pourrait entraîner un mauvais comportement.

### Quel est le surcoût de performance ?

Selon des premières mesures sur le décodage d'images, sur une cible 64 bits bien comportée avec les paramètres par défaut de TinyInst, le surcoût de performance était d'environ 15 % sans client et d'environ 20 % avec l'exemple de client collectant la couverture. Notez que cela n'inclut pas le temps d'initialisation introduit par l'instrumentation initiale des modules. Voir les conseils de performance ci-dessous pour plus de détails.

## Construction de TinyInst

1. Ouvrez un terminal et configurez votre environnement de construction (par exemple, sur Windows, exécutez vcvars64.bat / vcvars32.bat)

2. Naviguez vers le répertoire contenant les sources

3. Exécutez les commandes suivantes (modifiez le générateur selon la version de l'IDE et la plateforme pour laquelle vous voulez construire) :

#### Windows```
mkdir build
cd build
cmake -G "Visual Studio 16 2019" -A x64 ..
cmake --build . --config Release

macOS```

mkdir build cd build cmake -G Xcode .. cmake --build . --config Release

root@kitploit:~
#### Linux```
mkdir build
cd build
cmake ..
cmake --build . --config Release

Compilation croisée pour Android```

mkdir build cd build cmake -DCMAKE_TOOLCHAIN_FILE=</path/to/android/ndk>build/cmake/android.toolchain.cmake -DANDROID_NDK=</path/to/android/ndk> -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM= .. cmake --build . --config Release

root@kitploit:~
Note #1 : La version 64 bits fonctionnera également sur des cibles 32 bits sous Windows et Linux.

Note #2 : Vous rencontrez des problèmes pour créer une version 32 bits sur Windows 64 bits en raison d'un environnement mal configuré et de bibliothèques manquantes ? Ouvrez le fichier .sln généré dans Visual Studio et compilez à partir de là au lieu d'exécuter cmake --build. Notez également que la version 64 bits fonctionnera sur des cibles 32 bits, il n'est donc peut-être pas nécessaire de créer une version 32 bits.

## Utiliser TinyInst

TinyInst est principalement conçu pour être utilisé comme bibliothèque dans d'autres programmes.

Un client TinyInst est écrit en tant que sous-classe de la classe TinyInst. Le client peut ensuite surcharger les méthodes de l'API dont il a besoin. Les méthodes de l'API sont définies ci-dessous.

Une fois le client créé, il doit être initialisé avec des options de ligne de commande en appelant

`void init(int argc, char **argv);`

Les options de ligne de commande sont définies ci-dessous et un client peut également définir les siennes. Ensuite, pour exécuter et contrôler un programme instrumenté, les fonctions suivantes peuvent être utilisées.

`DebuggerStatus Run(int argc, char **argv, uint32_t timeout);`
`DebuggerStatus Attach(unsigned int pid, uint32_t timeout);`

Ces fonctions exécutent un programme (en utilisant la ligne de commande spécifiée) ou s'attachent à un programme déjà en cours d'exécution. Si aucune méthode cible n'est spécifiée, la cible continuera de s'exécuter jusqu'à ce que le programme se termine, plante, ou que le délai d'attente (en millisecondes) expire. Si une méthode cible est définie, TinyInst reviendra chaque fois que la méthode cible est entrée et chaque fois qu'elle retourne, permettant à l'appelant d'effectuer des tâches supplémentaires.

Lorsque `Run` et `Attach` retournent alors que le processus cible est toujours actif, les fonctions suivantes peuvent être utilisées pour terminer le processus ou continuer l'exécution.

`DebuggerStatus Kill();`

`DebuggerStatus Continue(uint32_t timeout);`

TinyInst est fourni avec un exemple de binaire de couverture, qui peut être invoqué en utilisant

`<options> -- <ligne de commande cible>`

Exemple sous Windows :

`litecov.exe -instrument_module notepad.exe -coverage_file coverage.txt -- notepad.exe`


## API d'instrumentation

### Callbacks d'événements du débogueur

Ces callbacks sont uniquement à titre informatif et le client ne doit pas émettre de code instrumenté pendant leur exécution. Les clients doivent appeler le même gestionnaire défini dans la superclasse avant de gérer eux-mêmes ces événements.

`OnProcessCreated`
Appelé lorsque le processus cible est créé ou attaché.

`OnProcessExit`
Appelé lorsque le processus cible se termine.

`OnProcessEntrypoint`
Appelé lorsque le point d'entrée du processus (binaire principal) est atteint.

`OnTargetMethodReached`
Si la méthode cible est définie, appelé lorsque la méthode cible est atteinte pour la première fois.

`OnModuleLoaded`
Appelé lorsqu'un module est chargé. Appelé pour chaque module, pas seulement pour les modules instrumentés.

`OnModuleUnloaded`
Appelé lorsqu'un module est déchargé. Appelé pour chaque module, pas seulement pour les modules instrumentés.

`OnException`
Appelé lorsqu'une exception est rencontrée. Le client doit soit retourner true (si l'exception a été gérée), soit le résultat de la même méthode sur la classe parente.

### Callbacks d'instrumentation

Pendant ces callbacks, le client peut ajouter du code à la cible en appelant `WriteCode()`. Notez que le client est responsable de la sauvegarde et de la restauration de tout contexte (comme les registres et les flags modifiés dans le code inséré).

`InstrumentBasicBlock`
Peut être utilisé pour insérer du code qui s'exécutera sur un bloc de base particulier.

`InstrumentEdge`
Peut être utilisé pour insérer du code qui s'exécutera sur une arête particulière. Note : Pour des raisons de performance, ce callback n'est émis que sur les arêtes non déterministes (c'est-à-dire les sauts conditionnels) et les sauts/appels indirects (par exemple `call rax`). Pour les arêtes où le bloc de base suivant est toujours connu étant donné le bloc de base précédent (par exemple `jmp offset`, `call offset`), aucun callback ne sera émis.

`InstrumentInstruction`
Peut être utilisé pour modifier l'instruction ou insérer du code avant elle. Selon le code de retour, l'instruction originale sera émise ou non après le callback.

### Autres callbacks

`OnModuleEntered`
Appelé lorsqu'un flux de contrôle est transféré dans un module instrumenté depuis un autre module.

`OnModuleInstrumented`
Appelé lorsqu'un module est instrumenté. Cela se produit généralement lorsque le point d'entrée du processus est atteint (si la méthode cible n'est pas définie) ou lorsque la méthode cible est atteinte (si elle est définie). Le client peut initialiser ici ses données liées à l'instrumentation.

`OnModuleUninstrumented`
Appelé lorsque les données d'instrumentation ne sont plus valides et doivent être effacées. Notez que ce n'est pas la même chose que le déchargement d'un module, car, par défaut, l'instrumentation persiste entre les déchargements/rechargements de modules. Ce callback peut être utilisé pour effacer toutes les données liées à l'instrumentation dans le client.

### API de hook

En plus de l'API à usage général documentée ci-dessus, TinyInst implémente également une API de hook qui est mieux adaptée pour inspecter et modifier le comportement de fonctions individuelles. Cette API est documentée sur une [page séparée](https://github.com/googleprojectzero/TinyInst/blob/master/hook.md).

## Options de ligne de commande

### Liées à l'instrumentation

`-instrument_module [nom du module]` spécifie quel module instrumenter. Plusieurs options `-instrument_module` peuvent être spécifiées pour instrumenter plusieurs modules.

`-instrument_transitive [nom du module]` similaire à `-instrument_module` sauf que seul le code entré depuis d'autres modules instrumentés sera exécuté instrumenté. Principalement utilisé comme optimisation pour des appels comme module1->module2->module1 où il n'est pas important d'instrumenter tout le module2, mais les entrées module2->module1 provoquent des ralentissements.

`-indirect_instrumentation [none|local|global|auto]` spécifie l'instrumentation à utiliser pour les sauts/appels indirects.

`-patch_return_addresses` remplace l'adresse de retour par la valeur d'origine, provoquant l'instrumentation des retours en utilisant la méthode `-indirect_instrumentation` spécifiée.

`-generate_unwind` génère des données de déroulement de pile pour le code instrumenté (pour une gestion plus rapide des exceptions C++). Notez que cela peut ne pas fonctionner correctement sur certaines versions plus anciennes de Windows.

`-persist_instrumentation_data` (par défaut = true) Ne réinstruments pas le module lors des déchargements/rechargements. Fonctionne uniquement si le module est chargé à la même adresse qu'avant.

`-instrument_cross_module_calls` (par défaut = true) Si plusieurs modules `-instrument_module` sont spécifiés et que l'un appelle dans un autre, saute vers le code instrumenté de l'autre module sans provoquer d'exception (ce qui entraînerait des ralentissements).

`-stack_offset` (par défaut = 0) Lors de la sauvegarde du contexte sur la pile, laisse ce nombre d'octets sur le dessus de la pile (avant le pointeur de pile) inchangés.

`-patch_module_entries [off|data|code|all]` Tente de résoudre les ralentissements dus à des entrées excessives dans le module en recherchant les pointeurs vers les points d'entrée précédemment détectés et en les remplaçant par leurs homologues instrumentés. La valeur du drapeau contrôle où rechercher ces pointeurs. Attention : Activer cela pourrait potentiellement introduire des instabilités dans la cible.

### Liées au débogage

`-trace_debug_events` affiche les événements du débogueur (modules chargés, exceptions, etc.)

`-trace_basic_blocks` affiche les blocs de base au fur et à mesure de leur exécution

`-trace_module_entries` affiche toutes les entrées dans le code instrumenté

`-trace_syscalls` [Linux/Android uniquement] Permet au client de recevoir les événements de début/fin d'appel système via les callbacks `OnSyscall()` / `OnSyscallEnd()`.

`-full_address_map` Maintient une carte au niveau instruction des adresses dans le code instrumenté vers les adresses dans le code original. Lourd en mémoire, mais utile pour le débogage.

### Méthode cible et persistance

TinyInst permet à l'utilisateur de définir une méthode cible. Si une méthode cible est définie, aucun code ne sera instrumenté (tout s'exécutera nativement) jusqu'à ce que la méthode cible soit atteinte pour la première fois. De plus, TinyInst interrompra l'exécution à l'entrée et à la sortie de la méthode cible.

`-target_module` module contenant la méthode cible

`-target_method` nom de la méthode cible. Cela fonctionne uniquement si la méthode cible est exportée ou si vous avez des symboles pour le module cible.

`-target_offset` à utiliser lorsque la méthode cible ne peut pas être spécifiée par son nom. Adresse relative de la méthode cible par rapport à la base du module.

`-loop` si ce drapeau est spécifié, TinyInst exécutera la méthode cible en boucle infinie (ou jusqu'à ce que Kill() soit appelée ou que le processus se termine pour une autre raison). Les arguments de la fonction seront sauvegardés et restaurés entre les itérations. Ceci est principalement utilisé pour forcer la persistance lors du fuzzing.

`-nargs` nombre d'arguments de la méthode cible à sauvegarder entre les itérations. À utiliser avec `-loop`.

`-callcon [ms64|stdcall|fastcall|thiscall]` convention d'appel utilisée par la méthode cible. À utiliser avec `-loop`.

### Autres

`-target_env key=value` [actuellement macOS et Linux/Android uniquement] spécifie une variable d'environnement supplémentaire à passer au processus cible. Plusieurs options `-target_env` peuvent être spécifiées pour passer plusieurs variables d'environnement.

`-force_dep` [Windows uniquement] Force l'activation de la DEP pour le processus cible.

## Module de couverture

TinyInst est fourni avec un module de couverture (exemple), `LiteCov`. Le module de couverture peut collecter la couverture de blocs de base ou d'arêtes (contrôlé par le drapeau `-covtype`). En plus de cela, le module peut extraire la couverture "compare" (comptant le nombre d'octets correspondant dans les instructions cmp/sub) en spécifiant le drapeau `-cmp_coverage`.

Une fonctionnalité spéciale du module de couverture est que le tampon de couverture dans le processus cible est initialement alloué en lecture seule, provoquant une exception la première fois qu'une nouvelle couverture est rencontrée. Combiné avec une option pour ignorer un certain sous-ensemble de couverture, cela permet de vérifier rapidement si l'exécution de la cible avec une entrée donnée a abouti à une nouvelle couverture ou non.

## Comment TinyInst fonctionne-t-il ?

TinyInst est construit sur un débogueur personnalisé. Le débogueur surveille le processus cible pour des événements tels que le chargement de modules, l'atteinte de points d'arrêt, le déclenchement d'exceptions, etc. Le débogueur implémente également des points d'arrêt et la persistance si la méthode cible est spécifiée.

Lorsqu'un module à instrumenter est chargé, il est d'abord « instrumenté » de la manière suivante :

- Toutes les régions exécutables du module sont marquées comme non exécutables, tout en conservant les autres permissions (lecture/écriture) telles qu'elles étaient à l'origine. Cela provoque une exception à chaque fois que le flux de contrôle atteint un module instrumenté, qui est interceptée et gérée par le débogueur.

- Une région de mémoire exécutable est allouée à moins de 2 Go de la plage d'adresses du module d'origine. C'est là que sera placé le code instrumenté/réécrit du module. 2 Go est important car cela permet à toutes les instructions utilisant l'adressage sous la forme [rip+offset] d'être remplacées par [rip+fixed_offset].

Chaque fois qu'un module instrumenté est entré (que ce soit pour la première fois ou à tout autre moment), le bloc de base qui a été atteint est instrumenté, ainsi que tous les blocs de base qui peuvent être découverts de manière fiable en suivant de manière récursive les branches conditionnelles ainsi que les appels et sauts directs (par exemple jmp offset, call offset).

Cela suffit pour exécuter le code instrumenté car :

- tous les sauts/appels directs atterriront dans le code instrumenté à l'emplacement correct

- tous les sauts/appels indirects (par exemple call rax) atterriront à leur emplacement de code d'origine, ce qui provoque une exception, que le débogueur résout en remplaçant le pointeur d'instruction par l'emplacement correspondant dans le code instrumenté.

Cependant, bien que cela fonctionne, notez que cela provoquera une exception sur chaque appel/saut indirect dont la cible se trouve dans un module instrumenté. Étant donné que la gestion des exceptions est lente, l'instrumentation de cibles avec beaucoup d'indirection (par exemple les méthodes virtuelles en C++, les pointeurs de fonction) sera lente sans instrumentation supplémentaire.

### Instrumentation des appels et sauts indirects

TinyInst peut instrumenter les appels et sauts indirects pour éviter les exceptions sur les cibles indirectes (déjà vues). Un appel/saut instrumenté, au lieu de sauter vers la cible d'origine, saute vers la tête de la liste chaînée de stubs. Chaque stub contient une paire (cible_originale, cible_traduite). Il teste si la cible du saut/appel correspond à la cible_originale, et si c'est le cas, le flux de contrôle est dirigé vers cible_traduite. Sinon, il saute vers le stub suivant. Si la fin de la liste est atteinte, cela signifie que la cible du saut/appel n'a pas été vue auparavant. Cela provoquera un point d'arrêt intercepté par le débogueur, qui sera résolu en créant un autre stub et en l'insérant dans la liste.

Ce mécanisme peut être implémenté de 2 manières :
- liste par site d'appel (locale)
- table de hachage globale utilisée par tous les sauts/appels indirects

La table de hachage globale offre de meilleures performances. La liste locale (par site d'appel) permet d'obtenir des arêtes correctes (avec l'adresse source correcte) sur les appels/sauts indirects.

Notez que sur les systèmes Windows modernes, en raison du CFG, tous les appels/sauts indirects proviennent du même emplacement. Par conséquent, avec des binaires compilés avec CFG, il est impossible (sans une sorte de traitement spécial) d'obtenir des arêtes précises de toute façon. Ceci, combiné à l'avantage de performance, est la raison pour laquelle la table de hachage globale est la méthode par défaut pour gérer les appels/sauts indirects dans TinyInst.

### Correction des adresses de retour

Par défaut, lorsqu'un appel se produit dans du code instrumenté, l'adresse de retour écrite sera celle de l'instruction suivante dans le *code instrumenté*. Cela fonctionne correctement dans la plupart des cas, mais cela posera problème si le processus cible accède aux adresses de retour à des fins autres que le retour. Un exemple notable est le déroulement de la pile lors de la gestion des exceptions sur les systèmes d'exploitation 64 bits. Par conséquent, les cibles qui doivent intercepter des exceptions ne fonctionneront pas correctement avec TinyInst par défaut.

Cela peut être résolu dans la plupart des cas en ajoutant le drapeau `-generate_unwind`, qui oblige TinyInst à générer et enregistrer des métadonnées de déroulement de pile / de gestion des exceptions pour le processus cible. Notez que `-generate_unwind` pourrait ne pas fonctionner correctement sur certaines versions plus anciennes de Windows car il nécessite UNWIND_INFO version 2.

TinyInst a également une option (exposée via le drapeau `-patch_return_addresses`) pour réécrire les adresses de retour en leurs valeurs correspondantes dans le code non instrumenté à chaque fois qu'un appel se produit. Notez cependant que cette option introduit une surcharge assez importante, car elle provoque un changement de contexte à chaque retour (arête arrière) d'un module non instrumenté vers un module instrumenté.

## Conseils de performance

La plus grande surcharge dans TinyInst provient d'une exception déclenchée à chaque fois qu'un module instrumenté est entré depuis un module non instrumenté. Vous pouvez voir ces exceptions être déclenchées en utilisant le drapeau `-trace_module_entries`. L'instrumentation des appels/sauts indirects doit être utilisée chaque fois que possible, et l'instrumentation des retours ne doit pas être utilisée si possible. TinyInst fonctionne mieux sur des modules (ou des groupes de modules) qui sont raisonnablement autonomes. Par exemple, si vous avez deux modules, A et B, où A appelle B souvent mais seul B est instrumenté, cela entraînera un ralentissement important. De meilleures performances pourraient être obtenues en instrumentant à la fois A et B.

## Conseils de débogage

Utilisez `-trace_basic_blocks` pour voir les blocs de base au fur et à mesure de leur exécution. Vous verrez à la fois les adresses dans le code instrumenté et les adresses correspondantes dans le code non instrumenté.

Utilisez le callback OnException() pour examiner l'état du programme lorsque le crash se produit.

## Avertissement

Ce n'est pas un produit officiel de Google.
Télécharger l’outil