11
votes

Ingénierie inverse d'un script Perl basé sur un vidage de noyau

Le serveur d'un ami (oui, vraiment. Pas le mien.) Était cassé et nous avons découvert un Perl binaire en exécutant un code de bot. Nous n'avons pas pu trouver le script lui-même (probablement évalué comme reçu sur le réseau), mais nous avons réussi à créer une vidange de base du processus PERL.

Running Strings sur le noyau nous a donné des indications (noms d'hôte, noms d'utilisateur / mots de passe), mais pas le code source du script.

Nous aimerions savoir ce que le script était capable de le faire, nous aimerions donc inverser l'ingénieur du Perl qui fonctionnait à l'intérieur de cet interprète Perl.

Vous recherchez autour de vous, la chose la plus proche d'un Perl de compilateur que j'ai trouvé est le module B :: Deparse qui semble être parfaitement approprié pour convertir le bytecode des pars-arbres en arrière en code lisible.

Maintenant, comment puis-je obtenir B :: Deparse à fonctionner sur un décharge de base? Ou, alternativement, comment puis-je redémarrer le programme du noyau, charger B :: Deparse et l'exécuter?

Les idées sont les bienvenues.


0 commentaires

3 Réponses :


0
votes

Eh bien, Undump fera tourner ce point de rebut dans une exécutable binaire (si vous le pouvez Trouver une version de travail). Vous devriez alors être capable de charger cela dans perl et -mo = déparfe it.


2 commentaires

Euh, je pense qu'il y a un défaut là-bas; Comment chargez-vous un exécutable binaire en Perl?


J'étais sous l'impression que j'avais juste fait Perl A.out Un de ces jours suivant un didacticiel PAR :: Packer, mais je l'ai essayé maintenant et cela n'a pas fonctionné.



2
votes

Je doute qu'il y ait un outil qui le fait hors de la boîte, alors ...

  1. Recherchez le code source à la version de Perl que vous utilisiez. Cela devrait vous aider à comprendre la mise en page de la mémoire de l'interprète PERL. Cela vous aidera également à comprendre s'il y a un moyen de prendre un raccourci ici (par exemple, si le bytecode est précédé d'un en-tête facile à trouver en mémoire ou quelque chose).

  2. chargez le vidage binaire + noyau dans un débogueur, probablement gdb

  3. Utilisez les informations du code source PERL pour vous guider dans la convaincre du débogueur pour cracher le bytecode qui vous intéresse.

    Une fois que vous avez le bytecode, B :: Deparse devrait être capable de vous amener quelque chose de plus lisible.


2 commentaires

Oui, cela semble raisonnable. Il pourrait y avoir une capture, cependant: la documentation PERL fait référence au code d'octet comme analyse d'analyse. Cela suggère que le code d'octet n'est pas un tableau de codes OP indépendants de son adresse en mémoire. Au lieu de cela, cela ressemble à une sorte d'arbre avec des pointeurs et peut-être même des pointeurs vers le code mettant en œuvre des primitives. Je ne sais donc pas si B :: Deparse peut faire face à un parse-arbre généré par une autre instance Perl.


En regardant le code DEPARSE indique un autre problème: Deparse a choisi les objets Perl représentant le programme, et non la mémoire / octet-flux qui stocke ce code.



8
votes

Ysth m'a demandé à IRC de commenter votre question. J'ai fait un tout tas de choses "désassembling" compilé perl et de choses (voir mon CPAN Page [ http://search.cpan.org/~jjore] ).

Perl compile votre source à un arbre de op * structs qui ont parfois des pointeurs C sur sv * qui sont des valeurs de Perl. Votre noyau Dump maintenant a un tas de ces op * et sv * caché.

Le meilleur monde possible serait d'avoir un module Perl comme B :: Deparse Faites le travail d'information-compréhension pour vous. Ce Fonctionne à l'aide d'une interface lumineuse pour la mémoire Perl dans le B :: op et B :: SV CLASSES (documenté dans B , perlguts , et Perlhack ). Ceci est irréaliste pour vous parce qu'un objet b :: * est juste un pointeur dans la mémoire avec des accesseurs pour décoder la structure pour notre utilisation. Considérez: xxx

lequel lorsque l'exécution a montré que l'objet b :: pv (ISA b :: sv ) est vraiment simplement une interface à la représentation de la mémoire de la string compilé ceci est une chaîne . xxx

Cela implique toutefois que tout b :: * à l'aide du code doit réellement fonctionner sur la mémoire en direct. Tye McQueen a pensé qu'il se souvenait d'un débogueur C qui pourrait pleinement relancer un processus de travail étant donné une caisse de base. Mon gdb ne peut pas. gdb peut vous permettre de jeter le contenu de votre op * et SV * Structs. Vous voudriez probablement juste lire les structs déversés à interpréter la structure de votre programme. Vous pourriez, si vous le souhaitez, utilisez, utilisez gdb pour vider les structs, puis créer synthétiquement b :: * objets qui se sont comportés dans l'interface comme s'ils étaient ordinaires et utilisent B :: déparfe à ce sujet. À la racine, notre dépassement et autre dumping de débogage les outils sont principalement axés sur des objets afin que vous puissiez simplement les "tromper" par Création d'une pile de fausses B :: * classes et objets.

Vous pouvez trouver la lecture du B :: Deparse Class's codèref2text méthode instructif. Il accepte une référence de fonction, la jette à un B :: cv Objet, et utilise cela pour entrer dans la méthode de dépendrse_sub : xxx

pour des introductions plus douces à op * et idées associées , voyez la mise à jour perlguts illustré et OPTREE GUTS .


1 commentaires

Josh, merci pour la réponse détaillée. C'est à peu près des jives avec ce que j'attendais. Ressemble à un projet pour de longues nuits d'hiver.