Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Bibliothèques, systèmes et outils
Bibliothèques, systèmes et outils Forum d'entraide sur les bibliothèques, la programmation système et les outils en C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 05/07/2012, 10h52   #1
manticore
Membre éclairé
 
Marc
Ingénieur sécurité
Inscription : novembre 2009
Messages : 282
Détails du profil
Informations personnelles :
Nom : Marc
Localisation : Suisse

Informations professionnelles :
Activité : Ingénieur sécurité

Informations forums :
Inscription : novembre 2009
Messages : 282
Points : 319
Points : 319
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
manticore est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2012, 11h03   #2
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 696
Détails du profil
Informations personnelles :
Âge : 25
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 : 1 696
Points : 4 135
Points : 4 135
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 :
Citation:
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é !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 05/07/2012, 13h31   #3
manticore
Membre éclairé
 
Marc
Ingénieur sécurité
Inscription : novembre 2009
Messages : 282
Détails du profil
Informations personnelles :
Nom : Marc
Localisation : Suisse

Informations professionnelles :
Activité : Ingénieur sécurité

Informations forums :
Inscription : novembre 2009
Messages : 282
Points : 319
Points : 319
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 :
Citation:
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 ?
manticore est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2012, 13h46   #4
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 696
Détails du profil
Informations personnelles :
Âge : 25
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 : 1 696
Points : 4 135
Points : 4 135
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é !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/07/2012, 13h52   #5
manticore
Membre éclairé
 
Marc
Ingénieur sécurité
Inscription : novembre 2009
Messages : 282
Détails du profil
Informations personnelles :
Nom : Marc
Localisation : Suisse

Informations professionnelles :
Activité : Ingénieur sécurité

Informations forums :
Inscription : novembre 2009
Messages : 282
Points : 319
Points : 319
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.
manticore est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/07/2012, 15h45   #6
manticore
Membre éclairé
 
Marc
Ingénieur sécurité
Inscription : novembre 2009
Messages : 282
Détails du profil
Informations personnelles :
Nom : Marc
Localisation : Suisse

Informations professionnelles :
Activité : Ingénieur sécurité

Informations forums :
Inscription : novembre 2009
Messages : 282
Points : 319
Points : 319
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
manticore est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 23h26.


 
 
 
 
Partenaires

Hébergement Web