Question:
Comment puis-je analyser un exécutable sans autorisation de lecture?
samuirai
2013-03-21 02:22:29 UTC
view on stackexchange narkive permalink

J'ai un binaire sur un Linux (noyau 2.6) que je peux exécuter, mais que je ne peux pas lire (chmod 0711). Aucune analyse statique n'est donc possible.

  user1: $ ls -l bin -rs - x --- user2 user1 binuser1: $ file binsetuid exécutable, fichier normal, pas d'autorisation de lecture  

Je recherche différentes techniques dynamiques pour rassembler le plus d'informations possible.

Par exemple, strace fonctionne avec cet exécutable.


MISE À JOUR: j'ai pu résoudre le problème. Voir la réponse.

Merci à tous <3, cette nouvelle communauté de ré-ingénierie est géniale!

Vous recherchez uniquement une technique d'analyse dynamique ou vous recherchez une solution en général?
Je suppose que seules les techniques d'analyse dynamique fonctionnent ici. Mais je suis ouvert à tout ce qui peut aider à comprendre ce que fait l'exécutable. Je n'ai pas d'accès "physique" au système de fichiers et ainsi de suite.
Si `strace` fonctionne, essayez de vous connecter avec GDB et de vider la mémoire (voir [ici] (http://serverfault.com/a/174027))
@IgorSkochinsky, Je viens de l'essayer sur ma machine, pas de chance. GDB refuse de joindre avec: `Impossible de joindre au processus. ... réessayez en tant qu'utilisateur root. Cela dépend de `ptrace` (qui donne la même erreur) donc` ltrace` ne fonctionne pas non plus.
Comment fonctionne `strace` alors, je me demande? Ou est-ce aussi setuid?
@IgorSkochinsky Si vous exécutez `strace. / Bin`, il exécute le programme sans privilèges supplémentaires. Si vous démarrez le programme normalement, il s'exécute avec des privilèges élevés et vous ne pouvez pas le suivre sans avoir vous-même des privilèges élevés.
Cinq réponses:
#1
+27
Gilles 'SO- stop being evil'
2013-03-21 05:28:53 UTC
view on stackexchange narkive permalink

Au départ, je pensais que vous ne seriez pas capable de vider le programme, mais il s'avère que vous pouvez - voir la deuxième section de cette réponse.

Lancer le programme

La plupart des méthodes habituelles ne fonctionneront pas car l'exécutable est setuid. Si vous démarrez le programme normalement, il s'exécute avec des privilèges élevés (euid ≠ ruid), et la plupart des fonctions de débogage sont réservées à root. Par exemple, tout ce qui repose sur l'attachement au programme avec ptrace est réservé à root. Cela inclut à peu près tout ce que vous pouvez faire dans un débogueur. Linux vous permet de vider la mémoire d'un processus en cours d'exécution (avec ptrace ou via / proc / $ pid / maps et / proc / $ pid / mem ), mais cela aussi est désactivé pour un exécutable setuid.

Vous pouvez exécuter strace ./bin , et voir quels appels système le programme fait . Cependant, cela exécute le programme sans aucun privilège supplémentaire. Il peut bien s'arrêter tôt et se plaindre de ne pas pouvoir lire un fichier ou de ne pas fonctionner avec le bon utilisateur.

Vous pouvez voir des statistiques comme l'utilisation du processeur, l'utilisation des E / S, l'utilisation du réseau, la mémoire utilisation, etc. dans / proc / $ pid : les fichiers comme status , sched et net / netstat sont du monde -readable (que le programme soit réellement lancé avec des privilèges supplémentaires ou non, les restrictions setuid s'appliquent). La seule chose intéressante que je vois, ce sont les connexions réseau du programme. Les éléments vraiment juteux, comme le contenu de la mémoire ( mem ) et même les fichiers ouverts ( fd ) sont désactivés de toute façon. Le préchargement d'une bibliothèque avec LD_PRELOAD ou l'exécution du programme avec un LD_LIBRARY_PATH différent est également désactivé dans les deux cas. Vous n'obtiendrez pas non plus de vidage de mémoire.

Alors, qu'est-ce qui fonctionne? Vous pouvez voir les connexions réseau ouvertes, peut-être que l'une d'entre elles vous donnera un indice ou sera usurpable. Vous pouvez essayer de déterminer à quels fichiers le programme accède en les modifiant lorsque vous le pouvez, ou en exécutant le programme à partir d'un autre répertoire (essayez de créer un lien symbolique).

Si vous avez accès à une prison chroot sur la machine, essayez d'exécuter le programme à partir de là. Si vous pouvez exécuter une machine virtuelle qui implémente des dossiers partagés (par exemple VMware ou VirtualBox), voyez si vous pouvez accéder au programme à partir de là. Il s'agit de subvertir la sécurité du système: les permissions sont conçues pour vous gêner dans votre tâche.

Une technique avancée consiste à observer le programme sous une forte charge et à essayer de déduire ce qu'il fait à partir du moment ça prend. Polluer les caches de disque et voir quels fichiers deviennent rapidement accessibles. Voyez comment l'utilisation du swap varie en fonction de ce que fait le programme (vous avez ainsi une idée du nombre de pages différentes dans son jeu de travail, pas seulement de la mémoire totale qu'il utilise). De nombreux essais et erreurs seront nécessaires. Lorsque vous connaissez le code et que vous essayez d'obtenir les données, il s'agit d'une attaque de canal secondaire bien connue. Lorsque vous ne connaissez pas le code, je pense qu'il sera très difficile d'obtenir des informations utiles de cette manière.

Vider le contenu de la mémoire

Au départ, je pensais que vous ne pouviez pas vider le mémoire du programme à cause du bit setuid (ce qui ne poserait généralement pas de problème car vous ne feriez que copier l'exécutable, mais ici ce n'est pas possible car l'exécutable n'est pas lisible). Cela s'avère être faux. Si vous vous connectez au programme avec ptrace avant d'appeler execve (comme le fait d'exécuter strace ./bin ), vous avez accès à ptrace dans toute sa splendeur, y compris PTRACE_PEEKDATA et PTRACE_PEEKEXEC . Cela n'exécute pas le programme setuid, il peut donc se comporter différemment, mais le code et les données statiques chargés en mémoire sont les mêmes dans les deux cas.

Félicitations à samuirai pour avoir signalé cela

Voici un aperçu de la façon dont vous pouvez vider la mémoire du programme:

  • Fork, et appeler ptrace (PTRACE_TRACEME, ...) dans l'enfant puis exécutez le programme ( execl ("./ bin", "./bin", NULL) ).
  • Dans le parent, appelez waitpid pour attendre que l'enfant revienne de execve.
  • Déterminez l'adresse à laquelle le code est chargé . La valeur du registre IP (obtenue via PTRACE_GETREGS ) doit donner un indice, et vous pouvez rechercher les en-têtes de format de fichier.
  • Lire mot par mot la mémoire de l'enfant ( PTRACE_PEEKTEXT , PTRACE_PEEKDATA).
  • Reconstruisez le format de fichier (par exemple, créez un binaire ELF à partir de sections de texte et de données) si nécessaire. Videz les données dans un fichier.
  • Tuez l'enfant - il ne pourra même pas exécuter quoi que ce soit.

Dougall a indiqué une preuve fonctionnelle- outil of-concept pour les exécutables ELF: xocopy.

En fait, je pense que je peux utiliser `ptrace` pas en tant que root. gdb fonctionne très bien avec d'autres exécutables. Le problème est que l'exécutable n'est pas lisible, et par conséquent gdb ne chargera pas le fichier. Je pensais que parce que je pouvais l'exécuter, je pourrais l'exécuter sous mes privilèges et le déboguer de cette façon (et accepter que les privilèges requis pour fonctionner avec setuid ne fonctionneront pas). Mais. gdb ne fonctionnera pas car il n'est pas lisible.
@samuirai: vous ne pouvez pas vous attacher au processus une fois qu'il est en cours d'exécution?
@IgorSkochinsky: Je l'ai essayé, mais je suis trop lent. L'exécutable se termine très rapidement.
@IgorSkochinsky Vous ne pouvez pas vous attacher au processus avec `ptrace` s'il est exécuté avec des privilèges élevés. Si vous exécutez `strace, / bin`, puisque le programme est tracé au moment de l'appel système` execve`, il s'exécute avec les privilèges ordinaires. Vous pouvez ensuite le tracer, mais vous ne pouvez pas vous y rattacher par la suite, et le programme peut se comporter différemment. Gdb refuse du tout d'exécuter le programme s'il ne peut pas lire l'exécutable.
@samuirai Parce que l'exécutable est setuid, vous ne pourrez pas vous y attacher après l'avoir démarré (sauf si vous avez des privilèges root qui rendraient toute la question sans objet).
@Gilles ne puis-je pas forcer à exécuter sous mes privilèges? Comme quand il est exécuté avec `ptrace` (désolé si je comprends mal ici quelque chose de fondamental)
@samuirai Normalement, oui, vous pourriez. Mais les techniques normales reposent sur la capacité de lire le fichier. Je ne peux pas penser à un autre moyen que «strace» pour le moment. Vous voudrez peut-être poser cette question sur [unix.se] et voir si d'autres personnes ont des idées différentes.
Ok, donc ça devrait être possible avec un autre débogueur alors? De plus, il semble que vous puissiez utiliser un fichier pour charger dans le débogueur pour les "symboles" mais utiliser la commande `exec-file` pour spécifier le programme à exécuter.
@Gilles concernant la carte de processus, si vous avez un accès ptrace, vous devriez être capable de lire / proc / pid / maps.
@IgorSkochinsky Habituellement, oui, mais pas ici. `/ proc / $ pid / maps` est interdit car le programme est setuid, même lorsque le processus ne fonctionne pas réellement avec des privilèges élevés. Vous ne pouvez pas non plus vous attacher au processus. Mais le parent reste attaché si le processus a appelé `PTRACE_TRACE_ME` avant d'appeler ʻexecve`.
PoC de travail https://gist.github.com/Samuirai/5217680 et une petite mise à jour dans ma question
@samuirai Bonne idée de déduire les adresses intéressantes des registres. Je vais essayer de mettre à jour mon code vers quelque chose qui fonctionne ce week-end.
#2
+10
samuirai
2013-03-21 07:15:14 UTC
view on stackexchange narkive permalink

J'ai trouvé un petit outil qui utilise ptrace aux instructions pas à pas d'un enfant fourchu qui a exécuté un autre programme:

http://pastebin.com/yHbkc0Je

Cela a parfaitement fonctionné. J'ai eu une décharge de toutes les instructions utilisées. Je sais qu'il n'a pas fonctionné avec les privilèges setuid, mais cela m'aidera probablement de toute façon. Maintenant, je n'ai besoin que de quelque chose pour démonter la trace d'instructions.


PoC ( https://gist.github.com/Samuirai/5217680) basé sur ceci.

  / * Cet outil a été développé grâce à l'impressionnant effort de la communauté sur reverseengineering.stackexchange.com The Thread: http://reverseengineering.stackexchange.com/questions/98/how-can-i-analyse-an -executable-with-no-read-permission Remerciements particuliers à: + igor-skochinsky qui a pointé du doigt cet article de Phrack et a donné l'idée initiale: http://www.phrack.com/issues.html?issue=63&id=12&mode=txt + gilles pour son engagement et son enthousiasme à propos de cette question et de sa tentative de code + et tous les autres qui ont été impliqués. <3 * / # include <stdio.h> #include <sys / ptrace.h> #include <sys / types.h> #include <sys / wait.h> # comprennent <sys / user.h> # comprennent <sys / syscall.h>int main () {pid_t pid; pid = fourchette (); if (pid == 0) {ptrace (PTRACE_TRACEME, 0, NULL, NULL); execl ("./ bin", "./bin", NULL); } else {int status; struct user_regs_struct regs; // pas à pas jusqu'à ce qu'il atteigne le segment de code réel while (1) {wait (&status); if (WIFEXITED (status)) break; // récupère les registres pour le pointeur d'instruction ptrace (PTRACE_GETREGS, pid, NULL, &regs); // strace ./bin // brk (0) = 0x804a000 if (regs.eip>0x804a000) {
printf ("dans la section de code à EIP =% lx \ n", regs.eip); unsigned int i; // Code de vidage pour (i = 0; i<0x1000; i + = 4) {long data = ptrace (PTRACE_PEEKTEXT, pid, regs.eip + i, 0); printf ("% lx", données); }} // étape unique dans le processus enfant ptrace (PTRACE_SINGLESTEP, pid, NULL, NULL); }} return 0;}  

Comme l'a souligné Gilles, vous ne pouvez pas lire / proc / <pid> / maps pour obtenir les adresses de la zone de code, mais J'ai reconnu que strace a cette belle ligne unique brk (0) = 0x804a000 .

Je fais un pas à travers le processus enfant, jusqu'à ce que EIP soit autour de ça valeur; puis, je vide 0x1000 octets.

Pourquoi ne pas simplement le modifier pour vider la mémoire au lieu du traçage? Il y a déjà une lecture avec `PTRACE_PEEKTEXT`, il vous suffit de la modifier pour lire toute la mémoire du processus. Voir un exemple de code [ici] (http://unix.stackexchange.com/a/9068)
Sur SE, nous aimons généralement voir les codes (pas trop longs) uniquement dans la réponse, pas derrière un lien. C'est parce que pastebin ne garantit pas de stocker les codes. Pourriez-vous ajouter le code à votre réponse s'il vous plaît?
C'est le même code de ma mise à jour de question. J'ajouterai la référence
#3
+8
Dougall
2013-03-22 13:36:04 UTC
view on stackexchange narkive permalink

L'utilisation d'outils d'analyse dynamique basés sur ptrace sur les binaires suid les fait fonctionner sans privilèges. Pour cette raison, une copie du fichier exécuté en tant qu'utilisateur est probablement suffisante à des fins d'analyse.

Lorsque j'ai eu à faire cela, j'ai utilisé l ' outil xocopy, qui utilise ptrace pour reconstruire les fichiers ELF lorsque l'en-tête est mappé en mémoire (la plupart des compilateurs le font, probablement pour une utilisation par l'éditeur de liens dynamique). Je n'ai pas testé l'outil avec ASLR, mais vous pourrez peut-être le combiner avec certaines des techniques couvertes dans d'autres réponses. Une fois le fichier vidé, il peut être analysé de manière statique ou exécuté avec n'importe quel outil d'analyse dynamique.

Existe-t-il une version 64 bits de cet outil? Cela ne semble pas fonctionner sur les fichiers elf 64 bits. : /
#4
+5
Igor Skochinsky
2013-03-21 02:52:39 UTC
view on stackexchange narkive permalink

Voici quelques outils qui pourraient ou non fonctionner:

Je serai intéressé de savoir si vous avez réussi avec l'un d'entre eux.

Aucun de ceux-ci ne fonctionnera sur un exécutable setuid.
@Guiles ce n'est pas setuid et il ne l'a jamais dit.
@cb88 pour être honnête, les permissions indiquées affichent le drapeau `s`. Bien que je suppose que cela aurait dû être mentionné explicitement.
#5
+1
cb88
2013-03-21 02:47:00 UTC
view on stackexchange narkive permalink
  1. Gain root lisez le fichier
  2. Copiez le système de fichiers dans un autre système et lisez-le si vous en avez l'autorisation (copiez le fichier fs sur un système sur lequel vous avez un accès root).
  3. examine la mémoire du processus pendant son exécution. ne fonctionnera pas s'il est setuid et que vous n'êtes pas cet utilisateur.
  4. Je suis juste stupide mais vous pouvez l'exécuter encore et encore jusqu'à ce qu'il remplisse le swap, puis le copier à partir de là: P Ou créez un fichier d'échange dans votre dossier de départ avec une priorité supérieure à l'échange système. Et puis faites ce qui précède ... et lorsque le swap système commence à se remplir, copiez votre fichier d'échange pour le sauvegarder. Je suggérerais de le faire dans un script, sinon votre système pourrait se retrouver verrouillé. Vous pouvez surveiller l'utilisation du swap avec free je crois ou à défaut d'analyser l'utilisation de / proc. Bien sûr, tuez toutes les tâches créées après avoir copié votre fichier d'échange.

Il y a de fortes chances que vous n'ayez pas l'autorisation de faire quoi que ce soit: P. Cela dit, vous devez probablement fournir plus de détails sur ce que vous pouvez / ne pouvez pas faire sur ce système.

C'est vrai. Je ne suis qu'un utilisateur normal et je ne peux pas accéder à / proc. Bien que `strace` fonctionne et je pensais qu'il existe d'autres choses que je ne connais pas.


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...