
Un framework de débogage, traçage et manipulation de processus multicœurs piloté par événements.
libptrace est un framework événementiel de débogage, traçage et manipulation de processus/threads. Il est écrit en C et dispose de liaisons pour Python 2.7 et 3.7.
Il est conçu pour être utilisé comme une bibliothèque. L'API a été conçue en tenant compte de la compatibilité multiplateforme. Bien que la version actuelle ne fonctionne que sur les versions 32 et 64 bits (wow64 est pris en charge) de Windows, la conception et les abstractions sont telles que d'autres plateformes et même la prise en charge du débogage à distance peuvent être ajoutées sous la même API.
Il est conscient des multiples cœurs/threads et peut facilement être utilisé pour exécuter plusieurs boucles d'événements simultanément. Le débogage de groupes de processus ou de pipelines, ou le traçage d'un grand nombre de processus peut être mis à l'échelle en augmentant les cœurs d'exécution de cette manière.
J'ai écrit la version initiale de libptrace en 2006 alors que j'étais encore à l'université, et je l'ai ré-licenciée pour une utilisation complète par Immunity Inc. en 2011, mon employeur à l'époque. À cette époque, le framework était destiné à être intégré dans Immunity Debugger, bien que j'aie toujours veillé à garder le framework séparé, afin qu'il puisse être utilisé de manière autonome.
Avec cet objectif en tête, il a connu beaucoup de développement chez Immunity, et je suis reconnaissant d'avoir pu développer activement dessus pendant mes heures de travail et voir le framework devenir plus mature. J'ai repensé la majeure partie pour qu'il soit conscient de plusieurs cœurs, pour fournir des liaisons Python et créer de meilleures abstractions.
Avec la sortie éventuelle de x64dbg, il a été décidé que nous ne travaillerions plus sur Immunity Debugger, et concentrerions plutôt nos efforts sur d'autres choses. Cela a également interrompu le développement de libptrace, et pendant les années suivantes, il a pris la poussière dans le dépôt git interne, jusqu'à ce qu'après l'acquisition d'Immunity Inc. par Cyxtera Technologies, maintenant sous Cyxtera Cybersecurity Inc., il soit décidé de publier le projet sous la licence LGPL version 2.1 afin qu'il puisse, espérons-le, être adopté et développé davantage.
Je tiens à remercier chaleureusement Immunity Inc., ainsi que Cyxtera Technologies et Cyxtera Cybersecurity Inc. d'avoir rendu cette publication possible. Je tiens également à remercier tout particulièrement Dave Aitel d'avoir poussé cette publication à travers les couches de la direction et de m'avoir protégé des parties bureaucratiques du processus. Il aurait été triste de voir mon travail perdu et sans but, et sans leur volonté de publier le développement de libptrace qui a été fait en interne en tant qu'open source, c'est ce qui se serait produit.
Je tiens également à remercier plusieurs collègues qui ont passé du temps à utiliser ou à travailler sur le framework, notamment Massimiliano Oldani, Roderick Asselineau et Christos Kalkanis. Mes remerciements s'étendent également à Lennert Buytenhek pour ses implémentations intrusives d'arbres AVL et de listes chaînées que j'ai fini par utiliser.
Bien que plus de 4 ans se soient écoulés depuis tout travail sur le projet, j'espère que les gens le trouveront utile. Je crois que la conception et le code source sont relativement propres, et à ce stade, ils permettent d'étendre le framework et de le porter sur d'autres plateformes relativement facilement. J'espère qu'un jour cela pourra se transformer en une véritable bibliothèque de débogage multiplateforme sous une API unique et cohérente.
Enfin, je voudrais dédier ce projet à ma fille perdue, Yuzuyu Huizer, avec qui j'espère être réuni un jour. Je t'aime.
-- Ronald Huizer [email protected]
La méthode de construction actuellement prise en charge consiste à compiler le projet en croix en utilisant MinGW et CMake. Le système de construction a été testé sur Ubuntu 19.04.
Un programme d'installation 32 bits peut être construit en utilisant :
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86.cmake .
make
makensis libptrace-setup.nsi
Un programme d'installation 64 bits peut être construit en utilisant :
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x64.cmake .
make
makensis -DUSE64 libptrace-setup.nsi
Après avoir suivi les étapes de construction ci-dessus, le programme d'installation 32 bits se trouvera à libptrace-setup32.exe et le programme d'installation 64 bits à libptrace-setup64.exe.
Le programme d'installation déterminera automatiquement quelles versions de Python sont installées et si elles sont 32 bits ou 64 bits. Les versions trouvées seront proposées par le programme d'installation, et les versions non trouvées seront grisées.
Les téléchargements des versions peuvent être trouvés ici.
Le répertoire doc/ est désespérément obsolète. Il est inclus comme point de départ pour une documentation plus récente. Veuillez ne pas l'utiliser.
Plusieurs scripts d'exemple peuvent être trouvés dans le répertoire python/scripts. Ils seront installés dans Program Files\Immunity Inc\libptrace ou dans le cas de la version 32 bits Program Files (x86)\Immunity Inc\libptrace.
Ces exemples ne montrent en aucun cas le framework de manière exhaustive, mais ils devraient fournir un bon point de départ pour quiconque souhaite utiliser le framework. L'API C n'a pas été bien documentée, mais quelques exemples peuvent être trouvés dans le répertoire unittests/windows. Le répertoire python/ qui contient les liaisons python fournit également une bonne vue d'ensemble. Enfin, le répertoire include/libptrace contient les fichiers d'en-tête qui sont publics, et fournissent ainsi une bonne liste de fonctions API.
Il convient de noter que l'API Python est actuellement un sous-ensemble assez limité de l'API C.
À titre d'exemple, le flux de travail général pour tracer les appels RegOpenKeyExW dans un exécutable serait :
import _ptrace
def bp_handler(bp, thread):
(key, subkey, options, sam, result) = _ptrace.cconv.args_get(thread, "%u%p%u%u%p")
subkey = thread.process.read_utf16(subkey)
print('T{}: RegOpenKeyEx({}, "{}", 0x{:08x}, 0x{:08x}, 0x{:08x})'
.format(thread.id, key, subkey, options, sam, result), end='')
def attached_handler(process):
bp = _ptrace.breakpoint_sw("advapi32!RegOpenKeyExW", bp_handler)
process.breakpoint_set(bp)
handlers = _ptrace.event_handlers()
handlers.attached = attached_handler
_ptrace.execv(r"C:\Windows\Notepad.exe", [], handlers, 0)
_ptrace.main()
Si la valeur de retour de RegOpenKeyExW est également souhaitée, il est plus simple de définir un point d'arrêt sur l'adresse de retour de l'appel de fonction. Cela évite le besoin d'analyse de code pour déterminer les chemins de sortie de fonction de manière statique :
def bp_end_handler(bp, thread):
print("=", _ptrace.cconv.retval_get(thread))
def bp_handler(bp, thread):
(key, subkey, options, sam, result) = _ptrace.cconv.args_get(thread, "%u%p%u%u%p")
subkey = thread.process.read_utf16(subkey)
print('T{}: RegOpenKeyEx({}, "{}", 0x{:08x}, 0x{:08x}, 0x{:08x})'
.format(thread.id, key, subkey, options, sam, result), end='')
retaddr = _ptrace.cconv.retaddr_get(thread)
if thread.process.breakpoint_find(retaddr) is None:
bp_end = _ptrace.breakpoint_sw(retaddr, bp_end_handler)
thread.process.breakpoint_set(bp_end)
La situation des droits d'auteur est clarifiée dans chaque fichier individuel. Ils sont principalement détenus par Cyxtera Cybersecurity Inc., Ronald Huizer, ou les deux simultanément. Quelques fichiers sélectionnés ont des détenteurs de droits d'auteur tiers, comme Lennert Buytenhek.
Distribué sous la version 2.1 de la Licence Publique Générale Limitée GNU (GNU Lesser General Public License). Voir COPYING et COPYING.LESSER pour plus d'informations.