IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

[x86] Récupérer la pile mémoire


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Points : 609
    Points
    609
    Par défaut [x86] Récupérer la pile mémoire
    Bonjour a tous, je souhaiterais recuperer les valeurs de la pile memoire dans un but de debuggage.

    Voici le code que j'ai ecrit (sous GCC):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
                asm(
                ".intel_syntax noprefix\n"
     
                "push edi\n"                // Save data in stack for next code
                "push edx\n"                //
                "push ecx\n"                //
                "push eax\n"                //
                 //Initialisation
                "xor ecx, ecx\n"            //ecx = 0
                "mov edi, _st_head\n"       //edi = &stacktrace[0]
     
                "unstack:\n"                //while(true) {
     
                    "mov eax, esp\n"        //  if(esp+ecx == ebp) {
                    "add eax, ecx\n"        //
                    "cmp eax, ebp\n"        //
                    "je end_unstack\n"      //      break;
                                            //  } else {
                    "mov edx, [eax]\n"      //
                    "mov [edi], edx\n"      //      stack_trace[n] = *(esp+ecx);
                    "add edi, 4\n"          //      n ++;
                    "add ecx, 4\n"          //      ecx += 4;
                                            //  }
     
                    "jmp unstack\n"         //}
     
                "end_unstack:\n"
     
                "sub edi, _st_head\n"               // stack_size = 4 * n
                "mov _stack_size, edi\n"            //
                "shr DWORD PTR _stack_size, 2\n"    //stack_size >>= 2
                "pop eax\n"                         //
                "pop ecx\n"                         //
                "pop edx\n"                         // Get back stack data!
                "pop edi\n"                         //
     
                ".att_syntax \n"
                );
    Bon, ça fonctionne, cependant il m'affiche que les dix dernieres entrée dans la pile.
    Apres reflexion cela semble evident: je recupere d'ebp à esp, donc je recup uniquement les valeur du contexte de la fonction et non du programme en entier...
    Y'a-t-il une solution? existe-t-il une valeur en dure définissant le bas de la pile (à utiliser au lieu de ebp...)?

  2. #2
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Points : 1 956
    Points
    1 956
    Par défaut
    Bonjour,

    c'est pour quel système d'exploitation ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Points : 609
    Points
    609
    Par défaut
    C'est de l'assembleur x86, tout d'abord pour MS Windows. Cependant c'est une bibliotheque que je souhaiterais porté sous linux voir sous d'autre architecture lorsque j'aurais le temps.

  4. #4
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Points : 1 956
    Points
    1 956
    Par défaut
    Sous Windows c'est mon rayon pour Linux, faudrait que je demande aux collègues...

    La solution fonctionne pour les noyaux à technologie NT (donc pas pour les 9x) ce qui comprend NT, 2k, 2k3, XP et Vista. (j'ai oublié comment ça se passait sous 9x, faudra que je cherche).

    Pour l'adresse de début (et de fin de pile si ça t'intéresse) tu doit passer par le segment FS qui pointe vers la strcuture interne nommée Thread Environment Block (TEB) et plus exactement vers la structure NT_TIB (NT Thread Information Block), puisque chaque Thread a sa propre pile.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    mov esi, dword ptr fs:[18h] ; esi = pointeur linéaire vers NT_TIB
    mov eax, dword ptr [esi+4] ; eax = base de la pile
    mov ebx, dword ptr [esi+8] ; ebx = haut de la pile

  5. #5
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Points : 609
    Points
    609
    Par défaut
    Yes! Merci pour votre reponse clair et rapide !

    Je pense pas que j'aurais trouvé en plus

  6. #6
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Points : 609
    Points
    609
    Par défaut
    J'ai integré le code et sa marche parfaitement... Ou presque

    A vrai dire j'ai un petit soucis: J'utilise ce code pour recuperer la pile d'appel de mon programme lors d'un plantage.
    Pour les interruptions de type abort, floating point operation ou cancel by user c'est niquel.
    Pour les signaux segfaults la parcontre...

    Peut-etre savez vous si lorsqu'un thread fait une violation mémoire:

    * La zone memoire fs:[0x18] ne se bloque pas? Ou alors est-ce mon code qui est foireux?

    Merci d'avance pour ces eclaircissements

  7. #7
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Points : 1 956
    Points
    1 956
    Par défaut
    Bonjour,

    Peut-etre savez vous si lorsqu'un thread fait une violation mémoire:

    * La zone memoire fs:[0x18] ne se bloque pas? Ou alors est-ce mon code qui est foireux?
    Le pointeur linéaire vers NT_TIB est garanti "fonctionnel" dans tout les cas. En fait la structure est tellement critique qu'elle doit être atteignable par Windows (et même un programme utilisateur) quoi qu'il puisse arriver.

    l'adresse FS[0], par exemple, est en réalité un pointeur vers une structure de type EXCEPTION_REGISTRATION_RECORD qui sert aux SEH (Structured Exception Handling) de Windows.

    Donc quelle que soit l'erreur occasionnée (et un segfault en fait partie) Windows - et le programme lui-même - doivent pouvoir y accéder.

    P.S : Ah oui au fait, j'ai oublier de mentionner un point important pour les limites de la pile, car je viens de le tester à l'instant :

    - la limite basse de la pile n'est pas inclusive.
    - la limite haute est "variable" et mise à jour en temps réel.

    En d'autres termes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    mov esi, dword ptr fs:[18h] ; esi = pointeur linéaire vers NT_TIB
    mov eax, dword ptr [esi+4] ; eax = base de la pile (non inclus, ne doit pas être atteignable par le prog)
    mov ebx, dword ptr [esi+8] ; ebx = haut de la pile
    sub eax, 4 ; eax = valeur base de la pile atteignable par le prog.
    sub ebx, 4 ; ebx = adresse haut dessus la limite haute
    mov dword ptr [ebx], 0 ; tentative d'écriture
    mov ebx, dword ptr [esi+8] ; la limite haute a changée dû à l'écriture précédente !
    N'hésites pas si tu as d'autres questions

  8. #8
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2005
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Philippines

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2005
    Messages : 244
    Points : 609
    Points
    609
    Par défaut
    Effectivement, je cherché au mauvais endroit! Du coup ça marche!

    En fait, le tableau allouée pour sauvegarder la pile été trop petite (128 entrée max), et forcement je debordais a coté

    Je l'ai changé par un tableau dynamique et la plus de soucis!
    Un grand merci pour votre aide, maintenant il ne me reste plus qu'à trier et lier certaines des valeurs de la pile vers le nom des fonctions appelée, ce qui ne sera pas de tout repos


    Voilà le code pour ceux que ça interresse:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    //Sous GCC...    
    #define intel_asm(x...) asm ( ".intel_syntax noprefix\n"  #x  ".att_syntax \n" )
    //Sous VC++
    #define intel_asm(x...) asm { x }
     
            #if ATL_ARCHITECTURE == X86
                        //Drop stack to the global stacktrace var
                        std::cout << "Try to read stack..." << std::endl;
                        intel_asm (
     
                        push edi\n                // Push data in stack for next code
                        push esi\n                //
                        push edx\n                //
                        push ecx\n                //
                        push ebx\n                //
                         //Initialisation
                        xor ecx, ecx\n            //ecx = 0
                        mov edi, _st_head\n       //edi = &stacktrace[0]
     
                        #if ATL_OS == WINNT
                        push esi\n
                            //Thanks to Neitsa =========================================
                            mov esi, fs:[0x18]\n// linear pointer to NT_TIB
                            mov eax, [esi+4]\n  // get stack base in eax
                            sub eax, 4\n        //the base of stack is non inclusive
                            //==========================================================
                        pop esi\n
                        #else
                            mov DWORD PTR _stack_size, 0\n
                            jmp non_implemented_yet\n
                        #endif
                        //==========================================================
     
                        unstack:  \n              //while(true) {
     
                            mov ebx, ebp \n       //  if(ebp+ecx == ebp) {
                            add ebx, ecx \n       //
                            cmp ebx, eax \n       //
                            je end_unstack\n      //      break;
                                                    //  } else {
                            mov edx, [ebx]\n      //
                            mov [edi], edx\n     //      stack_trace[n] = *(ebp+ecx);
                            add edi, 4    \n      //      n ++;
                            add ecx, 4    \n      //      ecx += 4;
                                                    //  }
     
                            jmp unstack   \n      //}
     
                        end_unstack:\n
     
                        sub edi, _st_head\n               // stack_size = 4 * n
                        mov _stack_size, edi\n            //
                        shr DWORD PTR _stack_size, 2\n    //stack_size >>= 2
     
                        non_implemented_yet:\n
                        pop ebx\n                         //
                        pop ecx\n                         //
                        pop edx\n                         // Get back stack data!
                        pop esi\n                         //
                        pop edi\n                         //
                        );
     
                    std::cout <<  std::dec << "* Stack size: " << stack_size << std::endl;
     
                    //Display the stack
                    for(unsigned int i = 0; i < stack_size; i++)
                        std::cout << (void*)stacktrace[i] << std::endl;
            #endif

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment récupérer la consommation mémoire de mon programme
    Par youpileouf dans le forum Threads & Processus
    Réponses: 6
    Dernier message: 11/09/2010, 18h15
  2. Debugger avec affichage de la pile mémoire
    Par z980x dans le forum x86 32-bits / 64-bits
    Réponses: 1
    Dernier message: 30/01/2009, 23h38
  3. Script pour récupérer l'allocation mémoire
    Par nicotine78 dans le forum Linux
    Réponses: 6
    Dernier message: 14/09/2007, 16h15
  4. [D7] Récupérer charge processeur, mémoire libre ?
    Par chipster45 dans le forum Delphi
    Réponses: 4
    Dernier message: 01/04/2007, 22h37
  5. [debug] comment récupérer la pile d'appel lors d'un crash ?
    Par mamelouk dans le forum Autres éditeurs
    Réponses: 13
    Dernier message: 10/11/2006, 17h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo