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

Bibliothèques, systèmes et outils C Discussion :

Utilisation de ptrace


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre confirmé

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

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    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.

  3. #3
    Membre confirmé

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

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    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 ?

  5. #5
    Membre confirmé

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

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    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 confirmé

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

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    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 : 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
    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

Discussions similaires

  1. Utilisation de la commande ptrace()
    Par Hahuha dans le forum Threads & Processus
    Réponses: 0
    Dernier message: 24/11/2011, 19h22
  2. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  3. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  4. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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