Le déballage d'un packer d'emballage générique ou d'un crypteur implique généralement les étapes suivantes:
1. Tracez le code, en évitant ou en contournant peut-être les vérifications anti-débogage.
Ce n'est pas difficile avec de simples packers mais cela peut être compliqué avec les plus avancés. Ils peuvent utiliser des contrôles de synchronisation ( rdtsc
), un transfert de contrôle basé sur des exceptions, l'utilisation de registres de débogage pour les calculs, etc. L'utilisation d'une VM ou d'un émulateur ici aide généralement à lutter contre la plupart d'entre eux.
2. Trouvez le point d'entrée d'origine (OEP)
Il y a plusieurs façons de le faire. Parfois, le saut vers OEP est évident quand il suit un morceau de code en boucle et qu'il n'y a rien de raisonnable. Ou vous pouvez reconnaître le code chez OEP si vous connaissez les points d'entrée produits par différents compilateurs. Quelques autres astuces:
-
si le packer enregistre les registres d'origine avant de déballer, définissez un point d'arrêt matériel sur leur emplacement dans la pile - de cette façon, vous vous casserez dès qu'ils sont restauré avant de passer à OEP.
-
si, pendant le traçage, vous pouvez identifier la mémoire où le code décompressé est écrit, définissez un point d'arrêt d'exécution de page sur cette plage de mémoire - il se déclenchera après le sauter. IDA vous permet de définir un tel point d'arrêt, et je pense qu'OllyDbg aussi.
-
définir des points d'arrêt sur les API courantes utilisées par le code de démarrage, par exemple GetCommandLine
ou GetVersionEx
. Cela ne vous donnera pas l'OEP exact, mais vous pouvez généralement revenir en arrière dans la pile d'appels et le trouver plus ou moins facilement.
3. Vider le code décompressé
Si vous utilisez IDA, vous n'avez pas besoin de vider le fichier dans un fichier séparé - il suffit de prendre un instantané de la mémoire qui copierait les octets de la mémoire vers la base de données afin que vous puissiez les analyser ultérieurement. Une chose à garder à l'esprit ici est que si le packer a utilisé de la mémoire allouée dynamiquement, vous devez la marquer comme "chargeur" pour qu'elle soit incluse dans l'instantané. Plus ici.
4. Restaurer les importations
Je ne sais pas très bien comment cela se fait dans Olly ou dans un autre débogueur, mais AFAIK vous devez utiliser un outil comme ImpREC sur votre vidage et une copie du processus en mémoire.
C'est un peu plus simple (OMI) dans l'IDA. Il vous suffit de trouver la table d'importation et de renommer les pointeurs en fonction des fonctions sur lesquelles ils pointent actuellement (cela devrait être fait pendant que le débogueur est actif). Vous pouvez utiliser le script renimp.idc
ou la "fonction de reconstruction manuelle" UUNP (voir ici).
Pour trouver la table d'importation, il y a deux astuces: utilisez parfois:
-
suivez certains appels dans le code de démarrage d'OEP pour trouver des API externes et cela devrait vous conduire à la table d'importation. Habituellement, le début et la fin de la table sont évidents.
-
pendant le déballage, définissez un point d'arrêt sur GetProcAddress et voyez où les résultats sont écrits. Cependant, cela ne fonctionnera pas avec les packers qui utilisent le résultat de l'importation manuelle à l'aide du répertoire d'exportation. Mettre un BP en lecture sur la table d'exportation de kernel32 pourrait aider ici.
5. Nettoyer
Ceci est facultatif mais il peut être utile de supprimer les restes du code du packer qui ne feraient que vous distraire. Dans IDA, vous devez également appliquer une signature FLIRT du compilateur si vous reconnaissez le compilateur utilisé.
6. Créer un exécutable décompressé
Je ne fais pas cette étape car j'ai rarement besoin d'exécuter le fichier décompressé, mais en général, vous devez généralement corriger l'en-tête PE afin que les décalages du code de la section dans le fichier correspondent à ceux dans la décharge.
Maintenant, il existe de nombreuses variantes et astuces qui ne sont pas couvertes par les étapes ci-dessus. Par exemple, certains packers ne résolvent pas entièrement les importations au départ, mais placent des sauts dans les stubs qui résolvent l'importation au premier appel, puis le corrigent pour qu'il passe directement à la cible la prochaine fois. Ensuite, il y a l'approche du «code volé» qui rend plus difficile la recherche et la récupération d'OEP. Parfois, le packer exécute une copie de lui-même et le débogue, de sorte que vous ne pouvez pas y attacher votre propre débogueur (cela peut être résolu en utilisant un émulateur ou un débogueur qui n'utilise pas d'API de débogage comme Intel PIN). Néanmoins, les étapes décrites peuvent couvrir une grande partie de ce qui existe.
Je terminerai par la vidéo réalisée par Elias montrant le processus de déballage du Lighty Compressor: https: //www.hex -rays.com/video/bochs_video_2.html