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 :

[OllyDbg] Algorithme d'analyse


Sujet :

x86 32-bits / 64-bits Assembleur

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 4
    Par défaut [OllyDbg] Algorithme d'analyse
    Bonjour,

    Je me lance dans une analyse particulière sous OllyDbg.

    J'utilise un programme client / serveur qui un moment donnée reçois une trame de control via un socket client et renvoie une trame via le même socket a un serveur.

    Je connais l'adresse de la réception (recv) et de l'envoi (send) dans le code ASM.

    J'utilise le plugin OllySocketTrace qui me permet de visualiser les trames en question.

    J'aimerai pouvoir analyser ce que fait le programme entre la réception de la trame et l'émission, pour en ressortir un algorithme, qui me permettrait de générer cette fameuse trame à partir de la trame reçue qui est aléatoire.

    Le stockage de la trame renvoyée par SEND m’est inconnue jusqu’à son envoi (RECV).

    Donc je ne sais pas dans quelle zone mémoire me placer pour analyser la construction de la trame à envoyer.

    Faut t’il se mettre en mode pas à pas, et à chaque pas, faire un DUMP de la mémoire, pour retrouver les octets changé ??

    Y a-t-il une technique logique et non fastidieuse, car j’ai essayé mais beaucoup d’instruction son joué entre le RECV et le SEND.

    Merci à ceux qui pourront m’éclairer sur la façon d’opérer, je suis novice (4 semaines) je me suis lancé dedans après 5 tutos, je suis un développeur DELPHI à la base.

  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
    Par défaut
    Hello,

    Le deuxième argument de recv() est un pointeur vers un buffer. En gros:

    1) Pose un BP sur recv(). Il vaut mieux poser le BP sur la fonction recv() plutôt que sur son appel, ce qui implique de poser le BP dans Ws2_32.dll, à moins que tu sache précisément quel recv() reçoit le bon paquet.

    2) Le deuxième argument est un pointeur vers un buffer, donc à l'appel de recv, tu le verra à [ESP+8].

    3) Click droit sur ESP+8 dans la pile => follow in dump / in stack (suivant où se situe le buffer).

    4) Pose un BP sur ce buffer (dans les premiers octets), hardware ou memory [à essayer avec l'un puis l'autre]. La taille du BP a peu d'importance.

    5) F9 (Run). Le BP devrait être déclenché dès que le code du programme va s'occuper de ce qu'il y a dans le buffer.

    6) A partir de là il ne reste plus qu'a tracer. Ca peut être très long comme très court, mais il n'y a pas de mystères... Si tu veux comprendre ce que fait le code, il faudra mélanger step-in (F7) et step-over (F8) pour suivre ce que fait ce code et en dégager un algo / pseudo - code.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 4
    Par défaut
    Merci pour ces détails, j'ai une base pour travailler maintenant.

    Super sympa, et réponse super rapide, merci encore.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 4
    Par défaut Point de blocage
    Re-bonjour, après n tentatives, je n'arrive toujours pas à me placer dans la zone mémoire où sera construite la trame à envoyer. Voici un log OllySocketTrace :

    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
    cmnet.01C6D58F        0x000015F0    socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )                                       960
    WS2_32.719F4261       0x000015F0    WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0x00000000, 0, WSA_FLAG_OVERLAPPED  960
    cmnet.01C6D7E6        0x000015F0    ioctlsocket( 960, FIONBIO, 0x00110BE8 )                                           0
    cmnet.01C6D5BE        0x000015F0    connect( 960, 0x02515F6C, 16 )                                                    INVALID_SOCKET  Connecting to: 94.23.239.9:6005.
    cmnet.01C6D783        0x00000724    send( 960, 0x02513710, 132, 0x0 )                                                 132
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )                                               81
    cmnet.01C6D783        0x00000724    send( 960, 0x02513D60, 183, 0x0 )                                                 183
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )                                               68
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )                                               815
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )                                               276
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )
    cmnet.01C6D783        0x00000724    send( 960, 0x024D69F0, 32, 0x0 )                                                  32
    cmnet.01C6D783        0x00000724    send( 960, 0x0574D960, 18, 0x0 )                                                  18
    cmnet.01C6D783        0x00000724    send( 960, 0x024DDA04, 13, 0x0 )                                                  13
    cmnet.01C6D8A8        0x0000102C    closesocket( 960 )                                                                0
    Ce qui m'intéresse ici, c'est le deuxième send. J'aimerais à l'avance connaître l'adresse 0x02513D60 où est stockée l'information à envoyer.

    Voici un deuxième log OllySocketTrace issu d'une seconde connexion. Ici, on voit que la nouvelle adresse est 0x024DF1D0. N'y a-t-il pas un moyen où un plugin qui nous permet de visualiser les plages d'adresse mémoire concerné par le socket afin de suivre en mode pas à pas ce qui se passe ?

    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
    cmnet.01C6D58F        0x00000CF0    socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )       956
    WS2_32.719F4261       0x00000CF0    WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0x  956
    cmnet.01C6D7E6        0x00000CF0    ioctlsocket( 956, FIONBIO, 0x00110BE8 )           0
    cmnet.01C6D5BE        0x00000CF0    connect( 956, 0x024E389C, 16 )                    INVALID_SOCKET  Connecting to: 94.23.239.9:6005.
    cmnet.01C6D783        0x00001338    send( 956, 0x024F55B0, 132, 0x0 )                 132
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               81
    cmnet.01C6D783        0x00001338    send( 956, 0x024DF1D0, 183, 0x0 )                 183
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               68
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               815
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               100
    cmnet.01C6D783        0x00001338    send( 956, 0x02502CC0, 32, 0x0 )                  32
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               276
    cmnet.01C6D783        0x00001338    send( 956, 0x02502BD0, 18, 0x0 )                  18
    cmnet.01C6D783        0x00001338    send( 956, 0x057199A0, 66, 0x0 )                  66
    cmnet.01C6D783        0x00001338    send( 956, 0x056DA5C0, 21, 0x0 )                  21
    cmnet.01C6D753        0x00001338    recv( 956, 0x02538330, 32768, 0x0 )               124
    cmnet.01C6D8A8        0x00000D78    closesocket( 956 ) 0
    Merci d'avance à tous ceux qui prendront la peine de répondre à ce post.

  5. #5
    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
    Par défaut
    Bonjour,

    Citation Envoyé par nirou Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    cmnet.01C6D58F        0x000015F0    socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )                                       960
    WS2_32.719F4261       0x000015F0    WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0x00000000, 0, WSA_FLAG_OVERLAPPED  960
    cmnet.01C6D7E6        0x000015F0    ioctlsocket( 960, FIONBIO, 0x00110BE8 )                                           0
    cmnet.01C6D5BE        0x000015F0    connect( 960, 0x02515F6C, 16 )                                                    INVALID_SOCKET  Connecting to: 94.23.239.9:6005.
    cmnet.01C6D783        0x00000724    send( 960, 0x02513710, 132, 0x0 )                                                 132
    cmnet.01C6D753        0x00000724    recv( 960, 0x0252D328, 32768, 0x0 )                                               81
    cmnet.01C6D783        0x00000724    send( 960, 0x02513D60, 183, 0x0 )                                                 183
    La difficulté dans ce cas est d'arrivé à remonter à l'allocation du buffer passé à send - dans le cas ci-dessus 0x02513D60. Etant donnée le type d'adresse il s'agit probablement d'un buffer alloué sur le tas (donc malloc -> ... -> RtlAllocateHeap)

    Sous le désassembleur (olly en l’occurrence), essaye de voir d'où vient le second paramètre passé à send(). Depuis ce paramètre, essaye d'en trouver l'origine. Deux options:

    - Soit il (le buffer) provient de la même fonction (même stack frame).
    - Soit il provient d'une fonction appelante (stack frame supérieur).

    Dans le premier cas, c'est relativement facile et tu l'aurais certainement vu, mais il y a des chances que ce ne soit pas le cas.
    Dans le deuxième cas, soit le pointeur vers le buffer est passé en argument à la fonction qui appelle send(), soit il passé via une ou plusieurs indirections.

    Par indirection; j'entends quelque chose du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    mov ecx, [edi]
    mov ebx, [ecx+08]
    ; ebx = pointeur vers le buffer
    S'il est passé en argument de la fonction, il faut alors regarder das la fonction supérieure. S'il est passé via une indirection, ça se complique, car il faut alors tracer (suivre et regarder) d'où vient le pointeur qui contient l'adresse du buffer, et ainsi de suite (le pointeur vers le pointeur vers le pointeur du buffer...).

    Dans certains cas le "tracing" d'indirection devient trop complexe. Dans ton cas, on voit qu'il y a un recv() avant le send(). Ce recv() est le premier à être appelé dans ton log-trace. On peut aussi gager que le buffer du send() a un rapport avec le contenu reçu via recv().

    L'idée est de poser un BP sur recv(), et de poser ensuite un BP sur une fonction d'allocation: soit statique/dynamique type malloc(), soit ntdll!RtlAllocateHeap() qui est la dernière fonction à être appelée lors d'une allocation sur le tas (c-a-d qu'on passe forcément par cette fonction).

    Sachant que le 3ème paramètre de RtlAllocateHeap() est la taille du buffer allouée, tu peux regarder si une allocation est faites avec une taille de 183 (taille passée à send() dans ton trace-log). Ceci dit, ça n'est pas forcément la même taille allouée et passé à send(). Dans ce dernier cas, tu poses un BP de log sur RtlHeapAlloc() et tu log l'adresse de sortie de la fonction( pointeur vers le buffer alloué).

    Ensuite tu compares les adresses loggées avec celle passée à send(). Il devrait y avoir à un moment ou à un autre une correspondance. A partir de là tu aura trouvé l'endroit où est alloué le buffer, il ne reste plus qu'a tracer depuis cet endroit jusqu'au send().

    Il y a de toute façon de forte chance que le buffer passé à send() ne soit pas allouée avant l'appel à la fonction socket() ce qui laisse potentiellement peu de ligne de code traversée entre l'allocation et l'utilisation lors du send().

    Je suis conscient que l'entreprise est complexe, mais il n'existe pas d'alternative ce genre de problème, et en combinant analyse statique et runtime c'est tout à fait possible.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2007
    Messages : 4
    Par défaut Merci pour ces explications
    Bonjour,

    L'adresse est bien passée via une indirection. J'ai reussi à la remonter sur trois niveaux.

    Un peu après le premier Recv, si je récupère le pointeur à l'adresse EAX+44, ce pointeur me redonne un pointeur et le résultat de ce pointeur + 2 me positionne dans l'espace mémoire où est construite la trame, mais elle y est déja construite.

    Donc je vais essayer de faire ce que tu me proposes, c'est-à-dire mettre un BP sur l'API d'allocation dynamique et vérifier par rapport à la taille.

    Merci encore pour ces excellentes explications. Je suis certes un bon développeur en Delphi (pascal) mais vraiment un amateur en assembleur, et cela est toujours plaisant d'avoir une réponse, cohérente et construite.

    Donc merci, pour le temps donné à me répondre.

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 06/11/2013, 11h41
  2. Recherche d'algorithmes pour l'analyse de la texture
    Par nounadevelop dans le forum Traitement d'images
    Réponses: 150
    Dernier message: 25/04/2008, 19h28
  3. exercice complexité et analyse des algorithmes
    Par psycho_xn dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 21/01/2008, 14h04
  4. Réponses: 4
    Dernier message: 28/11/2006, 12h44
  5. doc sur l'analyse des algorithmes
    Par pinkle dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 28/05/2005, 12h59

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