Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6

Discussion: Utilisation de ptrace

  1. #1
    Membre expérimenté

    Profil pro Marc
    Ingénieur développement logiciels
    Inscrit en
    novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Nom : Marc
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : novembre 2009
    Messages : 377
    Points : 509
    Points
    509

    Par défaut Utilisation de ptrace

    Bonjour,

    j'essaye de mettre en place une méthode d'anti-debugging très connu, la détection du ptrace.

    J'arrive à le faire lorsque je n'ai qu'une seule occurrence, mais je n'arrive pas à me détacher, donc lorsque je refais un appel à ptrace, celui-ci me renvoie une erreur.

    Un petit bout de code pour montrer ce que j'aimerai faire :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <sys/ptrace.h>
     
    int main(void)
    {
       pid_t pid;
       pid = getpid();
     
       printf("Process create with PID : %d\n", pid);
       printf("TraceME %d\n", ptrace(PTRACE_TRACEME,0,1,0));
       printf("KILL%d\n", ptrace(PTRACE_KILL,pid,1,0));
       printf("TraceME 2 %d\n", ptrace(PTRACE_TRACEME,0,1,0));
    Et la sortie :

    Code :
    1
    2
    3
    4
    5
    # ./armPtrace
    Process create with PID : 450
    TraceME 0
    KILL-1
    TraceME 2 -1
    Comme on peut le voir, le premier trace fonctionne (retour 0), mais le kill ne fonctionne pas, tout comme le second traceme, car le processus est déjà sous debug.

    Dans un premier temps j'ai pensé à un problème de timer, et j'ai tenté d'ajouter un wait, mais pas plus de résultat.

    Quelqu'un aurait-il une idée, mon objectif est juste de savoir si je suis déjà "ptracer" (du verbe ptrace). Et de pouvoir le faire x fois de suite.

    Merci

  2. #2
    Modérateur
    Avatar de Bktero
    Profil pro
    Ingénieur systèmes embarqués
    Inscrit en
    juin 2009
    Messages
    2 644
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2009
    Messages : 2 644
    Points : 6 315
    Points
    6 315

    Par défaut

    Je découvre ptrace en lisant le manuel : http://man.developpez.com/man2/ptrace.2.php

    PTRACE_TRACEME est pour démarrer la surveillance, dans le processus fils.
    PTRACE_KILL est pour envoyé au fils un signal SIGKILL. Cet appel doit être fait dans le père et non dans le fils comme tu le fais. Ton processus n'a rien à tuer, et ça doit être la cause de son plantage.

    De plus, tu ne crées pas de processus fils dans ce code exemple, ce que le man indique comme procéder classique d'utilisation de ptrace :
    Le père peut démarrer un suivi en appelant fork(2) et que le fils créé face un PTRACE_TRACEME, suivi (en général) par un exec(3). Autrement, le père peut commencer un suivi sur un processus existant en utilisant PTRACE_ATTACH.
    En espérant que ça te serve.
    Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

    Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

    Pour vos problèmes d'embarqué, utilisez le forum dédié !

  3. #3
    Membre expérimenté

    Profil pro Marc
    Ingénieur développement logiciels
    Inscrit en
    novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Nom : Marc
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : novembre 2009
    Messages : 377
    Points : 509
    Points
    509

    Par défaut

    Oui ça confirme ce que j'avais lu en anglais, mais j'étais pas à 100% sûr de moi .

    Donc voila la partie suivante, je me suis dis tiens, pourquoi ne pas utiliser attach. Mais je n'arrive à rien.

    Le manuel dit :
    PTRACE_ATTACH
    Attaches to the process specified in pid, making it a traced "child" of the
    calling process; the behavior of the child is as if it had done a
    PTRACE_TRACEME. The calling process actually becomes the parent of the
    child process for most purposes (e.g., it will receive notification of child
    events and appears in ps(1) output as the child's parent), but a getppid(2)
    by the child will still return the PID of the original parent. The child is
    sent a SIGSTOP, but will not necessarily have stopped by the completion of
    this call; use wait(2) to wait for the child to stop. (addr and data are
    ignored.)

    Since Ubuntu 10.10, PTRACE_ATTACH is not allowed against arbitrary matching-
    uid processes. The traced "child" must be a descendant of the tracer or must
    have called prctl(2) using PR_SET_PTRACER, with the pid of the tracer (or
    one of its ancestors). For more details, see /etc/sysctl.d/10-ptrace.conf.
    Alors j'ai essayé ce code :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int main(void)
    {
    	#ifndef PR_SET_PTRACER
    	#define PR_SET_PTRACER 0x59616d61
    	#endif
    	pid_t pid;
    	int status;
    	pid = getpid();
    	printf("Set ptracer : %d\n", prctl(PR_SET_PTRACER, pid, 0, 0, 0));
    	printf("Process create with PID : %d\n", pid);
    	printf("TraceME %d\n", ptrace(PTRACE_ATTACH, pid,0,0));
    	printf("TraceME 2 %d\n", ptrace(PTRACE_DETACH,pid,0,0));
    	printf("KILL%d\n", ptrace(PTRACE_ATTACH,pid,0,0));
    }

    Et la sortie :

    Code :
    1
    2
    3
    4
    5
    6
    Set ptracer : -1
    Process create with PID : 517
    TraceME -1
    TraceME 2 -1
    KILL-1
    #
    Je comprends pas pourquoi il refuse toutes les opérations (je suis sur un arm-linux, mais j'ai quand même esssayé de seter le PR_SET_PTRACER, et cela ne chance rien).

    Quelqu'un aurait une idée ?

  4. #4
    Modérateur
    Avatar de Bktero
    Profil pro
    Ingénieur systèmes embarqués
    Inscrit en
    juin 2009
    Messages
    2 644
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2009
    Messages : 2 644
    Points : 6 315
    Points
    6 315

    Par défaut

    Euh.... Si j'ai bien compris, ptrace permet à un processus père de suivre un processus fils. Dans ton code, je ne vois pas de processus fils et donc je vois pas comment ça pourrait marcher. Il faut que ton processus en cours crée un processus fils, avec fork() puis établir le lien ptrace entre le père et son fils, en :
    • dans le processus fils, faisant un TRACE_ME
    • ou dans le processus père, faisant un ATTACH


    prctl() est a appelé dans le processus à suivre si ce processus n'est pas le fils du suiveur. C'est le cas à partir de Ubuntu 10.10 mais ça peut différer avec un autre OS.


    Que souhaites-tu faire en fait ? Tu souhaites débugguer un programme que tu as écrit ? Des tâches plus complexes ?
    Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

    Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

    Pour vos problèmes d'embarqué, utilisez le forum dédié !

  5. #5
    Membre expérimenté

    Profil pro Marc
    Ingénieur développement logiciels
    Inscrit en
    novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Nom : Marc
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : novembre 2009
    Messages : 377
    Points : 509
    Points
    509

    Par défaut

    En faite la technique de détection du debugging (technique faible d'ailleurs) est de regarder si un processus est déjà en cours de débug. Car la plupart des débugger utilise la librairie ptrace pour effectuer celui-ci.

    L'idée est la suivante, tu essayes de te debugger, si il te renvoie une erreur c'est que tu es déjà sous débug.

    J'arrive à le faire une fois sans problème, mais ensuite je n'arrive pas à le détacher (c'est ce que je fais avec ptrace_me. Maintenant j'aimerai le faire avec attach pour pouvoir le détacher.

    C'est pour cela que je veux être mon propre père-fils dans un seul programme. Comme ça je peux me détacher-rattacher quand je le souhaite.

    J'essayerai de le faire avec un fork la semaine prochaine, mais je pensais que je pouvais le faire sans créer de processus fils.

  6. #6
    Membre expérimenté

    Profil pro Marc
    Ingénieur développement logiciels
    Inscrit en
    novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Nom : Marc
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : novembre 2009
    Messages : 377
    Points : 509
    Points
    509

    Par défaut

    J'ai fais quelques essaie, mais c'est vraiment la misère

    Je ne trouve aucun moyen pour faire ce que je veux, c'est à dire voir si je suis déjà sous ptrace, et revenir à un état ou je peux ré-effectuer ce test.

    Si j'utilise un fork, cela ne sert à rien car je contrôle si le fork est sous ptrace et non si le processus père l'est.

    J'ai voulu tenter une autre approche :

    1. Je fais un ptraceme sur mon processus.
    2. Si retour -1 exit (je suis déjà sous debugger).
    Sinon, je crée un fork, qui va s'attacher à son père et se détacher (j'espère que cela annule le ptraceme).
    3. je ferme mon fork.

    4. J'effectue les phases 1-3 à nouveau.

    Le problème c'est que je n'arrive pas à m'attacher sur mon processus père :

    Code :
    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
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
     
     
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <sys/prctl.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ptrace.h>
    #include <sys/prctl.h>
    #include <sys/mman.h>
     
    int* state;
     
    int main(void)
    {
     
    	state = mmap(NULL, sizeof(int), PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
    	*state = 0;
    	#ifndef PR_SET_PTRACER
    	#define PR_SET_PTRACER 0x59616d61
    	#endif
    	printf("----------- FIRST TRY ------------\n");
    	int status;
    	pid_t pid;
    	pid_t pidFork;
    	pid = getpid();
    	pidFork = fork(); 
    	printf("state %d\n", *state);
    	if (pidFork == -1)
    	{
    		printf("Error during fork");
    		exit(0);
    	}
     
    	// Parent attach son.
    	if (pidFork != 0)
    	{
    		printf("Run PID %d with new fork with PID %d\n", pid, pidFork);
    		printf("Set ptracer : %d for id :%d\n", prctl(PR_SET_PTRACER, pidFork, 0, 0, 0), pidFork);
    		status = ptrace(PTRACE_TRACEME, 0, 1, 0);
    		printf("Trace traceme %d for PID %d\n", status, getpid());
     
    		// Detect debug.
    		if (status == -1)
    		{
    			printf("Debugger detect LEAVING NOW !!!\n");
    			exit(1);
    		}
    		*state = 1;
    	}
     
    	printf("state for pid %d %d\n", getpid(), *state);
     
    	// Kill child.
    	if (pidFork == 0)
    	{
    		while(*state == 0){printf(""); sleep(1);}
    		status = ptrace(PTRACE_ATTACH, pid, 1, 0);
    		printf("\nTrace attach %d for PID %d\n", status, pid);
    		status = ptrace(PTRACE_DETACH, pid, 1, 0);
    		printf("Trace detach %d for PID %d\n", status, pid);
    		*state = 2;
    	}
     
    	// Assure we have kill the child.
    	while(*state != 2)
    	{}
     
    	printf("----------- SECOND TRY ------------\n");
     
    	*state = 0;
    	pidFork = fork(); 
     
    	if (pidFork == -1)
    	{
    		printf("Error during fork");
    		exit(0);
    	}
     
    	// Parent attach son.
    	if (pidFork != 0)
    	{
    		printf("Run PID %d with new fork with PID %d\n", pid, pidFork);
    		printf("Set ptracer : %d for id :%d\n", prctl(PR_SET_PTRACER, pidFork, 0, 0, 0), pidFork);
    		status = ptrace(PTRACE_TRACEME, 0, 1, 0);
    		printf("Trace traceme %d for PID %d\n", status, getpid());
     
    		// Detect debug.
    		if (status == -1)
    		{
    			printf("Debugger detect LEAVING NOW !!!\n");
    			exit(1);
    		}
    		*state = 1;
    	}
     
    	// Kill child.
    	if (pidFork == 0)
    	{
    		while(*state == 0){printf(""); sleep(1);}
    		status = ptrace(PTRACE_ATTACH, pid, 1, 0);
    		printf("\nTrace attach %d for PID %d\n", status, pid);
    		status = ptrace(PTRACE_DETACH, pid, 1, 0);
    		printf("Trace detach %d for PID %d\n", status, pid);
    		*state = 2;
    	}
     
    	// Assure we have kill the child.
    	while(*state != 2)
    	{}
     
     
    	// Kill parent.
    	if (pidFork != 0)
    	{
    		printf("Parent end of life.\n");
    		exit(0);
    	}
    }
    Est-ce que mon idée peut marcher ? (attacher et détacher pour remettre ptraceme en état standard). Ou une solution pour réaliser cette implémentation ?

    Merci

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •