Forum Programmation.c retour de system("echo $?"); inattendu

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
21
oct.
2014

Bonjour à tous,

Je tente d'écrire un (N ième :-)) programme de recherche de mot de passe pour fichier .rar par force brute.

Le principe est de tester un mot de passe et d'analyser le retour .
Ainsi,si, dans une console , je rentre :

Bash shell scripts
moi@MonPc:~$ unrar e -y -p_mot.de.passe_ monFichier.rar

la fonction unrar se déroule normalement en confirmant selon le cas, que le mot de passe est correct ou non.
Ensuite, la commande :

Bash shell scripts
moi@MonPc:~$echo $?

me retourne 0 si le mot de passe est bon ou 3 si le mot de passe est incorrect.

Or, J'ai inclus ces deux commandes dans un programme C via la fonction system() mais l'effet n'est pas celui escompté .
En effet, quelque soit le mot de passe - bon ou mauvais-, la fonction

system("echo $?");

me retourne systématiquement et uniquement la valeur 0. Comme si cette fonction me retournait, non pas le code erreur de la fonction précédente mais le code de "bon déroulement" de celle-ci.

//code complet
#include <stdio.h>
#include <stdlib.h>

int main()
{
int CODE_RETOUR;

    system("unrar e -y -p13 /home/roth/Bureau/test.rar "); 
               // e = test, y= oui a toutes les questions , -p13 = mot de passe :"13" 
    CODE_RETOUR = (system("echo $?"));
    printf("code de retour = %i \n", CODE_RETOUR);
    return 0;
}

Quelqu'un aurait-il une explication ou une piste, s.v.p. ?

Roth

  • # Je ne suis pas un programmeur C...

    Posté par  (site web personnel) . Évalué à 10.

    … mais "echo $?" va te retourner la code de retour de la dernière commande exécutée pendant la session de ton shell.
    Je suppose que l'appel system() va recréer un nouveau shell (donc nouveau fork, nouveau processus… c'est en général une mauvaise pratique) chaque fois que tu l'appelles, donc $? ne sera pas ce que tu attends.
    Peut-être peux-tu faire une seule commande:

    system("unrar e -y -p13 /home/roth/Bureau/test.rar && echo $?");

    ou encore mieux si je comprends bien la doc, system() retourne le code de retour directement, donc:

    CODE_RETOUR = system("unrar e -y -p13 /home/roth/Bureau/test.rar ");
    • [^] # Re: Je ne suis pas un programmeur C...

      Posté par  (site web personnel) . Évalué à 5. Dernière modification le 21 octobre 2014 à 10:38.

      Je suis d'accord avec la seconde proposition : le code retour tu l'as déjà : c'est le retour de la fonction system…

      Mais il n'existe pas une bibliothèque en C pour le format RAR, plutôt que d'appeler la commande unrar !?

      • [^] # Re: Je ne suis pas un programmeur C...

        Posté par  . Évalué à 2.

        Mais il n'existe pas une bibliothèque en C pour le format RAR, plutôt que d'appeler la commande unrar !?

        Il est sûrement possible de modifier les sources d'unrar pour ajouter une boucle sur les mots de passe à tester

        • [^] # Re: Je ne suis pas un programmeur C...

          Posté par  . Évalué à 2.

          Pas sûr .

          D'après quelques posts lus à ce sujet, il semblerait qu'il y ait 2 librairies unrar : la première, en libre, semblerait être peu efficace au final : un taux d'échecs plutôt élevé ; Quant à la seconde, jugée plus efficace, elle serait propriétaire.
          Tout cela au conditionnel puisqu'il s'agit surtout posts et que je te réponds avant d'avoir vérifié.
          Je vais étudier ça de plus près.

          Merci pour ton conseil

          Roth

      • [^] # Re: Je ne suis pas un programmeur C...

        Posté par  . Évalué à 3.

        Effectivement, je n'ai pas pensé une seconde que system() ouvrait … et fermait la session .
        Heureusement que vous êtes là ! Merci .

        Ensuite, il est clair que l'utilisation des bibliothèques rar est maintenant le passage obligatoire .

        Merci

        Roth

        • [^] # Re: Je ne suis pas un programmeur C...

          Posté par  . Évalué à 4.

          Même si system gardait un shell ouvert, code_retour = system("echo $?"); n'aurait pas fonctionné non plus. echo $? va afficher la variable ? et retourner 0. Elle écrit une représentation en base 10 du code de retour sur la sortie standard, pour la récupérer il faut jouer des redirections avec pipe et dup.

          en gros, system(foo) ça fait if(0 == fork()) exec(foo)

          int p[2];
          int code_retour;
          pipe(p);
          if(0 == fork()) { 
            dup2(1,pipe[1]); // pas sûr de l'ordre des paramètres, il faut faire en sorte que le processus fils écrive dans le pipe
            execjesaisplusquoi("/bin/sh", "sh", "-c",  "unrar blablalba ; echo $?");
          
          } else {
            char ret[4]
            read(pipe[0],4,ret) // lire le code retours
            code_retour = atoi(ret);
          }

          Please do not feed the trolls

    • [^] # Re: Je ne suis pas un programmeur C...

      Posté par  . Évalué à 2.

      Ta suggestion :

      CODE_RETOUR = system("unrar e -y -p13 /home/roth/Bureau/test.rar ");

      semble marcher parfaitement et ton raisonnement est très logique .
      Je n'avais pas pris la peine - en fait, ça ne m'est tout simplement pas venu à l'esprit :-s- de lire la doc de system() … Mea culpa !

      Un tout grand merci pour ton aide précieuse Lom !

      Roth

  • # j'espère que tu as du temps ;)

    Posté par  . Évalué à 7.

    car system("unrar …") crée un shell, puis un exec il me semble, et cela à chaque tentative; à ta place je tenterai l'utilisation de libunrar ou une équivalente évitant des fork/exec à répétition

    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # exit() ?

    Posté par  (site web personnel) . Évalué à 1.

    A lire

    Système - Réseau - Sécurité Open Source - Ouvert à de nouvelles opportunités

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.