Embedded ELF Debugging : the middle head of Cerberus

                             ==Phrack Inc.==

              Volume 0x0b, Issue 0x3f, Phile #0x09 of 0x14

|=------=[ Embedded ELF Debugging : the middle head of Cerberus ]=------=|
|=----------------------------------------------------------------------=|
|=------------=[ The ELF shell crew <elfsh@devhell.org> ]=--------------=|
|=----------------------------------------------------------------------=|
|=--------------=[ Traduit par TboWan pour arsouyes.org ]=--------------=|
|=----------------------------------------------------------------------=|



I. Introduction au déboguage endurci
     A. Travaux précédents & limites
     B. Au delà de PaX et ptrace
     C. Amélioration de l'interface
II. Air de jeu du déboguage embarqué
     A. Injection dans un processus
     B. Alternance de scripting ELF sur disque et en mémoire
     C. Déboguage proprement dit : dumping, backtrace, breakpoints
     D. Génération d'analyseurs dynamiques
III. De meilleures redirections ELF multi-architecture
     A. CFLOW : redirection de fonction statique résistante à PaX
     B. Revision de la technique ALTPLT
     C. Technique ALTGOT : Le complément RISC
     D. Technique EXTPLT : post-liaison de fonction inconnues
     E. Algorithmes compatibles IA32, SPARC32/64, ALPHA64, MIPS32
V. Déboguage contraint
     A. relocalisation ET_REL en mémoire
     B. Relocalisation ET_REL dans ET_DYN
     C. Extentions d'exécutables statiques
     D. Algorithmes indépendants de l'architecture
VI. Passé et présent
VII. Remerciements
VIII. Références



-------[ I. Introduction au déboguage sous contraintes


	     Dans le passé, la manipulation de binaires s'est surtout
	portee sur l'écriture de virus, le cracking, le déploiement
	de backdoors, et la création de minuscules exécutable camouflés.
	A part les outils du projet GNU comme binutils qui inclu le GNU
	debugger [1] (qui s'intéresse plus à la portabilité qu'aux
	fonctionnalités), aucune suite majeure de manipulation de binaire
	n'existe. Depuis près de dix ans, le format ELF a été un succès
	et la plupart des systèmes et distributions UNIX se basent dessus.

	Cependant, les outils existants ne tirent pas avantages du
	format et la plupart des logiciels de reverse engineering ou de
	débugging sont soit trop spécifiques à une architecture, ou ne
	font tout simplement pas attention à la structure du binaire pour
	extraire ou rediriger des informations.

	Depuis notre première publication sur le shell ELF, nous avons
	tellement amélioré la nouvelle suite qu'il est maintenant temps
	de publier un second article de fond mettant l'accent sur les
	avancées dans les techniques ELF statiques et à la volée. Nous
	allons expliquer en grands détails les 8 nouvelles
	fonctionnalités de manipulations de binaires qui intersectent la
	méthodologie existante du reverse engineering. Ces techniques
	permettent un nouveau type d'approche du déboguage et l'extension
	de logiciels proprietaire en environnement contraint.

	Nous avons travaillé sur beaucoup d'architectures (x86, alpha,
	sparc, mips) et nous nous sommes concentrés sur les environements
	contraints où les binaires sont liés pour inclure des protections
	de sécurité (comme les binaires endurcis de gentoo) dans les
	machines protégées par PaX [2]. Ceci signifie que notre débugger
	reste utilisable quand il est injecté dans un processus (local ou)
	distant.


----[ A. Travaux précédents & limites


	Dans la première partie de la série d'articles Cerberus, nous
	avions introduit une nouvelle technique résidente appelée
	l'injection ET_REL. Elle consistait en la compilation d'un source
	en C vers un objet relogeable (.o) et de son injection dans un
	programme sans les sources sur architecture INTEL et SPARC pour le
	format ELF32.

	Nous avons amélioré cette technique pour qu'à la fois les
	binaires 32 et 64 bits soient supportés en ajoutant un support
	pour alpha64 et sparc64. Nous avons aussi travaillé sur
	l'architecture MIPS r5000 et fournissons maintenant un
	debut d'environnement pour cette architecture. Nous
	permettons maintenant aussi l'injection ET_REL dans les objets
	ET_DYN (librairies partagées), notre technique est donc
	complètement compatible avec des environnement complètement
	randomisés comme ceux fournis par les Gentoo endurcies en
	activant PaX sur le système d'exploitation Linux. Nous avons
	aussi travaillé sur d'autres OS comme les BSD's, Solaris et HP-UX
	et le code y a été compilé et testé régulièrement aussi.

	Une innovation majeure de notre suite de manipulation de binaires
	basée sur le débugging est l'absence d'utilisation de ptrace. Nous n'utilisons
	pas de résidence dans le noyau comme [8] pour que même les
	utilisateurs sans privilèges puisse l'utiliser. Enfin, l'environment n'est pas
	dépendant d'API optionelles du système d'exploitation.

	Les débogueurs existants se base sur l'appel système ptrace pour
	que le processus de déboguage s'attache au programme débogué et
	permette des manipulations internes variables du processus comme
	la copie de mémoire, le placement de points d'arrets, le
	backtracking, etc. Nous proposons les mêmes fonctionnalités sans
	utiliser l'appel système.

	Les raisons pour lesquelles nous n'utilisons pas ptrace sont
	simples et multiples. Tout d'abord, beaucoup de systèmes endurcis
	ou embarqués ne l'implémentent pas. C'est le cas des systèmes
	basés sur grsecurity, des systèmes de production, ou les systèmes
	sur téléphones dont le système d'exploitation est basé sur ELF
	mais sans interface pour ptrace.

	La deuxième raison de ne pas utiliser ptrace est la pénalité de
	performance due à ce système de déboguage. Nous n'avons aucune
	penalite de performances puisque notre débogueur se trouve dans le
	même processus. Nous fournissons une technique complète en mode
	utilisateur qui n'a pas besoin d'accéder à la mémoire noyau, elle
	est donc utile dans toutes les étapes de test de pénétration
	quand on veut déboguer un logiciel sensible dans un environnement
	endurci et qu'aucune mise à jour du système n'est possible.

	Nous permettons d'injecter du code C dans un nouveau fichier
	binaire (dans une optique statique) ou dans un processus (en mode
	à la volée) en utilisant une API unifiee. Quand cela est necessaire,
	nous n'utilisons que des techniques ELF qui réduisent
	les indices sur le disque et fonctionnent uniquement en mémoire.


----[ B. Au delà de PaX et ptrace


	Un autre point clef de notre suite est la technique de
	redirection grandement améliorée. Nous pouvons rediriger
	quasiment tous les flots de contrôle, que le code soit ou non
	dans le binaire lui même (technique CFLOW) ou dans une librairie
	dont le binaire dépend (notre précédent travail présentais une
	nouvelle technique d'hijacking, ALTPLT).

	Nous avons amélioré cette technique et sommes passé à travers
	plusieurs réécritures et fournissons à présent une
	implémentation complète et indépendante de l'architecture. Nous
	avons completé ALTPLT par une nouvelle technique appellée ALTGOT
	qui rend possible l'hijacking d'une fonction puis l'appel de son
	code original sur des machines Alpha, Mips et RISC.

	Nous avons aussi créé une nouvelle technique appellée EXTPLT qui
	autorise des fonctions inconnues (pour lesquelles il n'y a aucune
	information de liaison du tout dans le fichier ELF) utilisant un
	algorithme de post-liaison compatible avec les objets ET_EXEC et
	ET_DYN.


----[ C. Amélioration de l'interface


	Notre implémentation du débogueur ELF embarqué est un prototype.
	Il faut comprendre qu'il est réellement utilisable mais est
	encore au stade du développement. Tout le code présenté ici
	fonctionne. Cependant, nous ne sommes pas omniscients et vous
	pouvez rencontrer des problèmes. Dans ce cas, envoyez-nous un
	email pour que nous puissions voir comment faire un patch.

	La seule supposition que nous avons faite est la capacité de lire
	le programme débogué. Dans tous les cas, vous pouvez aussi
	déboguer en mémoire un binaire illisible sur disque en chargeant
	le débogueur via la variable LD_PRELOAD. Cependant, les fonctionalites
	du debugger sont plus interessantes quand le binaire est lisible.
	Puisque le débogueur fonctionne dans le même espace d'adressage,
	vous pouvez toujours lire la mémoire [3] [4] et restaurer le programme
	binaire bien que nous ne l'avons pas encore implemente nous meme.

	Le langage de communication central pour la suite Embedded ELF
	Debugger (e2dbg) est le langage de script ELFsh. Nous l'avons
	étendu avec des boucles et des contrôles conditionnels, un
	support transparent pour les variables typées dynamiquement (comme en
	python). La commande source (pour exécuter un script dans la
	session courante) et les macros défines par l'utilisateur (la
	commande scriptdir) sont aussi supportées.

	Nous avons aussi développé une pile pair à pair appellée
	Distributed Update Management Protocol - DUMP - qui permet de
	lier plusieurs instances du débogueur via le réseau, mais ses
	capacités ne font pas l'objet de cet article. Pour être complets,
	nous supportons maintenant des sessions multi-utilisateurs (en
	parallèle ou partagées) et les changements d'environnements en
	utilisant la commande workspace.

	Nous allons voir l'utilisation de cette interface dans la
	première partie de ce papier. Dans la seconde partie, nous
	donnons des détails techniques sur l'implémentation de ces
	fonctionnalités sur de multiples architectures. La dernière
	partie est dédiée aux avancées techniques les plus récentes que
	nous avons développé ces dernières semaines sur le déboguage
	contraint de binaires protégés. Le dernier algorithme du papier
	est indépendant de l'architecture et constitue le coeur du moteur
	de relocation dans ELFsh.


-------[ II. Air de jeu du déboguage embarqué



---[ A. Injection dans un processus



	Nous avons différentes techniques d'injection du débogueur dans
	un processus débogué. Ils vont donc partager le même espace
	d'adressage et le débogueur sera capable de lire ses propres
	données et code pour récupérer et changer les informations du
	processus débogué.

	Puisque ELF shell est composé a l'heure actuelle de 40 000 lignes
	de code, nous n'avons pas voulu tout recoder pour permettre la
	modification de binaires. Nous avons utilisé des astuces qui nous
	ont permi de sélectionner si la modification sera faite en mémoire ou
	sur le disque. Le truc consiste en 10 lignes de code. En considérant que
	la macro PROFILE n'est pas obligatoire, voici le code exact :


 (libelfsh/section.c)


 ========= BEGIN DUMP 0 =========

 void                    *elfsh_get_raw(elfshsect_t *sect)
 {
   ELFSH_PROFILE_IN(__FILE__, __FUNCTION__, __LINE__);

   /* sect->parent->base is always NULL for ET_EXEC */
   if (elfsh_is_debug_mode())
     {
       sect->pdata = (void *) sect->parent->base + sect->shdr->sh_addr;
      ELFSH_PROFILE_ROUT(__FILE__, __FUNCTION__, __LINE__, (sect->pdata));
     }
   if (sect)
     ELFSH_PROFILE_ROUT(__FILE__, __FUNCTION__, __LINE__, (sect->data));

   ELFSH_PROFILE_ERR(__FILE__, __FUNCTION__, __LINE__, 
					"Invalid parameter", NULL);
 }

 ========= END DUMP 0 =========


	Quelle est cette technique ? C'est assez simple : si le drapeau
	du débogueur interne indique le mode statique (modification sur le
	disque), alors, on retourne le pointeur vers le cache des données
	interne d'ELFsh pour la section de données (ou de code) que nous
	voulons accéder.

	Cependant, si nous sommes en mode dynamique (modification du
	processus), alors nous retournons juste l'adresse de la section.
	Le débogueur fonctionne dans le même processus et pensera donc
	que l'adresse retournée est un buffer en lecture (ou écriture).
	Nous pouvons réutiliser toute l'API de ELF shell en faisant juste
	attention à l'utilisation de la fonction elfsh_get_raw() quand
	nous accédont au pointeur ->data. La sélection processus/sur
	disque est transparente pour tout le code du debogueur/elfsh.

	L'idée d'injecter du code directement dans le processus n'est pas
	nouvelle et ça fait quelques années maintenant que nous
	l'étudions. L'injection de code embarqué est aussi utilisée par
	la communauté du cracking sous Windows [12] pour éviter la
	plupart des protection contre le traçage et le déboguage, mais
	nous n'avons vu nulle part d'implémentation d'un débogueur
	complet, capable de telles fonctionnalités avancées comme
	l'injection ET_REL ou la redirection de fonctions sur des
	architectures multiples, à la fois sur disque et en mémoire, dans
	un seul code.



---[ B. Alternance de scripts ELF sur disque et en mémoire
        (y compris avec la linkmap)


	Nous avons deux approches pour insérer le débogueur dans le
	programmé débogué. Quand on utilise une entrée DT_NEEDED et qu'on
	redirige le main débogué vers le point d'entrée main du débogueur
	ET_DYN, nous injectons aussi differentes sections pour
	permettre de faires des techniques essentielles comme EXTPLT.
	Ceci sera expliqué en détail dans la prochaine partie.

	La deuxième approche implique l'utilisation du LD_PRELOAD sur le
	programme débogué et de placer des points d'arrets (soit via
	l'opcode 0xCC sous x86, via l'opcode équivalent sur les autres
	architectures, ou en redirigeant des fonctions, ce qui est
	disponible sur beaucoup d'architectures et pour de nombreux
	genres de fonctions dans cette suite).

	Puisqu'une modification du binaire est nécessaire de toute
	façons, nous allons utiliser la technique DT_NEEDED pour ajouter
	les dépendances de librairies, et toutes les injections de
	sections et redirections décrites dans cet article avant le
	débogueur proprement dit.

	La technique du LD_PRELOAD est particulièrement plus utile quand
	vous ne pouvez pas lire le binaire que vous voulez déboguer. Le
	choix du type d'injection du débogueur est laissé à
	l'utilisateur, qui le fera en fonction des besoins du moment.

	Voyons comment utiliser le débogueur embarqué et sa commande
	"mode" qui fait la sélection en mémoire/sur disque. Ensuite, nous
	imprimons la Table Globale d'Offset [NDT : Global Offset Table -
	.got]. D'abord, la mémoire GOT est affichée, ensuite, nous
	revenons en mode static et la GOT sur disque est affichée :


 ========= BEGIN DUMP 1 =========

 (e2dbg-0.65) list

 .::. Working files .::.
 [001] Sun Jul 31 19:23:33 2005  D ID: 9 /lib/libncurses.so.5
 [002] Sun Jul 31 19:23:33 2005  D ID: 8 /lib/libdl.so.2
 [003] Sun Jul 31 19:23:33 2005  D ID: 7 /lib/libtermcap.so.2
 [004] Sun Jul 31 19:23:33 2005  D ID: 6 /lib/libreadline.so.5
 [005] Sun Jul 31 19:23:33 2005  D ID: 5 /lib/libelfsh.so
 [006] Sun Jul 31 19:23:33 2005  D ID: 4 /lib/ld-linux.so.2
 [007] Sun Jul 31 19:23:33 2005  D ID: 3 ./ibc.so.6    # e2dbg.so renamed
 [008] Sun Jul 31 19:23:33 2005  D ID: 2 /lib/tls/libc.so.6
 [009] Sun Jul 31 19:23:33 2005 *D ID: 1 ./a.out_e2dbg # debuggee

 .::. ELFsh modules .::.
 [*] No loaded module

 (e2dbg-0.65) mode

 [*] e2dbg is in DYNAMIC MODE

 (e2dbg-0.65) got

 [Global Offset Table .::. GOT : .got ]
 [Object ./a.out_e2dbg]

 0x080498E4: [0] 0x00000000       <?>

 [Global Offset Table .::. GOT : .got.plt ]
 [Object ./a.out_e2dbg]

 0x080498E8: [0] 0x0804981C       <_DYNAMIC@a.out_e2dbg>
 0x080498EC: [1] 0x00000000       <?>
 0x080498F0: [2] 0x00000000       <?>
 0x080498F4: [3] 0x0804839E       <fflush@a.out_e2dbg>
 0x080498F8: [4] 0x080483AE       <puts@a.out_e2dbg>
 0x080498FC: [5] 0x080483BE       <malloc@a.out_e2dbg>
 0x08049900: [6] 0x080483CE       <strlen@a.out_e2dbg>
 0x08049904: [7] 0x080483DE       <__libc_start_main@a.out_e2dbg>
 0x08049908: [8] 0x080483EE       <printf@a.out_e2dbg>
 0x0804990C: [9] 0x080483FE       <free@a.out_e2dbg>
 0x08049910: [10] 0x0804840E      <read@a.out_e2dbg>

 [Global Offset Table .::. GOT : .elfsh.altgot ]
 [Object ./a.out_e2dbg]

 0x08049928: [0] 0x0804981C      <_DYNAMIC@a.out_e2dbg>
 0x0804992C: [1] 0xB7F4A4E8      <_r_debug@ld-linux.so.2 + 24>
 0x08049930: [2] 0xB7F3EEC0      <_dl_rtld_di_serinfo@ld-linux.so.2 + 477>
 0x08049934: [3] 0x0804839E      <fflush@a.out_e2dbg>
 0x08049938: [4] 0x080483AE      <puts@a.out_e2dbg>
 0x0804993C: [5] 0xB7E515F0      <__libc_malloc@libc.so.6>
 0x08049940: [6] 0x080483CE      <strlen@a.out_e2dbg>
 0x08049944: [7] 0xB7E01E50      <__libc_start_main@libc.so.6>
 0x08049948: [8] 0x080483EE      <printf@a.out_e2dbg>
 0x0804994C: [9] 0x080483FE      <free@a.out_e2dbg>
 0x08049950: [10] 0x0804840E     <read@a.out_e2dbg>
 0x08049954: [11] 0xB7DAFFF6     <e2dbg_run@ibc.so.6>

 (e2dbg-0.65) mode static

 [*] e2dbg is now in STATIC mode

 (e2dbg-0.65) # Here we switched in ondisk perspective
 (e2dbg-0.65) got

 [Global Offset Table .::. GOT : .got ]
 [Object ./a.out_e2dbg]

 0x080498E4: [0] 0x00000000       <?>

 [Global Offset Table .::. GOT : .got.plt ]
 [Object ./a.out_e2dbg]

 0x080498E8: [0] 0x0804981C       <_DYNAMIC>
 0x080498EC: [1] 0x00000000       <?>
 0x080498F0: [2] 0x00000000       <?>
 0x080498F4: [3] 0x0804839E       <fflush>
 0x080498F8: [4] 0x080483AE       <puts>
 0x080498FC: [5] 0x080483BE       <malloc>
 0x08049900: [6] 0x080483CE       <strlen>
 0x08049904: [7] 0x080483DE       <__libc_start_main>
 0x08049908: [8] 0x080483EE       <printf>
 0x0804990C: [9] 0x080483FE       <free>
 0x08049910: [10] 0x0804840E      <read>

 [Global Offset Table .::. GOT : .elfsh.altgot ]
 [Object ./a.out_e2dbg]

 0x08049928: [0] 0x0804981C       <_DYNAMIC>
 0x0804992C: [1] 0x00000000       <?>
 0x08049930: [2] 0x00000000       <?>
 0x08049934: [3] 0x0804839E       <fflush>
 0x08049938: [4] 0x080483AE       <puts>
 0x0804993C: [5] 0x080483BE       <malloc>
 0x08049940: [6] 0x080483CE       <strlen>
 0x08049944: [7] 0x080483DE       <__libc_start_main>
 0x08049948: [8] 0x080483EE       <printf>
 0x0804994C: [9] 0x080483FE       <free>
 0x08049950: [10] 0x0804840E      <read>
 0x08049954: [11] 0x0804614A      <e2dbg_run + 6>

 =========  END DUMP 1 =========


	Il y a beaucoup de choses à voir dans ce dump. Tout d'abord, vous
	pouvez vérifier qu'il fait effectivement ce qu'il est supposé
	faire en regardant les premières entrées de la GOT qui sont
	réservées pour la linkmap et la fonction rtld dl-resolve. Ces
	entrées sont remplies à l'exécution, donc, la version statique de
	la GOT contien des pointeurs NULL pour celles-là. Cependant, la
	GOT en mémoire a ces entrées qui sont remplies.

	En plus, la nouvelle version de l'éditeur de lien de GNU insère
	de multiples sections GOT dans les binaires ELF. La section .got
	gère les pointeurs vers les données externes, tandis que la
	.got.plt gère les pointeurs vers les fonctions externes. Dans les
	premières version de LD, ces deux sections étaient fusionnées.
	Nous supportons les deux conventions.

	Enfin, vous pouvez voir à la fin dans la section .elfsh.altgot.
	Ça fait partie de notre technique ALTGOT et sera expliquée comme un
	algorithme indépendant dans la prochaine partie du papier. La
	technique ALTGOT permet une augmentation de la taille de la GOT.
	Ça permet différentes choses suivant l'architecture sur laquelle
	on se trouve. Sous x86, ALGOT est seulement utilisée quand EXTPLT
	l'est aussi, pour pouvoir ajouter des fonctions supplémentaires
	au programme hôte. Sur MIPS et ALPHA, ALTGOT permet de rediriger
	une fonction externe (PLT) sans perdre l'adresse réelle de la
	fonction. Nous développerons ces deux techniques dans la partie
	suivante.



---[ C. Déboguage proprement dit : dumping, backtrace, breakpoints

	Quand nous déboguons en utilisant un débogueur embarqué dans le
	processus débogué, nous n'avons pas besoin de ptrace, et nous ne
	pouvons pas modifier si facilement l'espace d'adressage du
	processus. C'est pourquoi nous devons effectuer de petits
	changements statiques : nous pouvons par exemple ajouter le débogueur
	comme une dépendance DT_NEEDED (dans le cas ou nous n'utilisons pas
	LD_PRELOAD). Le débogueur va aussi surcharger certains
	gestionnaires de signaux (SIGTRAP, SIGINT, SIGSEGV ..) pour qu'il
	puisse garder le contrôle de ces évenements.

	Nous pouvons rediriger des fonctions en utilisant tout autant les
	techniques CFLOW ou ALTPLT utilisant des modifications sur
	disque, pour récupérer le contrôle au moment désiré. Nous pouvons
	évidement mettre des breakpoints lors de l'exécution, mais cela
	demande de mprotect la zone de code si elle n'était pas en
	écriture à ce moment. Nous avons des idées pour ne plus être
	embêtés par mprotect mais ça n'a pas été implémenté dans cette
	version (0.65). (En fait, beaucoup d'utilisations de l'appel
	systèle mprotect sont incompatible avec une des options de PaX).
	Heureusement, en assumant pour l'instant que nous avons un accès
	en lecture vers le programme débogué, on peut copier le fichier
	et désactivé cette option.

	Voici comment la dépendance DT_NEEDED est ajoutée :


 ========= BEGIN DUMP 2 =========

 elfsh@WTH $ cat inject_e2dbg.esh
 #!../../vm/elfsh
 load a.out
 set 1.dynamic[08].val 0x2
 set 1.dynamic[08].tag DT_NEEDED
 redir main e2dbg_run
 save a.out_e2dbg

 =========  END DUMP 2 =========


	Voyons maintenant la section .dynamic modifiée du binaire, où les
	entrées DT_NEEDED supplémentaires ont été ajoutée grace à la
	technique DT_DEBUG publiée il y a deux ans [0] :


 ========= BEGIN DUMP 3 =========

 elfsh@WTH $ ../../vm/elfsh -f ./a.out -d DT_NEEDED

 [*] Object ./a.out has been loaded (O_RDONLY)

 [SHT_DYNAMIC]
 [Object ./a.out]

 [00] Name of needed library => libc.so.6 {DT_NEEDED}

 [*] Object ./a.out unloaded

 elfsh@WTH $ ../../vm/elfsh -f ./a.out_e2dbg -d DT_NEEDED

 [*] Object ./a.out_e2dbg has been loaded (O_RDONLY)

 [SHT_DYNAMIC]
 [Object ./a.out_e2dbg]

 [00] Name of needed library => libc.so.6 {DT_NEEDED}
 [08] Name of needed library => ibc.so.6 {DT_NEEDED}

 [*] Object ./a.out_e2dbg unloaded

 =========  END DUMP 3 =========

	Voyons maintenant comment la fonction main est redirigée vers la
	fonction hook_main. Vous pouvez noter les deux octets écrasés
	entre les deux jmp de hook_main. Cette technique est aussi
	disponible sur l'architecture MIPS, mais ce dump vient de
	l'implémentation IA32 :


 ========= BEGIN DUMP 4 =========

 elfsh@WTH $ ../../vm/elfsh -f ./a.out_e2dbg -D main%40

 [*] Object ./a.out_e2dbg has been loaded (O_RDONLY)

 08045134 [foff: 308] hook_main + 0  jmp   <e2dbg_run>
 08045139 [foff: 313] hook_main + 5  push  %ebp
 0804513A [foff: 314] hook_main + 6  mov   %esp,%ebp
 0804513C [foff: 316] hook_main + 8  push  %esi
 0804513D [foff: 317] hook_main + 9  push  %ebx
 0804513E [foff: 318] hook_main + 10 jmp   <main + 5>

 08045139 [foff: 313] old_main + 0   push  %ebp
 0804513A [foff: 314] old_main + 1   mov   %esp,%ebp
 0804513C [foff: 316] old_main + 3   push  %esi
 0804513D [foff: 317] old_main + 4   push  %ebx
 0804513E [foff: 318] old_main + 5   jmp   <main + 5>

 08048530 [foff: 13616] main + 0     jmp   <hook_main> 
 08048535 [foff: 13621] main + 5     sub   $2010,%esp
 0804853B [foff: 13627] main + 11    mov   8(%ebp),%ebx
 0804853E [foff: 13630] main + 14    mov   C(%ebp),%esi
 08048541 [foff: 13633] main + 17    and   $FFFFFFF0,%esp
 08048544 [foff: 13636] main + 20    sub   $10,%esp
 08048547 [foff: 13639] main + 23    mov   %ebx,4(%esp,1)
 0804854B [foff: 13643] main + 27    mov   $<_IO_stdin_used + 43>,(%esp,1)
 08048552 [foff: 13650] main + 34    call  <printf>
 08048557 [foff: 13655] main + 39    mov   (%esi),%eax

 [*] No binary pattern was specified

 [*] Object ./a.out_e2dbg unloaded

 =========  END DUMP 4 =========


	Exécutons maintenant le programme débogué dans lequel on a
	injecté le débogueur.


 ========= BEGIN DUMP 5 =========

 elfsh@WTH $ ./a.out_e2dbg


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 17:56:52 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 17:56:52 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libelfsh.so loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) b puts

 [*] Breakpoint added at <puts@a.out_e2dbg> (0x080483A8)

 (e2dbg-0.65) continue

         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test

         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 17:57:03 2005 - New object /lib/tls/libc.so.6 loaded

 (e2dbg-0.65) bt

 .:: Backtrace ::.
 [00] 0xB7DC1EC5 <vm_bt@ibc.so.6 + 208>
 [01] 0xB7DC207F <cmd_bt@ibc.so.6 + 152>
 [02] 0xB7DBC88C <vm_execmd@ibc.so.6 + 174>
 [03] 0xB7DAB4DE <vm_loop@ibc.so.6 + 578>
 [04] 0xB7DAB943 <vm_run@ibc.so.6 + 271>
 [05] 0xB7DA5FF0 <e2dbg_entry@ibc.so.6 + 110>
 [06] 0xB7DA68D6 <e2dbg_genericbp_ia32@ibc.so.6 + 183>
 [07] 0xFFFFE440 <_r_debug@ld-linux.so.2 + 1208737648>	# sigtrap retaddr
 [08] 0xB7DF7F3B <__libc_start_main@libc.so.6 + 235>	
 [09] 0x08048441 <_start@a.out_e2dbg + 33>

 (e2dbg-0.65) b

 .:: Breakpoints ::.

 [00] 0x080483A8 <puts@a.out_e2dbg>

 (e2dbg-0.65) delete 0x080483A8

 [*] Breakpoint at 080483A8 <puts@a.out_e2dbg> removed

 (e2dbg-0.65) b

 .:: Breakpoints ::.

 [*] No breakpoints

 (e2dbg-0.65) b printf

 [*] Breakpoint added at <printf@a.out_e2dbg> (0x080483E8)

 (e2dbg-0.65) dumpregs

 .:: Registers ::.

         [EAX] 00000000 (0000000000) <unknown>
         [EBX] 08203F48 (0136331080) <.elfsh.relplt@a.out_e2dbg + 1811272>
         [ECX] 00000000 (0000000000) <unknown>
         [EDX] B7F0C7C0 (3086010304) <__guard@libc.so.6 + 1656>
         [ESI] BFE3B7C4 (3219371972) <_r_debug@ld-linux.so.2 + 133149428>
         [EDI] BFE3B750 (3219371856) <_r_debug@ld-linux.so.2 + 133149312>
         [ESP] BFE3970C (3219363596) <_r_debug@ld-linux.so.2 + 133141052>
         [EBP] BFE3B738 (3219371832) <_r_debug@ld-linux.so.2 + 133149288>
         [EIP] 080483A9 (0134513577) <puts@a.out_e2dbg>

 (e2dbg-0.65) stack 20

 .:: Stack ::.
 0xBFE37200 0x00000000 <(null)>
 0xBFE37204 0xB7DC2091 <vm_dumpstack@ibc.so.6>
 0xBFE37208 0xB7DDF5F0 <_GLOBAL_OFFSET_TABLE_@ibc.so.6>
 0xBFE3720C 0xBFE3723C <_r_debug@ld-linux.so.2 + 133131628>
 0xBFE37210 0xB7DC22E7 <cmd_stack@ibc.so.6 + 298>
 0xBFE37214 0x00000014 <_r_debug@ld-linux.so.2 + 1208744772>
 0xBFE37218 0xB7DDDD90 <__FUNCTION__.5@ibc.so.6 + 49>
 0xBFE3721C 0xBFE37230 <_r_debug@ld-linux.so.2 + 133131616>
 0xBFE37220 0xB7DB9DF9 <vm_implicit@ibc.so.6 + 304>
 0xBFE37224 0xB7DE1A7C <world@ibc.so.6 + 92>
 0xBFE37228 0xB7DA8176 <do_resolve@ibc.so.6>
 0xBFE3722C 0x080530B8 <.elfsh.relplt@a.out_e2dbg + 38072>
 0xBFE37230 0x00000014 <_r_debug@ld-linux.so.2 + 1208744772>
 0xBFE37234 0x08264FF6 <.elfsh.relplt@a.out_e2dbg + 2208758>
 0xBFE37238 0xB7DDF5F0 <_GLOBAL_OFFSET_TABLE_@ibc.so.6>
 0xBFE3723C 0xBFE3726C <_r_debug@ld-linux.so.2 + 133131676>
 0xBFE37240 0xB7DBC88C <vm_execmd@ibc.so.6 + 174>
 0xBFE37244 0x0804F208 <.elfsh.relplt@a.out_e2dbg + 22024>
 0xBFE37248 0x00000000 <(null)>
 0xBFE3724C 0x00000000 <(null)>

 (e2dbg-0.65) continue

         [..: Embedded ELF Debugger returns to the grave :...]

 First_puts

         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 18:00:47 2005 - /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 18:00:47 2005 - /usr/lib/gconv/ISO8859-1.so loaded

 (e2dbg-0.65) dumpregs

 .:: Registers ::.

         [EAX] 0000000B (0000000011) <_r_debug@ld-linux.so.2 + 1208744763>
         [EBX] 08203F48 (0136331080) <.elfsh.relplt@a.out_e2dbg + 1811272>
         [ECX] 0000000B (0000000011) <_r_debug@ld-linux.so.2 + 1208744763>
         [EDX] B7F0C7C0 (3086010304) <__guard@libc.so.6 + 1656>
         [ESI] BFE3B7C4 (3219371972) <_r_debug@ld-linux.so.2 + 133149428>
         [EDI] BFE3B750 (3219371856) <_r_debug@ld-linux.so.2 + 133149312>
         [ESP] BFE3970C (3219363596) <_r_debug@ld-linux.so.2 + 133141052>
         [EBP] BFE3B738 (3219371832) <_r_debug@ld-linux.so.2 + 133149288>
         [EIP] 080483E9 (0134513641) <printf@a.out_e2dbg>

 (e2dbg-0.65) linkmap

 .::. Linkmap entries .::.
 [01] addr : 0x00000000 dyn : 0x0804981C -
 [02] addr : 0x00000000 dyn : 0xFFFFE590 -
 [03] addr : 0xB7DE3000 dyn : 0xB7F0AD3C - /lib/tls/libc.so.6
 [04] addr : 0xB7D95000 dyn : 0xB7DDF01C - ./ibc.so.6
 [05] addr : 0xB7F29000 dyn : 0xB7F3FF14 - /lib/ld-linux.so.2
 [06] addr : 0xB7D62000 dyn : 0xB7D93018 - /lib/libelfsh.so
 [07] addr : 0xB7D35000 dyn : 0xB7D5D46C - /lib/libreadline.so.5
 [08] addr : 0xB7D31000 dyn : 0xB7D34BB4 - /lib/libtermcap.so.2
 [09] addr : 0xB7D2D000 dyn : 0xB7D2FEEC - /lib/libdl.so.2
 [10] addr : 0xB7CEB000 dyn : 0xB7D2A1C0 - /lib/libncurses.so.5
 [11] addr : 0xB6D84000 dyn : 0xB6D85F28 - /usr/lib/gconv/ISO8859-1.so

 (e2dbg-0.65) exit

 [*] Unloading object 1 (/usr/lib/gconv/ISO8859-1.so)
 [*] Unloading object 2 (/lib/tls/libc.so.6)
 [*] Unloading object 3 (/lib/tls/libc.so.6)
 [*] Unloading object 4 (/lib/libncurses.so.5)
 [*] Unloading object 5 (/lib/libdl.so.2)
 [*] Unloading object 6 (/lib/libtermcap.so.2)
 [*] Unloading object 7 (/lib/libreadline.so.5)
 [*] Unloading object 8 (/home/elfsh/WTH/elfsh/libelfsh/libelfsh.so)
 [*] Unloading object 9 (/lib/ld-linux.so.2)
 [*] Unloading object 10 (./ibc.so.6)
 [*] Unloading object 11 (/lib/tls/libc.so.6)
 [*] Unloading object 12 (./a.out_e2dbg) *

         .:: Bye -:: The Embedded ELF Debugger 0.65

 =========  END DUMP 5 =========


	Comme vous venez de le voir, l'utilisation du débogueur est assez
	similaire aux autres débogueurs. La différence tient dans la
	technique d'implémentation qui permet un déboguage sur des
	systèmes embarqués et endurcis où ptrace n'est pas présent ou est
	désactivé.

	On nous a dit [9] que l'appel système sigaction active la
	possibilité d'exécution pas à pas sans utiliser ptrace. Nous
	n'avons pas eu le temps de l'implémenté mais nous fournirons un
	débogueur pas à pas dans un futur proche. Puisque cet appel n'est
	pas filtré par grsecurity et semble assez portable sous Linux,
	BSD, Solaris et HP-UX, ça vaut certainement la peine de le tester.


---[ D. Génération d'analyseurs dynamiques


	Évidement, les outils comme ltrace[7] peuvent maintenant être
	fait en utilisant des scripts elfsh pour des architectures
	multiples puisque tout le travail de redirections à été fait.

	Nous pensons aussi que la suite peut être utilisée dans des
	instrumentations de logiciels dynamiques. Puisque nous supportons
	des architectures multiples, nous laissons la porte ouverte à
	d'autres équipes de développement pour coder ce genre de
	modules ou d'extensions au sein de la suite ELF shell.

	Nous n'avons pas eu le temps d'inclure un script d'example qui le
	fait, mais nous le ferons bientôt. Le genre de choses
	intéressantes qui peuvent être faites et améliorée en utilisant
	la suite prendrait leur inspiration dans des projets comme fenris
	[6]. Ceci pourrait être fait pour de multiples architectures
	puisque le type de format d'instruction est intégré dans le
	moteur de script, en utilisant l'abstraction du code de libasm
	(qui est maintenant inclu comme source dans elfsh).

	Nous n'avons pas encore traité le chiffrement pour l'instant,
	mais des API prometteuses [5] pourrait être implémentées aussi
	pour de multiples architectures très facilement.



-------[ III. Meilleures redirections ELF multi-architecture


	Dans la première édition du Cerberus ELF interface [0], nous
	avions présenté une technique de redirection appelée ALTPLT.
	Cette technique n'est pas suffisante puisqu'elle ne permet que
	des redirections du PLT sur des fonctions existantes du programme
	binaire, les fonctions utilisables pour étendre le logiciel sont
	donc limitées.

	De plus, nous avons remarqué un bogue dans l'implémentation de la
	technique ALTPLT publiée précédement : sur l'architecture SPARC,
	quand on appelait une fonction originale, la redirection était
	enlevée et le programme continuait à fonctionner comme si aucun
	détournement n'était installé. Ce bogue vient du fait que Solaris
	n'utilise pas le champt r_offset pour calculer ses
	relocations mais calcule l'offset dans le fichier en
	multipliant la taille de l'entrée du PLT par l'offset de
	relocation placé sur la pile au moment de la résolution
	dynamique.

	Nous avons trouvé une solution à ce problème. Cette solution
	consiste à mettre quelques corrections spécifiques à
	l'architecture au début de la section ALTPLT. Cependant, une
	telle correction est trop dépendante de l'architecture et nous
	avons commencé à pensé à une technique alternative pour
	implémenter ALTPLT. Tout en implémentant la technique DT_DEBUG en
	modifiant certaines entrées de la section .dynamic, nous avons
	découvert que beaucoup d'autres entrées sont écrasables et nous
	fournissent une technique très forte et indépendante de
	l'architecture pour redirriger l'accès à des sections variables.
	Plus précisément, quand on patche l'entrée DT_PLTREL, nous sommes
	capable de fournir notre propre pointeur. DT_PLTREL est une
	entrée DEPENDANTE de l'architecture et la documentation à son
	sujet est très petite, pour ne pas dire inexistante.

	Elle pointe en fait sur la section de l'exécutable qui est
	relogee à l'exécution (par exemple la GOT sous x86 et mips,
	PLT sous sparc et alpha). En changeant cette entrée, nous sommes
	capable de fournir notre propre PLT ou GOT, qui nous permet de
	l'étendre par la suite.

	Regardons d'abord la technique CFLOW, nous reviendrons ensuite
	sur les redirections relatives au PLT en utilisant les
	modifications de DT_PLTREL.



---[ A. CFLOW : redirection de fonction statique résistante à PaX

	CFLOW est une technique simple mais efficace pour rediriger des
	fonctions qui sont localisées dans le programme hôte et qui n'ont
	pas d'entrée dans la PLT.

	Voyons maintenant le fichier hôte que nous allons utiliser pour
	les tests :



 ========= BEGIN DUMP 6 =========

 elfsh@WTH $ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     legit_func(char *str)
 {
   printf("legit func (%s) !\n", str);
   return (0);
 }

 int	main()
 {
   char  *str;
   char  buff[BUFSIZ];

   read(0, buff, BUFSIZ-1);

   str = malloc(10);
   if (str == NULL)
     goto err;
   strcpy(str, "test");
   printf("First_printf %s\n", str);
   fflush(stdout);
   puts("First_puts");
   printf("Second_printf %s\n", str);

   free(str);

   puts("Second_puts");

   fflush(stdout);
   legit_func("test");
   return (0);
  err:
   printf("Malloc problem\n");
   return (-1);
 }

 =========  END DUMP 6 =========


	Nous allons ici rediriger la fonction legit_func, localisée dans
	le fichier host.c par la fonction hook_funk localisée dans
	l'objet relogeable.

	Jetons un coup d'oeuil au fichier relogeable que nous allons
	injecter dans le binaire précédant.


 ========= BEGIN DUMP 7 =========

 elfsh@WTH $ cat rel.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     glvar_testreloc = 42;
 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;

 int     hook_func(char *str)
 {
    printf("HOOK FUNC %s !\n", str);
    return (old_legit_func(str));
 }

 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   printf("Trojan injected ET_REL takes control now "
          "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
         str2, str,
         glvar_testreloc,
         glvar_testreloc_bss,
         glvar_testreloc_bss2,
         glvar_testreloc_bss3,
         local);

   free(str2);

   putchar('e');
   putchar('x');
   putchar('t');
   putchar('c');
   putchar('a');
   putchar('l');
   putchar('l');
   putchar('!');
   putchar('\n'); 

   old_puts(str); 

   write(1, "calling write\n", 14);
   fflush(stdout);
   return (0);
 }

 int     func2()
 {
   return (42);
 }

 =========  END DUMP 7 =========


	  Comme vous pouvez le voir, l'objet relogeable utilise des
	fonctions inconnues comme write et putchar. Ces fonctions n'ont
	pas de symbole, d'entrée dans la PLT, d'entrée dans la GOT, ou
	même une entrée relogeable dans le programme hôte.

	Nous pouvons l'appeller quand même en utilisant la technique
	EXTPLT qui sera expliquée comme technique indépendante dans la
	prochaine partie du papier. Pour l'instant, nous nous concentrons
	sur la technique CFLOW qui permet de rediger legit_func vers
	hook_func. Cette fonction n'a pas d'entrée en PLT et nous ne
	pouvons pas utiliser une simple infection de PLT.

	Nous avons développé une technique qui ne craint pas PaX pour les
	redirections sur disque de ce genre de fonctions. Elle consiste à
	mettre un bon vieux jmp au début de legit_func et de rediriger le
	flot vers notre code. ELFsh fera attention à bien exécuter part
	les octets écrasés ailleur et rendra le contrôle à la fonction
	redirigée, juste après le détournement par jmp, pour qu'aucune
	restauration à l'exécution ne soit nécessaire et qu'elle reste
	immunisée sur le disque contre PaX.

	Quand ces techniques sont utilisées dans le débogueur directement
	en mémoire et pas sur le disque, elles cassent les protection
	mrprotect de PaX, ce qui veut dire que ce flag doit être
	désactivé si vous voulez rediriger le flot directement en
	mémoire. Nous avons utilisé l'appel système mrprotect sur de
	petites zones de code pour pouvoir changer quelques instructions
	spécifiques pour la redirection. Cependant, nous pensons que
	cette technique est plus intéressante pour le déboguage et pas
	pour autre chose, ce n'est donc pas, pour nous, une priorité de
	l'améliorer.

	Voyons le petit script ELFsh pour cet exemple :


 ========= BEGIN DUMP 8 =========

 elfsh@WTH $ file a.out
 a.out: ELF 32-bit LSB executable, Intel 80386, dynamically linked, \
 not stripped
 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 load a.out
 load rel.o

 reladd 1 2

 redir puts puts_troj
 redir legit_func hook_func

 save fake_aout

 quit

 =========  END  EXAMPLE 8 =========


	La sortie du binaire ORIGINAL est la suivante :


 ========= BEGIN DUMP 9 =========

 elfsh@WTH $ ./a.out

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !

 ========= END DUMP 9 ===========


	Injectons maintenant le bazar :


 ========= BEGIN DUMP 10 ========

 elfsh@WTH $ ./relinject.esh


         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 ~load a.out

 [*] Sun Jul 31 15:30:14 2005 - New object a.out loaded

 ~load rel.o

 [*] Sun Jul 31 15:30:14 2005 - New object rel.o loaded

 ~reladd 1 2
 Section Mirrored Successfully !

 [*] ET_REL rel.o injected succesfully in ET_EXEC a.out

 ~redir puts puts_troj

 [*] Function puts redirected to addr 0x08047164 <puts_troj>

 ~redir legit_func hook_func

 [*] Function legit_func redirected to addr 0x08047134 <hook_func>

 ~save fake_aout

 [*] Object fake_aout saved successfully

 ~quit

 [*] Unloading object 1 (rel.o)
 [*] Unloading object 2 (a.out) *
         .:: Bye -:: The ELF shell 0.65

 ========= END DUMP 10 =========


	Exécutons maintenant le binaire modifié.


 ========= BEGIN DUMP 11 =========

 elfsh@WTH $ ./fake_aout

 First_printf test
 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 extcall!
 First_puts
 calling write
 Second_printf test
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 extcall!
 Second_puts
 calling write
 HOOK FUNC test !
 Trojan injected ET_REL takes control now [Z:LEGIT FUNC:42:43:44:45:1]
 extcall!
 calling write
 legit func (test) !
 elfsh@WTH $

 =========  END DUMP 11 =========


	Bien. legit_func a clairement été redirigée vers hook_func, et
	elle a bien fait attention à rappeller legit_func en utilisant la
	technique du vieux symbole décrite dans la première édition des
	articles de Cerberus.

	Regardons le code original de legit_func et celui redirigé en
	utilisant la technique CFLOW sous x86 :


 ========= BEGIN DUMP 12 =========

 080484C0 legit_func + 0        push   %ebp                             
 080484C1 legit_func + 1        mov    %esp,%ebp                        
 080484C3 legit_func + 3        sub    $8,%esp                          
 080484C6 legit_func + 6        mov    $<_IO_stdin_used + 4>,(%esp,1)   
 080484CD legit_func + 13       call   <.plt + 32>                      
 080484D2 legit_func + 18       mov    $<_IO_stdin_used + 15>,(%esp,1)  

 ========= END DUMP 12 =========


	   Maintenant, le code modifié :


 ========= BEGIN DUMP 13 =========

 080484C0 legit_func + 0        jmp    <hook_legit_func>               
 080484C5 legit_func + 5        nop                                    
 080484C6 legit_func + 6        mov    $<_IO_stdin_used + 4>,(%esp,1)  
 080484CD legit_func + 13       call   <puts>                          
 080484D2 legit_func + 18       mov    $<_IO_stdin_used + 15>,(%esp,1) 
 080484D9 legit_func + 25       mov    8(%ebp),%eax                    
 080484DC legit_func + 28       mov    %eax,4(%esp,1)                  
 080484E0 legit_func + 32       call   <printf>                        
 080484E5 legit_func + 37       leave                                  
 080484E6 legit_func + 38       xor    %eax,%eax                       

 ========= END DUMP 13 =========

	Nous créons une nouvelle section .elfsh.hooks dont la donnée est
	un tableau de bouts de codes de détournement comme celui-ci :


 ========= BEGIN DUMP 14 =========

 08042134 hook_legit_func + 0   jmp    <hook_func>                     
 08042139 old_legit_func  + 0   push   %ebp                            
 0804213A old_legit_func  + 1   mov    %esp,%ebp                       
 0804213C old_legit_func  + 3   sub    $8,%esp                         
 0804213F old_legit_func  + 6   jmp    <legit_func + 6>                

 ========= END DUMP 14 =========

	Puisque nous voulons pouvoir rappeller la fonction originale
	(legit_func), nous avons rajouté les octets écrasés, juste après
	le premier jmp, et ensuite, nous rappellons legit_func avec le
	bon offset (pour ne pas avoir de récursion dans le détournement
	puisque la fonction a été hijackée), comme vous pouvez le voir
	commancant au symbole old_legit_func de l'exemple 14.

	Cette technique du vieux symbole est cohérente avec la technique
	ALTPLT qui a été publiée dans le premier article. Nous pouvons
	tout autant utiliser l'appel old_funcname() à l'intérieur du code
	injecté pour rappeler la bonne fonction hijackée, et nous le
	faisons sans un seul octet de restauration à l'exécution. C'est
	pour cela que la technique CFLOW ne craint pas PaX.

	Pour l'architecture MIPS, la technique CFLOW est assez similaire,
	nous pouvons voir sont résultat aussi (dump 15 est le binaire
	original et dump 16 celui modifié) :


 ======== BEGIN DUMP 15 =========

 400400 <func>:        lui     gp,0xfc1
 400404 <func+4>:      addiu   gp,gp,-21696
 400408 <func+8>:      addu    gp,gp,t9
 40040c <func+12>:     addiu   sp,sp,-40
 400410 <func+16>:     sw      ra,36(sp)
 [...]

 ======== END DUMP 15 =========

	Le code de fonction modifié est maintenant :


 ======== BEGIN DUMP 16 =========

 <func>
 400400:       addi    t9,t9,104	# registre T9 comme fonction cible
 400404:       j       0x400468 <func2> # JMP Direct vers la fonction hook
 400408:       nop			# delay slot sous MIPS
 40040c:       addiu   sp,sp,-40	# le code de fonction original
 400410:       sw      ra,36(sp)
 400414:       sw      s8,32(sp)
 400418:       move    s8,sp
 40041c:       sw      gp,16(sp)
 400420:       sw      a0,40(s8)

 ======== END DUMP 16 =========

	La fonction func2 peut être n'importe laquelle, pourvu qu'elle ai
	le même nombre et type de paramètres. Quand la fonction func2
	veut appeler la fonction originale (func), elle saute vers le
	symbole old_func qui pointe à l'intérieur de l'entrée de la
	section .elfsh.hooks pour ce détournement CFLOW. Voici à quoi
	ressemble un détournement d'entrée sous architecture MIPS :


 ======== BEGIN DUMP 17 ========= 
 
 <old_func>
 3ff0f4         addi    t9,t9,4876
 3ff0f8         lui     gp,0xfc1
 3ff0fc         addiu   gp,gp,-21696
 3ff100         addu    gp,gp,t9
 3ff104         j       0x400408 <func + 8>
 3ff108         nop
 3ff10c         nop

 ======== END DUMP 17 ===========


	Comme vous pouvez le voir, les trois instructions qui ont été
	écrasées pour installer le détournement CFLOW au début de func()
	sont maintenant localisées dans l'entrée de hook, pointée par le
	symbole old_func. Le registre T9 est aussi remi pour qu'on puisse
	revenir dans une situation sûre juste avant de sauter en arrière
	vers func + 8.



---[ B. Technique ALTPLT revue


	La technique ALTPLT v1 a été présentée dans le papier "the
	Cerberus ELF Interface" [0]. Comme déjà dit, elle n'était pas
	satisfaisante puisque le détournement était retiré dès le premier
	appel à la fonction originale.

	Puisque sous SPARC, les 4 premières entrées du PLT sont
	réservées, il y a de la place pour 12 instructions qui feront
	tout ce dont on a besoin (en fait, la première entrée PLT) quand
	ALTPLT+0 prendra le contrôle.

	ALTPLTv2 fonctionne en fait avec 12 instructions, mais il y avait
	besoin de réencoder la première entrée ALTPLT avec le code de
	PLT+0 (qui est relogé à l'exécution sous SPARC avant que le main
	n'aie le contrôle, ce qui explique pourquoi nous ne pouvons pas
	le patcher statiquement sur le disque).

	Mais ce comportement, il casse PaX, et son implantation sont très
	dépendante de l'architecture à cause de sa partie en assembleur
	SPARC. Pour ceux qui voudrait le voir, nous avons laissé le code
	de tout ceci dans l'arborescence du source d'ELFsh dans
	libelfsh/sparc32.c .

	Pour l'architecture ALPHA64, il fournis presque l'équivalents
	dans ses instructions respectives, et cette fois,
	l'implémentation est dans libelfsh/alpha64.c .

	Comme vous pouvez le voir dans le code (que nous ne reproduiront
	pas pour garder l'article clair), ALTPLTv2 est un vrai merdier et
	nous avions besoin d'éviter tout ce code assembleur qui demandait
	trop d'efforts pour un futur portage de cette technique sur
	d'autres architectures.

	Alors, nous avons découvert le truc du DT_PLTREL du .dynamic et
	nous avons essayé de voir ce qu'il se passe quand on change cette
	entrée du .dynamic dans le binaire hôte. Changer l'entrée
	DT_PLTREL est très intéressante puisqu'elle est entièrement
	indépendante de l'architecture et fonctionne donc partout.

	Voyons donc à quoi ressemble la table d'en-tête de sections et la
	section .dynamic utilisée dans la technique très simple ALTPLTv3.
	Nous utilisons la section .elfsh.altplt comme miroir de la .plt
	originale comme expliqué dans notre premier papier. Les autres
	sections .elfsh.* ont déjà été expliquées ou le seront juste
	après le log.

	La sortie (modifiée) du binaire ressemble à ceci :


 =============== BEGIN DUMP 18 ================

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object fake_aout]

 [000] 0x00000000 -------                 foff:00000000 sz:0000000 link:00
 [001] 0x08042134 a-x---- .elfsh.hooks    foff:00000308 sz:0000016 link:00
 [002] 0x08043134 a-x---- .elfsh.extplt   foff:00004404 sz:0000048 link:00
 [003] 0x08044134 a-x---- .elfsh.altplt   foff:00008500 sz:0004096 link:00
 [004] 0x08045134 a--ms-- rel.o.rodata.str1.32 foff:12596 sz:4096  link:00
 [005] 0x08046134 a--ms-- rel.o.rodata.str1.1  foff:16692 sz:4096  link:00
 [006] 0x08047134 a-x---- rel.o.text      foff:00020788 sz:0004096 link:00
 [007] 0x08048134 a------ .interp         foff:00024884 sz:0000019 link:00
 [008] 0x08048148 a------ .note.ABI-tag   foff:00024904 sz:0000032 link:00
 [009] 0x08048168 a------ .hash           foff:00024936 sz:0000064 link:10
 [010] 0x080481A8 a------ .dynsym         foff:00025000 sz:0000176 link:11
 [011] 0x08048258 a------ .dynstr         foff:00025176 sz:0000112 link:00
 [012] 0x080482C8 a------ .gnu.version    foff:00025288 sz:0000022 link:10
 [013] 0x080482E0 a------ .gnu.version_r  foff:00025312 sz:0000032 link:11
 [014] 0x08048300 a------ .rel.dyn        foff:00025344 sz:0000016 link:10
 [015] 0x08048310 a------ .rel.plt        foff:00025360 sz:0000056 link:10
 [016] 0x08048348 a-x---- .init           foff:00025416 sz:0000023 link:00
 [017] 0x08048360 a-x---- .plt            foff:00025440 sz:0000128 link:00
 [018] 0x08048400 a-x---- .text           foff:00025600 sz:0000736 link:00
 [019] 0x080486E0 a-x---- .fini           foff:00026336 sz:0000027 link:00
 [020] 0x080486FC a------ .rodata         foff:00026364 sz:0000116 link:00
 [021] 0x08048770 a------ .eh_frame       foff:00026480 sz:0000004 link:00
 [022] 0x08049774 aw----- .ctors          foff:00026484 sz:0000008 link:00
 [023] 0x0804977C aw----- .dtors          foff:00026492 sz:0000008 link:00
 [024] 0x08049784 aw----- .jcr            foff:00026500 sz:0000004 link:00
 [025] 0x08049788 aw----- .dynamic        foff:00026504 sz:0000200 link:11
 [026] 0x08049850 aw----- .got            foff:00026704 sz:0000004 link:00
 [027] 0x08049854 aw----- .got.plt        foff:00026708 sz:0000040 link:00
 [028] 0x0804987C aw----- .data           foff:00026748 sz:0000012 link:00
 [029] 0x08049888 aw----- .bss            foff:00026760 sz:0000008 link:00
 [030] 0x08049890 aw----- rel.o.bss       foff:00026768 sz:0004096 link:00
 [031] 0x0804A890 aw----- rel.o.data      foff:00030864 sz:0000004 link:00
 [032] 0x0804A894 aw----- .elfsh.altgot   foff:00030868 sz:0000048 link:00
 [033] 0x0804A8E4 aw----- .elfsh.dynsym   foff:00030948 sz:0000208 link:34
 [034] 0x0804AA44 aw----- .elfsh.dynstr   foff:00031300 sz:0000127 link:33
 [035] 0x0804AB24 aw----- .elfsh.reldyn   foff:00031524 sz:0000016 link:00
 [036] 0x0804AB34 aw----- .elfsh.relplt   foff:00031540 sz:0000072 link:00
 [037] 0x00000000 ------- .comment        foff:00031652 sz:0000665 link:00
 [038] 0x00000000 ------- .debug_aranges  foff:00032324 sz:0000120 link:00
 [039] 0x00000000 ------- .debug_pubnames foff:00032444 sz:0000042 link:00
 [040] 0x00000000 ------- .debug_info     foff:00032486 sz:0006871 link:00
 [041] 0x00000000 ------- .debug_abbrev   foff:00039357 sz:0000511 link:00
 [042] 0x00000000 ------- .debug_line     foff:00039868 sz:0000961 link:00
 [043] 0x00000000 ------- .debug_frame    foff:00040832 sz:0000072 link:00
 [044] 0x00000000 ---ms-- .debug_str      foff:00040904 sz:0008067 link:00
 [045] 0x00000000 ------- .debug_macinfo  foff:00048971 sz:0029295 link:00
 [046] 0x00000000 ------- .shstrtab       foff:00078266 sz:0000507 link:00
 [047] 0x00000000 ------- .symtab         foff:00080736 sz:0002368 link:48
 [048] 0x00000000 ------- .strtab         foff:00083104 sz:0001785 link:47

 [SHT_DYNAMIC]
 [Object ./testsuite/etrel_inject/etrel_original/fake_aout]

 [00] Name of needed library            =>           libc.so.6 {DT_NEEDED}
 [01] Address of init function          =>          0x08048348 {DT_INIT}
 [02] Address of fini function          =>          0x080486E0 {DT_FINI}
 [03] Address of symbol hash table      =>          0x08048168 {DT_HASH}
 [04] Address of dynamic string table   =>          0x0804AA44 {DT_STRTAB}
 [05] Address of dynamic symbol table   =>          0x0804A8E4 {DT_SYMTAB}
 [06] Size of string table              =>      00000127 bytes {DT_STRSZ}
 [07] Size of symbol table entry        =>      00000016 bytes {DT_SYMENT}
 [08] Debugging entry (unknown)         =>          0x00000000 {DT_DEBUG}
 [09] Processor defined value           =>          0x0804A894 {DT_PLTGOT}
 [10] Size in bytes for .rel.plt        =>      000072 bytes {DT_PLTRELSZ}
 [11] Type of reloc in PLT              =>            00000017 {DT_PLTREL}
 [12] Address of .rel.plt               =>          0x0804AB34 {DT_JMPREL}
 [13] Address of .rel.got section       =>          0x0804AB24 {DT_REL}
 [14] Total size of .rel section        =>      00000016 bytes {DT_RELSZ}
 [15] Size of a REL entry               =>      00000008 bytes {DT_RELENT}
 [16] SUN needed version table          =>          0x80482E0 {DT_VERNEED}
 [17] SUN needed version number         =>             001 {DT_VERNEEDNUM}
 [18] GNU version VERSYM                =>          0x080482C8 {DT_VERSYM}

 =============== END DUMP 18 ================


	Comme vous pouvez le voir, plusieurs sections ont été copiées
	etétendues, et leurs entrées da	ns .dynamic ont été changées.
	Ceci s'applique pour .got (DT_PLTGOT), .rel.plt (DT_JMPREL),
	.dunsym (DT_SYMTAB), et .dynstr (DT_STRTAB). Changer ces entrées
	nous fournis une nouvelle technique ALTPLT sans aucune ligne
	d'assembleur.

	Bien sûr, la technique ALTPLT version 3 n'a besoin d'aucune
	informations non-obligatoire comme la section debug. Ça peut
	sembler évident, mais certaines personnes nous ont vraiment posé
	la question.



---[ C. Technique ALTGOT : Le complément RISC


	       Sous architecture MIPS, les appels vers les entrées de PLT
	sont fait différement. En fait, au lieu d'une instruction call
	directe sur l'entrée, un jmp indirect est utilisé pour utiliser
	l'entrée GOT liée à la fonction désirée. Si cette entrée est
	remplie, alors, la fonction est appelée directement. Par défaut,
	les entrées GOT contiennent un pointeur vers les entrées PLT.
	Pendant l'exécution, par la suite, le linker dynamique est
	appelé pour reloge la section GOT (MIPS, x86) ou la section PLT
	(sous SPARC ou ALPHA).

	Voici un log d'assembleur MIPS qui le prouve sur un bête
	helloworld qui utilise printf :

       00400790 <main>:
       400790:  3c1c0fc0   lui     gp,0xfc0	  # Met GP à base de GOT
       400794:  279c78c0   addiu   gp,gp,30912    # address + 0x7ff0
       400798:  0399e021   addu    gp,gp,t9	  # utilise t9 (= main)
       40079c:  27bdffe0   addiu   sp,sp,-32	  
       4007a0:  afbf001c   sw      ra,28(sp)
       4007a4:  afbe0018   sw      s8,24(sp)
       4007a8:  03a0f021   move    s8,sp
       4007ac:  afbc0010   sw      gp,16(sp)
       4007b0:  8f828018   lw      v0,-32744(gp)
       4007b4:  00000000   nop
       4007b8:  24440a50   addiu   a0,v0,2640
       4007bc:  2405002a   li      a1,42
       4007c0:  8f828018   lw      v0,-32744(gp)
       4007c4:  00000000   nop
       4007c8:  24460a74   addiu   a2,v0,2676
       4007cc:  8f99803c   lw      t9,-32708(gp)  # charge l'entrée 
                                                  # GOT de printf
       4007d0:  00000000   nop
       4007d4:  0320f809   jalr    t9		  # y saute
       4007d8:  00000000   nop
       4007dc:  8fdc0010   lw      gp,16(s8)
       4007e0:  00001021   move    v0,zero
       4007e4:  03c0e821   move    sp,s8
       4007e8:  8fbf001c   lw      ra,28(sp)
       4007ec:  8fbe0018   lw      s8,24(sp)
       4007f0:  27bd0020   addiu   sp,sp,32
       4007f4:  03e00008   jr      ra		  # retour de la fonction
       4007f8:  00000000   nop
       4007fc:  00000000   nop

	On note que le registre de pointeur global %gp contient toujours
	l'adresse de base de la section GOT sous MIPS, plus ou moins un
	certain offset fixé, dans notre cas 0x7ff0 (0x8000 sous ALPHA).

	Pour pouvoir appeler une fonction dont l'adresse n'est pas
	connue, les entrées GOT sont remplies et ensuite, le jmp indirect
	sous MIPS n'utilise plus l'entrée PLT. Qu'apprenons nous de ceci ?
	Simplement que nous ne pouvons plus nous baser sur un
	détournement classique du PLT puisque le code de l'entrée PLT ne
	sera pas appelé si l'entrée GOT est déjà remplie, ce qui veut
	dire que nous ne détourneront la fonction que la première fois.

	À cause de ceci, nous détournerons les fonction en patchant le
	GOT sous MIPS. Cependant, il ne résoud pas le problème de
	rappeller la fonction originale. Pour permetre ces rappels, nous
	alons juste ajouter le symbols old_ sur l'entrée PLT réelle, pour
	que nous puissions toujours accéder aux morceaux de code du
	méchanismes de liaison dynamique même si la GOT a été modifiée.

	Voyons les résultats détaillés de la technique ALTGOT sous
	architecture ALPHA et MIPS. Ceci a été fait sans aucune ligne
	d'assembleur, ce qui la rend très portable :


 ========= BEGIN DUMP 19 =========

 elfsh@alpha$ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int main()
 {
   char  *str;

   str = malloc(10);
   if (str == NULL)
     goto err;
   strcpy(str, "test");
   printf("First_printf %s\n", str);
   fflush(stdout);
   puts("First_puts");
   printf("Second_printf %u\n", 42);
   puts("Second_puts");
   fflush(stdout);
   return (0);
  err:
   printf("Malloc problem %u\n", 42);
   return (-1);
 }

 elfsh@alpha$ gcc host.c -o a.out
 elfsh@alpha$ file ./a.out
 a.out: ELF 64-bit LSB executable, Alpha (unofficial), for NetBSD 2.0G,
       dynamically linked, not stripped

 ========= END DUMP 19 =========


	Exécution du binaire original :


 ========= BEGIN DUMP 20 =========

 elfsh@alpha$ ./a.out
 First_printf test
 First_puts
 Second_printf 42
 Second_puts

 ========= END DUMP 20 ==========


	Regardons encore une fois l'objet relogeable que nous allons
	injecter :


 ========= BEGIN DUMP 21 =========

 elfsh@alpha$ cat rel.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     glvar_testreloc = 42;

 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;


 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   printf("Trojan injected ET_REL takes control now "
         "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
         str2, str,
         glvar_testreloc,
         glvar_testreloc_bss,
         glvar_testreloc_bss2,
         glvar_testreloc_bss3,
         local);

   old_puts(str);
   fflush(stdout);
   return (0);
 }

 int     func2()
 {
   return (42);
 }

 ========= END DUMP 21 =========


	Comme vous pouvez le voir, l'objet relogeable rel.c utilise le
	symbole old_ qui signifie qu'il se base sur la technqiue ALTPLT.
	Cependant, nous ne faisont pas encore appel à la technique EXTPLT
	sous ALPHA et MIPS, nous ne pouvons donc pas encore appeler des
	fonctions inconnues à partir du binaire sur ces architectures.
	Notre rel.c est une copie de celui de l'example 7 sans l'appel
	aux fonction inconnues write et putchar de l'example 7.

	Maintenant, nous injectons le tout :


 ========= BEGIN DUMP 22 =========

 elfsh@alpha$ ./relinject.esh > relinject.out
 elfsh@alpha$ ./fake_aout
 First_printf test
 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 First_puts
 Second_printf 42
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 Second_puts

 ========= END DUMP 22 ==========


	La list des section sous ALPHA est la suivante. Un coup d'oeil à
	la section injectée est recommandé :


 ========= BEGIN DUMP 23 =========

 elfsh@alpha$ elfsh -f fake_aout -s -p

 [*] Object fake_aout has been loaded (O_RDONLY)

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object fake_aout]

 [000] 0x000000000 -------                     foff:00000 sz:00000
 [001] 0x120000190 a------ .interp             foff:00400 sz:00023
 [002] 0x1200001A8 a------ .note.netbsd.ident  foff:00424 sz:00024
 [003] 0x1200001C0 a------ .hash               foff:00448 sz:00544
 [004] 0x1200003E0 a------ .dynsym             foff:00992 sz:00552
 [005] 0x120000608 a------ .dynstr             foff:01544 sz:00251
 [006] 0x120000708 a------ .rela.dyn           foff:01800 sz:00096
 [007] 0x120000768 a------ .rela.plt           foff:01896 sz:00168
 [008] 0x120000820 a-x---- .init               foff:02080 sz:00128
 [009] 0x1200008A0 a-x---- .text               foff:02208 sz:01312
 [010] 0x120000DC0 a-x---- .fini               foff:03520 sz:00104
 [011] 0x120000E28 a------ .rodata             foff:03624 sz:00162
 [012] 0x120010ED0 aw----- .data               foff:03792 sz:00000
 [013] 0x120010ED0 a------ .eh_frame           foff:03792 sz:00004
 [014] 0x120010ED8 aw----- .dynamic            foff:03800 sz:00352
 [015] 0x120011038 aw----- .ctors              foff:04152 sz:00016
 [016] 0x120011048 aw----- .dtors              foff:04168 sz:00016
 [017] 0x120011058 aw----- .jcr                foff:04184 sz:00008
 [018] 0x120011060 awx---- .plt                foff:04192 sz:00116
 [019] 0x1200110D8 aw----- .got                foff:04312 sz:00240
 [020] 0x1200111C8 aw----- .sdata              foff:04552 sz:00024
 [021] 0x1200111E0 aw----- .sbss               foff:04576 sz:00024
 [022] 0x1200111F8 aw----- .bss                foff:04600 sz:00056
 [023] 0x120011230 a-x---- rel.o.text          foff:04656 sz:00320
 [024] 0x120011370 aw----- rel.o.sdata         foff:04976 sz:00008
 [025] 0x120011378 a--ms-- rel.o.rodata.str1.1 foff:04984 sz:00072
 [026] 0x1200113C0 a-x---- .alt.plt.prolog     foff:05056 sz:00048
 [027] 0x1200113F0 a-x---- .alt.plt            foff:05104 sz:00120
 [028] 0x120011468 a------ .alt.got            foff:05224 sz:00072
 [029] 0x1200114B0 aw----- rel.o.got           foff:05296 sz:00080
 [030] 0x000000000 ------- .comment            foff:05376 sz:00240
 [031] 0x000000000 ------- .debug_aranges      foff:05616 sz:00048
 [032] 0x000000000 ------- .debug_pubnames     foff:05664 sz:00027
 [033] 0x000000000 ------- .debug_info         foff:05691 sz:02994
 [034] 0x000000000 ------- .debug_abbrev       foff:08685 sz:00337
 [035] 0x000000000 ------- .debug_line         foff:09022 sz:00373
 [036] 0x000000000 ------- .debug_frame        foff:09400 sz:00048
 [037] 0x000000000 ---ms-- .debug_str          foff:09448 sz:01940
 [038] 0x000000000 ------- .debug_macinfo      foff:11388 sz:12937
 [039] 0x000000000 ------- .ident              foff:24325 sz:00054
 [040] 0x000000000 ------- .shstrtab           foff:24379 sz:00393
 [041] 0x000000000 ------- .symtab             foff:27527 sz:02400
 [042] 0x000000000 ------- .strtab             foff:29927 sz:00948

 [Program header table .::. PHT]
 [Object fake_aout]

 [00] 0x120000040 -> 0x120000190 r-x  => Program header table
 [01] 0x120000190 -> 0x1200001A7 r--  => Program interpreter
 [02] 0x120000000 -> 0x120000ECA r-x  => Loadable segment
 [03] 0x120010ED0 -> 0x120011510 rwx  => Loadable segment
 [04] 0x120010ED8 -> 0x120011038 rw-  => Dynamic linking info
 [05] 0x1200001A8 -> 0x1200001C0 r--  => Auxiliary information

 [Program header table .::. SHT correlation]
 [Object fake_aout]

 [*] SHT is not stripped

 [00] PT_PHDR
 [01] PT_INTERP         .interp
 [02] PT_LOAD           .interp .note.netbsd.ident .hash .dynsym .dynstr
                        .rela.dyn .rela.plt .init .text .fini .rodata
 [03] PT_LOAD           .data .eh_frame .dynamic .ctors .dtors .jcr .plt
                        .got .sdata .sbss .bss rel.o.text rel.o.sdata
                        rel.o.rodata.str1.1 .alt.plt.prolog .alt.plt
                        .alt.got rel.o.got
 [04] PT_DYNAMIC        .dynamic
 [05] PT_NOTE           .note.netbsd.ident

 [*] Object fake_aout unloaded

 ========= END DUMP 23 =========


	Les segments sont étendus comme il faut. On le voit à la
	corrélation entre SHT et PHT : toutes les bornes sont correctes.
	La section .alt.plt.prolog est là pour implémenter ALTPLTv2 sous
	ALPHA. Ceci pourra patcher à la volée les octets de la première
	entrée ALTPLT avec ceux de la première entrée PLT la première
	fois que l'entrée ALTPLT sera appelée (quand on appelera une
	fonction originale à partir d'une fonction de détournement la
	première fois).

	Quand nous avons découvert comment faire ALTPLTv3 (sans une ligne
	d'assembleur), la .alt.plt.prolog est devenue une section de
	bourrage pour que GOT et ALTGOT soit bien aligné sur une certaine
	taille qui est nécessaire pour installer ALTPLT à cause de
	l'encodage des instruction ALPHA pour un saut indirect du flux de
	contrôle.



---[ D. Technique EXTPLT : post-liaison de fonctions inconnues


	Cette technique est l'une des ameliorations majeures dans la nouvelle
	version d'ELFsh. Elle fonctionne sur les fichiers ET_EXEC et ET_DYN,
	inclus quand l'injection est faite directement en mémoire. EXTPLT
	consiste à ajouter une nouvelle section (.elfsh.extplt) pour que
	nous puissions ajouter des entrées pour les nouvelles fonctions.

	Quand on couple l'extension par copie de .rel.plt, .got,
	.dynsym, et .dynstr, cela permet de placer des entrées de
	relocation qui correspondent aux besoin des nouveaux couples
	ALTPLT/ALTGOT. Regardons les informations de relocation
	additionnelles en utilisant la commande elfsh -r.

	Tout d'abord, regardons la table de relocation originale du
	binaire :

 
 ========= BEGIN DUMP 24 =========

 [*] Object ./a.out has been loaded (O_RDONLY) 

 [RELOCATION TABLES]
 [Object ./a.out]

 {Section .rel.dyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .rel.plt} 
 [000] R_386_JMP_SLOT  0x08049860 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x08049864 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x08049868 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804986C sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x08049870 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x08049874 sym[007] : free             
 [006] R_386_JMP_SLOT  0x08049878 sym[009] : read             

 [*] Object ./testsuite/etrel_inject/etrel_original/a.out unloaded 
	  
 ========= END DUMP 24 =========


	Regardons mainteant la table modifiée :


 ========= BEGIN DUMP 25 =========
	  
 [*] Object fake_aout has been loaded (O_RDONLY) 

 [RELOCATION TABLES]
 [Object ./fake_aout]

 {Section .rel.dyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .rel.plt} 
 [000] R_386_JMP_SLOT  0x0804A8A0 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x0804A8A4 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x0804A8A8 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804A8AC sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x0804A8B0 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x0804A8B4 sym[007] : free             
 [006] R_386_JMP_SLOT  0x0804A8B8 sym[009] : read             

 {Section .elfsh.reldyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .elfsh.relplt} 
 [000] R_386_JMP_SLOT  0x0804A8A0 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x0804A8A4 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x0804A8A8 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804A8AC sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x0804A8B0 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x0804A8B4 sym[007] : free             
 [006] R_386_JMP_SLOT  0x0804A8B8 sym[009] : read             
 [007] R_386_JMP_SLOT  0x0804A8BC sym[011] : _IO_putc         
 [008] R_386_JMP_SLOT  0x0804A8C0 sym[012] : write            

 [*] Object fake_aout unloaded 

 =========  END DUMP 25 =========

	Comme vous le voyez, les fonctions _IO_putc (nom interne de
	putchar) et write ont été utilisée dans l'objet injecté. Nous
	avons du les insérer dans le binaire hôte pour que le binaire
	final puisse fonctionner.

	La section .elfsh.relplt est copiée à partir de la section
	.rel.plt mais avec une taille double pour avoir de la place pour
	des entrées additionnelles. Même si nous n'étendons qu'une des
	table de relocation, les deux doivent être copiées, parce que sur
	les fichier ET_DYN, le rtld reclame que les deux tables soient
	adjacentes en mémoire, nous ne pouvons donc pas juste copier
	.rel.plt mais avons aussi besoin de .rel.dyn (ou .rel.got) juste
	avant la copie de .rel.plt. C'est pourquoi vous pouvez voir
	.elfsh.reldyn et .elfsh.relplt .

	Quand on a besoin de plus de symboles, d'autres sections sont
	déplacées après le BSS, incluant .dynsym et .dynstr.


---[ E. Algorithmes compatibles IA32, SPARC32/64, ALPHA64, MIPS32


	Introduisons maintenant les détails des algorithmes des
	techniques montrées dans les exemples des paragraphes précédents.
	Nous couvrons ici tous les pseudos algorithmes pour la
	redirection ELF. Les algorithmes détaillés sur le déboguage plus
	contraint sont donné à la fin de la partie suivante.

	Puisque les techniques ALTPLT et ALTGOT sont si complémentaires,
	nous les avons implémentées dans un seul algorithme que nous
	donnons ici. Il n'y a aucune condition sur l'architecture SPARC
	puisque c'est l'architecture par défaut dans la liste.

	L'algorithme principal de ALTPLTv3 / ALTGOT (libelfsh/altplt.c)
	se trouve dans elfsh_build_plt() et elfsh_relink_plt() et est
	comme suit.

	Il pourrait probablement être nettoyé si le code était remplacé
	par des morceaux dédiés aux architectures mais ça dupliquerait du
	code, nous l'avons donc laissé comme suit :

	  Algorithme Multiarchitecture ALTPLT / ALTGOT
	 +--------------------------------------------+

	  0/ IF [ ARCH = MIPS ET PLT n'est pas trouvé AND
                  Le fichier est dynamique ]
	     [
		- récupère l'adresse de base de la section .text
		- Trouve la signature d'opcode MIPS pour le PLT embarqué
		  à l'intérieur du PLT
		- Modifier le SHT pour inclure l'en-tête de la section PLT
	     ]

	  1/ SWITCH sur l'architecture ELF
	  [
             MIPS:
		* Insère la section .elfsh.gotprolog
		* Insère la section .elfsh.padgot
	     ALPHA:
	        * Insère la section.elfsh.pltprolog
	     DEFAULT:
	        * Insère la section.elfsh.altplt (copie du .plt)
	  ]

	  2/ IF [ ARCH est (MIPS ou ALPHA ou IA32) ]
	  [
		* Insère la section .elfsh.altgot (copie du .got)
	  ]

	  3/ POUR CHAQUE ENTRÉE (ALT)PLT :
	  [
		IF [ PREMIÈRE entrée PLT ]
		[
		   IF [ARCH est MIPS ]
		   [
			* Insère des paires d'instructions ld/st dans
			  .elfsh.gotprolog pour copier les adresses de
			  variables externes placé dans GOT par le RTLD
			  dans la section ALTGOT. Voir le gestionnaire
			  d'altplt MIPS dans libelfsh/mips32.c
		   ]
		   ELSE IF [ ARCH est IA32 ]
		   [
			* Réencode la première entrée PLT en utilisant la
			  différence d'adresse GOT - ALTGOT (pour nous
			  replacer dans ALTGOT au lieu de GOT)
		   ]
		]
		
		IF [ ARCH est MIPS ]
		   * Injecte le symbole OLD sur l'entrée PLT courante
		ELSE
		   * Injecte le symbole OLD sur l'entrée ALTPLT courante

		IF [ ARCH est ALPHA ]
		   * Change l'entrée de relocalisation pointant vers
		     l'entrée courante
		
		IF [ ARCH est IA32 ]
		   * Réencode l'entrée courante du PLT et ALTPLT
	  ]   

	  4/ SWITCH sur l'architecture ELF
	  [
	       MIPS:
	       IA32:
		 * Change l'entrée DT_PLTGOT de l'adresse GOT vers ALTGOT
		 * Change les relocations GOT correspondantes
	       SPARC:
	         * Change l'entrée DT_PLTGOT de l'adresse PLT vers ALTPLT
		 * Change les relocations PLT correspondantes
	  ]


	  Sous MIPS, il n'y a pas de table de relocation dans les
	binaires ET_EXEC. Si nous voulons changer la relocation qui
	fait référence à GOT dans le code MIPS, nous devons chercher
	après un pattern dans le code tel qu'on puisse le modifier avec
	la différence ALTGOT-GOT. Ils sont facilement trouvés puisque le
	patch est toujours sur le même pattern d'instruction suivant :

	  3c1c0000        lui     gp,0x0
	  279c0000        addiu   gp,gp,0

	  Le champ 0 dans ces instructions devrait être changé au moment
	de la liaison quand elles correspondront aux relocations MIPS
	HI16 et LO16. Cependant, cette information n'est pas disponible
	dans une table pour les binaires ET_EXEC, nous avons donc besoin
	de les retrouver dans le code binaire. C'est plus facilement
	faisable sous RISC puisque toutes les instructions font la mêem
	taille, les faux positifs sont donc vraiment improbables. Une
	fois qu'on trouve ces patterns, on les corrige avec la différence
	ALTGOT-GOT dans les champs de la table de relocation. Bien
	sur, nous ne changeront pas TOUTES les références à GOT dans le
	code, puisque ça ne ferait que déplacer la GOT, sans
	détournement. On corrige donc ces références dans les premiers
	0x100 octets du .text et dans .init, .fini, ce qui concerne
	uniqument les références aux entrées GOT réservées (remplies par
	les adresses virtuelles dl-resolve et les adresses de linkmap).
	De cette façon, nous obligeons le code original à utiliser la
	section ALTGOT quand il accès aux entrées réservées (puisqu'elles
	ont été relocalisées à l'exécution dans ALTGOT et pas dans GOT)
	et les entrées GOT originales quand il accès aux entrées des
	fonctions (ont peux alors détourner les fonctions en modifiant la
	GOT).


	  Algorithme EXTPLT
	 +-----------------+

	  L'algorithme EXTPLT rentre bien dans l'algorithme précédent.
	Nous avons juste besoin d'ajouter deux étapes dans l'algo
	précédent :

	  Étape 2bis : Insèrer la section EXTPLT (copie de PLT) sur les
	architectures supportées.

	  Étape 5    : Faire une copie miroir (et étendue) de la section
	de liaison dynamique sur les architectures supportées. Regardons
	un peut plus en détail l'algorithme implémenté dans
	libelfsh/extplt.c.

	  * Copie les sections .rel.got (.rel.dyn) et .rel.plt après le
	BSS, dans une section de taille double. Ces deux sections
	doivent rester adjacentes en mémoire pour que EXTPLT
	fonctionne aussi sur les objet ET_DYN.

	  * Mettre à jours les entrées DT_REL et DT_JUMPREL dans .dynamic

	  * Copier les sections .dunsym et .dynstr avec une taille double.

	  * Mettre à jours les entrées DT_SUMTAB e tDT_STRTAB dans .dynamic

	  Une fois que ces opérations sont faites, nous avons assez de
	place dans toutes ces sections orientées liaison dynamique et
	nous pouvons y ajouter à la demande des symboles dynamiques, des
	noms de symboles, et des entrées de relocalisation nécessaires
	pour ajouter des entrées PLT supplémentaires dans la section
	EXTPLT.

	  Maintenant, chaque fois que nous rencontrons un symbole inconnu
	dans le processus de relocation d'un objet ET_REL dans un
	objet ET_EXEC ou ET_DYN, nous pouvons utiliser l'algorithme
	REQUESTPLT, comme implémenté dans la fonction
	elfsh_request_pltent() du fichier libelfsh/extplt.c file :

	  * Vérifier la place dans les copies des sections EXTPLT, RELPLT,
	  DYNSYM, DYNSTR, et ALTGOT.

	  * Initialiser l'entrée ALTGOT par la nouvelle entrée EXTPLT
	    allouée.

	  * Encoder l'entrée EXTPLT pour utiliser l'entrée ALTGOT.

	  * Insèrer une entrée de relocation dans .elfsh.relplt pour
	    la nouvelle entrée ALTGOT.

	  * Ajouter la taille de l'entrée de relocation à la valeur de
	    l'entrée DT_PLTRELSZ dans la section .dynamic.

	  * Insèrer le symbole manquant dans .elfsh.dynsym avec le nom
	    inséré dans la section .elfsh.dynstr.

	  * Ajouter la longueur du nom de symbole à la valeur de l'entrée
	    DT_STRSZ dans la section .dynamic.

	  Cet algorithme est appelé à partir de l'algorithme  principal
	d'injection et de relocation ET_REL chaque fois que l'objet
	ET_REL utilise une fonction inconnue dont le symbole n'est pas
	présent dans le programme hôte. Le nouvel algorithme d'injection
	ET_REL est donné à la fin de la partie sur le déboguage contraint
	de l'article.


	  ALgorithme CFLOW
	 +-----------------+

	 Cette technique est implémentée en utilisant des morceaux dédiés
	aux architectures, mais l'algorithme global est le même pour
	toutes les architectures :

	 - Créer la section .elfsh.hooks (une seule fois)

	 - Trouver le nombre d'octets aligné sur la taille de l'instruction :
		* avec libasm sous IA32
		* manuellement sur machine RISC

	 - Insèrer les entrées HOOK à la demande (voir le dump CFLOW pour le format)

	 - Insèrer JMP vers l'entrée hook dans le prologue de la fonction détournée.

	 - Aligner le JUMP sur la taille d'instruction avec des nop dans le prologue détourné.

	 - Insèrer les symboles hook_funcname et old_funcname dans
	   l'entrée hook pour être capable de rappeler la fonction
	   originale.

	 Cette technique passe Pax puisqu'elle n'a besoin d'aucune étape
	de restauration d'octets pendant l'exécution. Nous pouvons
	détourner l'adresse de notre choix en utilisant la technqiue
	CFLOW, cependant, exécuter les octets originaux dans l'entrée
	hook au lieu de leur place originale ne fonctionnera pas si on
	place le détournement sur une instruction de branchement relatif.
	En fait, les branchements relatifs seront résolu vers une
	mauvaise adresse virtuelle nous nous exécutons leurs opcode au
	mauvais endroit (dasn le .elfsh.hooks au lieu de leur place
	originale) dans le processus. Souvenez-vous en quand vous placez
	des détournements CFLOW : ils ne sont pas fait pours détourner
	les instructions de branchements conditionnels.



-------[ V. Déboguage contraint


	Dans les environnements actuels, les binaires endurcis sont
	souvent du type ET_DYN. Nous devons supporter ce type d'injection
	puisqu'il permet des modifications de librairies aussi puissantes
	que les modifications d'exécutables. De plus, certaines
	distributions sont fournies avec un ensemble de binaires par
	défaut compilé en ET_DYN, comme les gentoo endurcies.

	Une autre amélioration que nous voulions faire est la
	relocation ET_REL en mémoire. L'algorithme pour celle-ci est
	le même que pour l'injection sur disque, mais cette fois le
	disque n'est pas changé, ça réduit donc les traces comme dans
	[12]. On pense que ce type d'injection peut être utilisé dans les
	exploits et le backdooring de processus sans toucher au disque
	dur. Diabolique non ?!

	Nous sommes au courant d'une autre implémentation de l'injection
	ET_REL en mémoire [10]. La notre supporte plus d'architectures et
	se couple avec la technique EXTPLT directement en mémoire, ce qui
	n'a encore jamais été implémenté à notre connaissance.

	Une dernière technique que nous voulions implémenter concerne
	l'extension et le déboguage d'exécutables statiques. Nous avons
	développé cette nouvelle technique que nous avons appelé
	l'algorithme EXTSTATIC. Elle permet l'injection statique en
	utilisant libc.a quand une fonction ou du code est manquant. Le
	même algorithme que celui de l'injection ET_REL est utilisé sauf
	que plus d'un fichier relogeable pris de libc.a est injecté à la
	fois en utilisant un algorithme de dépendances récursives.


---[ A. Relocation ET_REL en mémoire


	Vu qu'on veut que l'utilisateur puisse fournir son propre gestionnaire
	de breakpoints, nous permettons un mapping direct d'un objet
	ET_REL en mémoire. Pour cela, nous utilisons des zones mmap
	supplémentaire, en faisant toujours attention à ne pas casser
	PaX : nous ne mappons aucune zone à la fois en exécution ET en
	écriture.

	Dans e2dbg, les breakpoints peuvent être implémentés de deux
	façons. Soit un opcode dépendant de l'architecture (comme 0xCC
	sous IA32) est utilisé sur l'adresse désirée, ou alors les
	primitives CFLOW/ALTPLT peuvent être utilisées à l'exécution.
	Dans le second cas, l'appel système mprotect doit être utilisé
	pour pouvoir modifier le code à l'exécution. Cependant, nous
	pourrons nous passer de mrprotect bientôt pour l'injection à la
	volée quand la technique CFLOW sera assez forte pour respecter
	Pax en static et à l'exécution.

	Jetons un coup d'oeil à un binaire qui n'utilise que printf et
	puts pour mieux comprendre ces concepts :


 ========= BEGIN DUMP 26 =========

 elfsh@WTH $ ./a.out
 [host] main argc 1
 [host] argv[0] is : ./a.out

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !
 ========= END DUMP 26 =========


	Nous utilisons un petit script elfsh comme e2dbg pour créer un
	autre fichier avec le débogueur injecté dedans, en utilisant les
	techniques elfsh habituelles. Jetons-y un coup d'oeil :



 ========= BEGIN DUMP 27 =========	  
 elfsh@WTH $ cat inject_e2dbg.esh
 #!../../vm/elfsh
 load a.out
 set 1.dynamic[08].val 0x2			# entrée pour DT_DEBUG
 set 1.dynamic[08].tag DT_NEEDED
 redir main e2dbg_run
 save a.out_e2dbg
 ========= END DUMP 27 =========


	Nous exécutons ensuite le binaire modifié.


 ========= BEGIN DUMP 28 =========

 elfsh@WTH $ ./aout_e2dbg


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 [*] Sun Jul 31 16:24:00 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libelfsh.so loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) quit

         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !

 elfsh@WTH $

========= END DUMP 28 =========


	Ok, c'était facile. Et si on voulais faire quelque chose de plus
	intéressant comme de l'injection ET_REL en mémoire ? Nous allons
	utiliser la commande profile pour découvrir la fonctionnalité
	d'auto-profiling [NDT : ~ auto-description] d'e2dbg. Cette
	commande est toujours utile pour en apprendre plus sur le
	débogueur lui-même, et pour des problèmes de déboguage interne
	qui peuvent apparaitre pendant le développement.

	Notre léger pattern matching d'appel de fonctions rend la sortie
	plus compréhensible qu'un affichage brute des informations de
	profiling et a prix peu d'heures pour l'implémenter en utilisant
	les macros ELFSH_PROFILE_{OUT,ERR,ROUT} dans libelfsh-internals.h et
	libelfsh/error.c.

	Nous allons aussi afficher la liste de linkmap. Les premiers champs
	de la linkmap sont indépendant de l'OS. Il y a beaucoup d'autres champs
	internes que nous n'avons pas affiché mais beaucoup d'informations
	peuvent être récoltée à partir de là.

	Voici le truc en action :


 ========= BEGIN DUMP 29 =========

 elfsh@WTH $ ./a.out_e2dbg

         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 16:12:48 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libelfsh.so loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) linkmap 

 .::. Linkmap entries .::.
 [01] addr : 0x00000000 dyn : 0x080497D4 -
 [02] addr : 0x00000000 dyn : 0xFFFFE590 -
 [03] addr : 0xB7E73000 dyn : 0xB7F9AD3C - /lib/tls/libc.so.6
 [04] addr : 0xB7E26000 dyn : 0xB7E6F01C - ./ibc.so.6
 [05] addr : 0xB7FB9000 dyn : 0xB7FCFF14 - /lib/ld-linux.so.2
 [06] addr : 0xB7DF3000 dyn : 0xB7E24018 - /lib/libelfsh.so
 [07] addr : 0xB7DC6000 dyn : 0xB7DEE46C - /lib/libreadline.so.5
 [08] addr : 0xB7DC2000 dyn : 0xB7DC5BB4 - /lib/libtermcap.so.2
 [09] addr : 0xB7DBE000 dyn : 0xB7DC0EEC - /lib/libdl.so.2
 [10] addr : 0xB7D7C000 dyn : 0xB7DBB1C0 - /lib/libncurses.so.5

 (e2dbg-0.65) list

 .::. Working files .::.
 [001] Sun Jul 31 16:24:00 2005  D ID: 9 /lib/libncurses.so.5
 [002] Sun Jul 31 16:24:00 2005  D ID: 8 /lib/libdl.so.2
 [003] Sun Jul 31 16:24:00 2005  D ID: 7 /lib/libtermcap.so.2
 [004] Sun Jul 31 16:24:00 2005  D ID: 6 /lib/libreadline.so.5
 [005] Sun Jul 31 16:24:00 2005  D ID: 5 /lib/libelfsh.so
 [006] Sun Jul 31 16:24:00 2005  D ID: 4 /lib/ld-linux.so.2
 [007] Sun Jul 31 16:24:00 2005  D ID: 3 ./ibc.so.6
 [008] Sun Jul 31 16:24:00 2005  D ID: 2 /lib/tls/libc.so.6
 [009] Sun Jul 31 16:24:00 2005 *D ID: 1 ./a.out_e2dbg

 .::. ELFsh modules .::.
 [*] No loaded module

 (e2dbg-0.65) source ./etrelmem.esh

 ~load myputs.o

 [*] Sun Jul 31 16:13:32 2005 - New object myputs.o loaded

 [!!] Loaded file is not the linkmap, switching to STATIC mode

 ~switch 1

 [*] Switched on object 1 (./a.out_e2dbg)

 ~mode dynamic

 [*] e2dbg is now in DYNAMIC mode

 ~reladd 1 10

 [*] ET_REL myputs.o injected succesfully in ET_EXEC ./a.out_e2dbg

 ~profile
         .:: Profiling enable

 + <vm_print_actual@loop.c:38>
 ~redir puts myputs
 + <vm_implicit@implicit.c:91>
 + <cmd_hijack@fcthijack.c:19>
 + <elfsh_get_metasym_by_name@sym_common.c:283>
 + <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 + <elfsh_get_dynsymtab@dynsym.c:87>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_dynsymbol_name@dynsym.c:17>
 [W]     <elfsh_get_dynsymbol_by_name@dynsym.c:274>      Symbol not found
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --- Last 2 function(s) recalled 12 time(s) ---
 + <elfsh_get_symbol_by_name@symbol.c:236>
 + <elfsh_get_symtab@symbol.c:110>
 + <elfsh_get_symbol_name@symbol.c:20>
 [P] --[ <elfsh_get_symbol_name@symbol.c:20>
 [P] --- Last 1 function(s) recalled 114 time(s) ---
 + <elfsh_hijack_function_by_name@hijack.c:25>
 + <elfsh_setup_hooks@hooks.c:199>
 + <elfsh_get_pagesize@hooks.c:783>
 + <elfsh_get_archtype@hooks.c:624>
 + <elfsh_get_arch@elf.c:179>
 + <elfsh_copy_plt@altplt.c:525>
 + <elfsh_static_file@elf.c:491>
 + <elfsh_get_segment_by_type@pht.c:215>
 + <elfsh_get_pht@pht.c:364>
 + <elfsh_get_segment_type@pht.c:174>
 [P] --[ <elfsh_get_segment_type@pht.c:174>
 [P] --- Last 1 function(s) recalled 4 time(s) ---
 + <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_relink_plt@altplt.c:121>
 + <elfsh_get_archtype@hooks.c:624>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_relink_plt@altplt.c:121>
 [P] --[ <elfsh_get_archtype@hooks.c:624>
 [P] --- Last 3 function(s) recalled 1 time(s) ---
 + <elfsh_get_elftype@hooks.c:662>
 + <elfsh_get_objtype@elf.c:204>
 + <elfsh_get_ostype@hooks.c:709>
 + <elfsh_get_real_ostype@hooks.c:679>
 + <elfsh_get_interp@interp.c:41>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_section_by_name@section.c:168>
 + <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_symbol_by_name@symbol.c:236>
 + <elfsh_get_symtab@symbol.c:110>
 + <elfsh_get_symbol_name@symbol.c:20>
 [W]     <elfsh_get_symbol_by_name@symbol.c:253>         Symbol not found
 [P] --[ <elfsh_get_symbol_name@symbol.c:20>
 [P] --- Last 1 function(s) recalled 114 time(s) ---
 + <elfsh_is_pltentry@plt.c:73>
 [W]     <elfsh_is_pltentry@plt.c:77>               Invalid NULL parameter
 + <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 + <elfsh_get_dynsymtab@dynsym.c:87>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --[ <elfsh_is_pltentry@plt.c:73>
 [P] --[ <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 [P] --[ <elfsh_get_dynsymtab@dynsym.c:87>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --- Last 5 function(s) recalled 1 time(s) ---
 + <elfsh_get_plt@plt.c:16>
 + <elfsh_is_plt@plt.c:49>
 + <elfsh_get_section_name@sht.c:474>
 + <elfsh_is_altplt@plt.c:62>
 [P] --[ <elfsh_is_plt@plt.c:49>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_is_altplt@plt.c:62>
 [P] --- Last 3 function(s) recalled 3 time(s) ---
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_is_plt@plt.c:49>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_is_altplt@plt.c:62>
 [P] --[ <elfsh_get_anonymous_section@section.c:334>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 5 function(s) recalled 44 time(s) ---
 + <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_hijack_plt_ia32@ia32.c:258>
 + <elfsh_get_foffset_from_vaddr@raw.c:85>
 + <elfsh_get_pltentsz@plt.c:94>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_hijack_plt_ia32@ia32.c:258>
 [P] --[ <elfsh_get_foffset_from_vaddr@raw.c:85>
 [P] --[ <elfsh_get_pltentsz@plt.c:94>
 [P] --- Last 4 function(s) recalled 1 time(s) ---
 + <elfsh_munprotect@runtime.c:97>
 + <elfsh_get_parent_section@section.c:380>
 + <elfsh_get_parent_segment@pht.c:304>
 + <elfsh_segment_is_readable@pht.c:14>
 + <elfsh_segment_is_writable@pht.c:21>
 + <elfsh_segment_is_executable@pht.c:28>
 + <elfsh_raw_write@raw.c:22>
 + <elfsh_get_parent_section_by_foffset@section.c:416>
 + <elfsh_get_sht@sht.c:159>
 + <elfsh_get_section_type@sht.c:887>
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 + <elfsh_raw_write@raw.c:22>
 + <elfsh_get_parent_section_by_foffset@section.c:416>
 + <elfsh_get_sht@sht.c:159>
 + <elfsh_get_section_type@sht.c:887>
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 + <elfsh_get_pltentsz@plt.c:94>
 + <elfsh_get_arch@elf.c:179>
 + <elfsh_mprotect@runtime.c:135>

 [*] Function puts redirected to addr 0xB7FB6000 <myputs>

 + <vm_print_actual@loop.c:38>
 ~profile
 + <vm_implicit@implicit.c:91>
         .:: Profiling disable


 [*] ./etrelmem.esh sourcing -OK-

 (e2dbg-0.65) continue


         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test
 Hijacked puts !!! arg = First_puts
 First_puts
 Second_printf test
 Hijacked puts !!! arg = Second_puts
 Second_puts
 Hijacked puts !!! arg = LEGIT FUNC
 LEGIT FUNC
 legit func (test) !
 elfsh@WTH $

 ========= END DUMP 29 =========


	Vraiment cool. Nous avons détourner 2 fonctions (puts et
	legit_func) en utilisant 2 techniques différentes (ALTPLT et
	CFLOW). Pour ceci, nous n'avons pas eu besoin d'injecter un
	fichier ET_REL additionnel dans l'hôte ET_REL, mais nous avons
	directement injecté le module de détournement dans la mémoire en
	utilisant mmap.

	Nous aurions pu afficher la SHT et la PHT juste après l'injection
	ET_REL en mémoire. Nous gardons trace de tous les mappages quand
	nous injectons ce genre d'objet relogeable, pour pouvoir les
	démapper et les remapper plus tard :


 ========= BEGIN DUMP 30 =========
	  
 (e2dbg-0.65) s

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object ./a.out_e2dbg]

 [000] 0x00000000 -------                           foff:00000 size:00308
 [001] 0x08045134 a-x---- .elfsh.hooks              foff:00308 size:00015
 [002] 0x08046134 a-x---- .elfsh.extplt             foff:04404 size:00032
 [003] 0x08047134 a-x---- .elfsh.altplt             foff:08500 size:04096
 [004] 0x08048134 a------ .interp                   foff:12596 size:00019
 [005] 0x08048148 a------ .note.ABI-tag             foff:12616 size:00032
 [006] 0x08048168 a------ .hash                     foff:12648 size:00064
 [007] 0x080481A8 a------ .dynsym                   foff:12712 size:00176
 [008] 0x08048258 a------ .dynstr                   foff:12888 size:00112
 [009] 0x080482C8 a------ .gnu.version              foff:13000 size:00022
 [010] 0x080482E0 a------ .gnu.version_r            foff:13024 size:00032
 [011] 0x08048300 a------ .rel.dyn                  foff:13056 size:00016
 [012] 0x08048310 a------ .rel.plt                  foff:13072 size:00056
 [013] 0x08048348 a-x---- .init                     foff:13128 size:00023
 [014] 0x08048360 a-x---- .plt                      foff:13152 size:00128
 [015] 0x08048400 a-x---- .text                     foff:13312 size:00800
 [016] 0x08048720 a-x---- .fini                     foff:14112 size:00027
 [017] 0x0804873C a------ .rodata                   foff:14140 size:00185
 [018] 0x080487F8 a------ .eh_frame                 foff:14328 size:00004
 [019] 0x080497FC aw----- .ctors                    foff:14332 size:00008
 [020] 0x08049804 aw----- .dtors                    foff:14340 size:00008
 [021] 0x0804980C aw----- .jcr                      foff:14348 size:00004
 [022] 0x08049810 aw----- .dynamic                  foff:14352 size:00200
 [023] 0x080498D8 aw----- .got                      foff:14552 size:00004
 [024] 0x080498DC aw----- .got.plt                  foff:14556 size:00040
 [025] 0x08049904 aw----- .data                     foff:14596 size:00012
 [026] 0x08049910 aw----- .bss                      foff:14608 size:00008
 [027] 0x08049918 aw----- .elfsh.altgot             foff:14616 size:00044
 [028] 0x08049968 aw----- .elfsh.dynsym             foff:14696 size:00192
 [029] 0x08049AC8 aw----- .elfsh.dynstr             foff:15048 size:00122
 [030] 0x08049BA8 aw----- .elfsh.reldyn             foff:15272 size:00016
 [031] 0x08049BB8 aw----- .elfsh.relplt             foff:15288 size:00064
 [032] 0x00000000 ------- .comment                  foff:15400 size:00665
 [033] 0x00000000 ------- .debug_aranges            foff:16072 size:00120
 [034] 0x00000000 ------- .debug_pubnames           foff:16192 size:00042
 [035] 0x00000000 ------- .debug_info               foff:16234 size:06904
 [036] 0x00000000 ------- .debug_abbrev             foff:23138 size:00503
 [037] 0x00000000 ------- .debug_line               foff:23641 size:00967
 [038] 0x00000000 ------- .debug_frame              foff:24608 size:00076
 [039] 0x00000000 ---ms-- .debug_str                foff:24684 size:08075
 [040] 0x00000000 ------- .debug_macinfo            foff:32759 size:29295
 [041] 0x00000000 ------- .shstrtab                 foff:62054 size:00496
 [042] 0x00000000 ------- .symtab                   foff:64473 size:02256
 [043] 0x00000000 ------- .strtab                   foff:66729 size:01665
 [044] 0x40019000 aw----- myputs.o.bss              foff:68394 size:04096
 [045] 0x00000000 ------- .elfsh.rpht               foff:72493 size:04096
 [046] 0x4001A000 a-x---- myputs.o.text             foff:76589 size:04096
 [047] 0x4001B000 a--ms-- myputs.o.rodata.str1.1    foff:80685 size:04096

 (e2dbg-0.65) p

 [Program Header Table .::. PHT]
 [Object ./a.out_e2dbg]

 [00] 0x08045034 -> 0x08045134 r-x memsz(00256) filesz(00256)
 [01] 0x08048134 -> 0x08048147 r-- memsz(00019) filesz(00019)
 [02] 0x08045000 -> 0x080487FC r-x memsz(14332) filesz(14332)
 [03] 0x080497FC -> 0x08049C30 rw- memsz(01076) filesz(01068)
 [04] 0x08049810 -> 0x080498D8 rw- memsz(00200) filesz(00200)
 [05] 0x08048148 -> 0x08048168 r-- memsz(00032) filesz(00032)
 [06] 0x00000000 -> 0x00000000 rw- memsz(00000) filesz(00000)
 [07] 0x00000000 -> 0x00000000 --- memsz(00000) filesz(00000)

 [SHT correlation]
 [Object ./a.out_e2dbg]

 [*] SHT is not stripped 
 
 [00] PT_PHDR    
 [01] PT_INTERP         .interp 
 [02] PT_LOAD           .elfsh.hooks .elfsh.extplt .elfsh.altplt .interp 
			.note.ABI-tag .hash .dynsym .dynstr .gnu.version 
			.gnu.version_r .rel.dyn .rel.plt .init .plt 
			.text .fini .rodata .eh_frame 
 [03] PT_LOAD           .ctors .dtors .jcr .dynamic .got .got.plt .data 
			.bss .elfsh.altgot .elfsh.dynsym .elfsh.dynstr 
			.elfsh.reldyn .elfsh.relplt 
 [04] PT_DYNAMIC        .dynamic 
 [05] PT_NOTE           .note.ABI-tag 
 [06] PT_GNU_STACK 
 [07] PT_PAX_FLAGS 

 [Runtime Program Header Table .::. RPHT]
 [Object ./a.out_e2dbg]

 [00] 0x40019000 -> 0x4001A000 rw- memsz(4096) filesz(4096)
 [01] 0x4001A000 -> 0x4001B000 r-x memsz(4096) filesz(4096)
 [02] 0x4001B000 -> 0x4001C000 r-x memsz(4096) filesz(4096)

 [SHT correlation]
 [Object ./a.out_e2dbg]

 [*] SHT is not stripped 
 
 [00] PT_LOAD           myputs.o.bss 
 [01] PT_LOAD           myputs.o.text 
 [02] PT_LOAD           myputs.o.rodata.str1.1 

 (e2dbg-0.65) 


 ========= BEGIN DUMP 30 =========



	Notre algorithme n'est pas vraiment optimisé puisqu'il alloue un
	nouveau PT_LOAD par section. Ici, nous avons créer une table RPHT
	(Runtime PHT) qui gère la liste de toutes les pages injectées à
	l'exécution. Cette table n'a pas d'existance légale dans le
	fichier ELF, mais elle nous évite d'étendre la PHT réelle avec
	des zones mémoires additionnelles. La technique ne casse pas PaX
	puisque toutes les zones sont allouées en utilisant les droits
	strictement nécessaires. Cependant, si vous voulez rediriger une
	fonction existante vers une fonction nouvellement ajoutée de
	myputs.o, vous aurez besoin de changer un peu de code à
	l'exécution, et donc il devient nécessaire de désactiver
	l'options mrprotect pour éviter de casser PaX.


---[ B. Relocation ET_REL dans ET_DYN


	Nous avons porté l'injection ET_REL et la technique EXTPLT pour
	les fichiers ET_DYN. La plus grosse différence est que les
	fichiers ET_DYN ont un espace d'adressage relatif sur le disque.
	Bien sur, les binaires strippes n'ont pas d'effet nefaste sur nos
	algorithmes et nous n'avons pas besoin d'informations
	optionnelles comme la section debug ou autre chose (ça peut
	sembler évident, mais des gens nous posent vraiment la question).

	Voyons ce qu'il se passe sur ce fichier ET_DYN hôte :


 ========= BEGIN DUMP 31 =========

 elfsh@WTH $ file main
 main: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), 
 stripped

 elfsh@WTH $ ./main
 0x800008c8 main(argc=0xbfa238d0, argv=0xbfa2387c, envp=0xbfa23878, 
	         auxv=0xbfa23874) __guard=0xb7ef4148
 ssp-all (Stack) Triggering an overflow by copying [20] of data into [10]
 of space
 main: stack smashing attack in function main()
 Aborted

 elfsh@WTH $ ./main AAAAA
 0x800008c8 main(argc=0xbf898e40, argv=0xbf898dec, envp=0xbf898de8, 
	         auxv=0xbf898de4) __guard=0xb7f6a148
 ssp-all (Stack) Copying [5] of data into [10] of space

 elfsh@WTH $ ./main AAAAAAAAAAAAAAAAAAAAAAAAAAA
 0x800008c8 main(argc=0xbfd3c8e0, argv=0xbfd3c88c, envp=0xbfd3c888, 
                 auxv=0xbfd3c884) __guard=0xb7f0b148
 ssp-all (Stack) Copying [27] of data into [10] of space
 main: stack smashing attack in function main()
 Aborted

 ========= END DUMP 31 =========


	Juste pour le fun, nous avons décidé d'étudier en priorité les
	binaires endurcis de gentoo [11]. Ceux-ci sont fournis avec PIE
	(Position independant Executable) et SSP (Stack Smashing
	Protection) incorporés. Ça ne change pas une ligne de notre
	algorithme. Voici quelques tests fait sur un binaire protégé
	contre les débordement dans la pile avec un overflow dans le
	premier paramètre, déclanchant le gestionnaire de débordement de
	pile. Nous allons rediriger ce gestionnaire pour montrer qu'il
	s'agit d'une fonction habituelle qui utilise les méchanismes PLT
	classiques.

	Voici le code que nous allons injecter :


 ========= BEGIN DUMP 32 =========

 elfsh@WTH $ cat simple.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     fake_main(int argc, char **argv)
 {
   old_printf("I am the main function, I have %d argc and my "
  	      "argv is %08X yupeelala \n",
              argc, argv); 

   write(1, "fake_main is calling write ! \n", 30);

   old_main(argc, argv);

   return (0);
 }

 char*   fake_strcpy(char *dst, char *src)
 {
   printf("The fucker wants to copy %s at address %08X \n", src, dst);
   return ((char *) old_strcpy(dst, src));
 }

 void    fake_stack_smash_handler(char func[], int damaged)
 {
   static int i = 0;
   printf("calling printf from stack smashing handler %u\n", i++);
   if (i>3)
     old___stack_smash_handler(func, damaged);
   else
     printf("Same player play again [damaged = %08X] \n", damaged);
   printf("A second (%d) printf from the handler \n", 2);
 }

 int fake_libc_start_main(void *one, void *two, void *three, void *four, 
                          void *five, void *six, void *seven)
 {
   static int i = 0;

   old_printf("fake_libc_start_main \n");
   printf("start_main has been run %u \n", i++);
   return (old___libc_start_main(one, two, three, four, 
			         five, six, seven));
 }

 ========= END DUMP 32 =========


	Le script elfsh qui permet les modifications est le suivant :


 ========= BEGIN DUMP 33 =========

 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 load main
 load simple.o

 reladd 1 2

 redir main fake_main
 redir __stack_smash_handler fake_stack_smash_handler
 redir __libc_start_main fake_libc_start_main
 redir strcpy fake_strcpy

 save fake_main

 quit

 ========= END DUMP 33 =========


	Regardons le en actions !


 ========= BEGIN DUMP 34 =========
 elfsh@WTH $ ./relinject.esh


         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 ~load main

 [*] Sun Jul 31 17:24:20 2005 - New object main loaded

 ~load simple.o

 [*] Sun Jul 31 17:24:20 2005 - New object simple.o loaded

 ~reladd 1 2

 [*] ET_REL simple.o injected succesfully in ET_DYN main

 ~redir main fake_main

 [*] Function main redirected to addr 0x00005154 <fake_main>

 ~redir __stack_smash_handler fake_stack_smash_handler

 [*] Function __stack_smash_handler redirected to addr 
     0x00005203 <fake_stack_smash_handler>

 ~redir __libc_start_main fake_libc_start_main

 [*] Function __libc_start_main redirected to addr 
     0x00005281 <fake_libc_start_main>

 ~redir strcpy fake_strcpy

 [*] Function strcpy redirected to addr 0x000051BD <fake_strcpy>

 ~save fake_main

 [*] Object fake_main saved successfully

 ~quit

 [*] Unloading object 1 (simple.o)
 [*] Unloading object 2 (main) *
         .:: Bye -:: The ELF shell 0.65
 
 ========= END DUMP 34 =========


	Et quel est le résultat ?


 ========= BEGIN DUMP 35 =========

 elfsh@WTH $ ./fake_main
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 1 argc and my argv is BF9A6F54 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf9a6e80, argv=0xbf9a6e2c, envp=0xbf9a6e28, 
 	        auxv=0xbf9a6e24) __guard=0xb7f78148
 ssp-all (Stack) Triggering an overflow by copying [20] of data into [10]
 of space
 The fucker wants to copy 01234567890123456789 at address BF9A6E50
 calling printf from stack smashing handler 0
 Same player play again [damaged = 39383736]
 A second (2) printf from the handler

 elfsh@WTH $ ./fake_main AAAA
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 2 argc and my argv is BF83A164 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf83a090, argv=0xbf83a03c, envp=0xbf83a038, 
	        auxv=0xbf83a034) __guard=0xb7f09148
 ssp-all (Stack) Copying [4] of data into [10] of space
 The fucker wants to copy AAAA at address BF83A060

 elfsh@WTH $ ./fake_main AAAAAAAAAAAAAAA
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 2 argc and my argv is BF8C7F24 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf8c7e50, argv=0xbf8c7dfc, envp=0xbf8c7df8, 
                 auxv=0xbf8c7df4) __guard=0xb7f97148
 ssp-all (Stack) Copying [15] of data into [10] of space
 The fucker wants to copy AAAAAAAAAAAAAAA at address BF8C7E20

 ========= END DUMP 35 =========


	Aucun problème ici : nous detournons strcpy, main, libc_start_main et
	__stack_smash_handler vers nos propres procédures comme le montre
	la sortie. Nous appelons aussi write qui n'était pas disponible
	dans le binaire original, ce qui montre que EXTPLT fonctionne sur
	les objets ET_DYN, la bonne chose étant que ça marche sans
	modifications.

	Dans la version courante (0.65rc1), il y a cependant une
	limitation sur ET_DYN. Nous devons éviter les variables
	non-initialisées parce que ça pourrait ajouter des entrées dans
	la table de relocation. Ce n'est pas un problème d'en ajouter
	puisque nous copions aussi .rel.got (rel.dyn) dans EXTPLT sous
	ET_DYN, mais ce n'est pas encore implémenté.


---[ C. Extentions d'exécutables statics



	Maintenant, nous aimerions pouvoir déboguer des binaires statics
	de la même manière que pour les dynamiques. Puisque nous ne
	pouvons pas injecter e2dbg en utilisant les dépendances DT_NEEDED
	sur les binaires statiques, l'idée est d'injecter e2dbg comme
	ET_REL dans ET_EXEC puisque c'est possible sur les binaires
	statiques. E2dbg a beaucoup plus de dépendances qu'un simple
	programme rel.c. L'idée étendue est d'injecter la partie
	manquante des librairies statiques quand c'est nécessaire.

	Nous devons résoudre les dépendances à la volée pendant que
	l'injection ET_REL est faite. Pour cela, nous utiliserons un
	simple algorithme récursif sur le code relogeable existant :
	quand un symbole n'est pas trouvé au moment du relogeage, soit
	c'est un symbole old_* et c'est mis en attente de la deuxième
	étape de relogeage (en fait, les symboles old_* apparaissent au
	moment de la redirection, qui est fait après l'injection du
	fichier ET_REL, nous ignorons donc ces symboles dans un premier
	temps), ou le symbole de fonction est vraiment inconnu et nous
	devons ajouter des informations pour que le rtld puisse le
	résoudre quand même.

	Pour permettre de trouver le ET_REL adéquat à injecter, ELFsh
	extrait tous les objets ET_REL à partir d'une librairie statique (.a)
	et ensuite, la résolution est faite en utilisant cet ensemble de
	binaires. La fonctionnalité de workspace d'elfsh est assez utile
	pour ça, quand des sessions sont faites sur plus d'un milier de
	fichier ELF ET_EXEC en même temps (après extraction des modules
	de libc.a et d'autres binaires statique, par exemple).

	Les dépendances circulaires sont résolues en utilisant une
	deuxième étape de relocalisation quand le symbole requis se
	trouve dans un fichier qui sera injecté après le fichier courant.
	La même seconde phase du mechanisme de relocation est utilisée
	quand on doit reloger les objets ET_REL qui utilisent les symboles
	old_*. Puisque les symboles OLD sont injectés au moment de la
	redirection et que les fichiers ET_REL doivent être injectés avant
	(pour que nous puissions utiliser les fonctions de l'objet ET_REL
	comme fonctions de détournement), nous n'avons pas de symboles OLD
	au moment de la relocation. La seconde phase de relocation est alors
	déclanchée au moment de la sauvegarde (pour des modifications sur
	le disque) ou récursivement résolu quand on injecte plusieurs ET_REL
	avec des dépendances circulaires.

	Un problème reste, jusqu'a présent, nous avions un PT_LOAD par
	section injectée, nous atteignons vite plus de 500 PT_LOAD. Ceci
	semble un peu trop pour un ficheir ELF static habituel. Nous
	devons améliorer le méchanisme d'allocation PT_LOAD pour pouvoir
	ajouter de plus grosses extensions à ce genre de binaire hôte.

	Cette technique fournis les mêmes fonctionnalités que EXTPLT mais
	pour les binaires statiques : nous pouvons injecter ce que nous
	voulons (sans se soucier de ce que le fichier hôte contient).

	Donc, voici un plus petit exemple fonctionnel :


 ========= BEGIN DUMP 36 =========

 elfsh@WTH $ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     legit_func(char *str)
 {
   puts("legit func !");
   return (0);
 }

 int main()
 {
   char  *str;
   char  buff[BUFSIZ];
   read(0, buff, BUFSIZ-1);

   puts("First_puts");

   puts("Second_puts");

   fflush(stdout);

   legit_func("test");

   return (0);
 }

 elfsh@WTH $ file a.out
 a.out: ELF 32-bit LSB executable, Intel 80386, statically linked, 
 not stripped

 elfsh@WTH $ ./a.out

 First_puts
 Second_puts
 legit func !

 ========= END DUMP 36 =========


	Le code du fichier source injecté est le suivant :


 ========= BEGIN DUMP 37 =========

 elfsh@WTH $ cat rel2.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <netdb.h>


 int     glvar_testreloc = 42;
 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;


 int     hook_func(char *str)
 {
   int sd;

   printf("hook func %s !\n", str);

   return (old_legit_func(str));
 }


 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;
   int   fd;
   char  name[16];
   void  *a;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   memset(name, 0, 16);

   printf("Trojan injected ET_REL takes control now "
          "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
          str2, str,
          glvar_testreloc,
          glvar_testreloc_bss,
          glvar_testreloc_bss2,
          glvar_testreloc_bss3,
          local);

  free(str2);

  gethostname(name, 15);
  printf("hostname : %s\n", name);

  printf("printf called from puts_troj [%s] \n", str);

  fd = open("/etc/services", 0, O_RDONLY);

  if (fd)
    {
     if ((a = mmap(0, 100, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *) -1)
        {
          perror("mmap");
          close(fd);
          printf("mmap failed : fd: %d\n", fd);
          return (-1);
        }
      printf("-=-=-=-=-=- BEGIN /etc/services %d -=-=-=-=-=\n", fd);
      printf("host : %.60s\n", (char *) a);
      printf("-=-=-=-=-=- END   /etc/services %d -=-=-=-=-=\n", fd);
      printf("mmap succeed fd : %d\n", fd);
      close(fd);
    }


   old_puts(str);
   fflush(stdout);
   return (0);
 }

 ========= END DUMP 37 =========


	Le script load_lib.esh, généré en utilisant un petit script bash,
	ressemble à ça :


 ========= BEGIN DUMP 38 =========

 elfsh@WTH $ head -n 10 load_lib.esh
 #!../../../vm/elfsh
 load libc/init-first.o
 load libc/libc-start.o
 load libc/sysdep.o
 load libc/version.o
 load libc/check_fds.o
 load libc/libc-tls.o
 load libc/elf-init.o
 load libc/dso_handle.o
 load libc/errno.o
 
 ========= END DUMP 38 =========


	Voici le script ELFsh de l'injection :


 ========= BEGIN DUMP 39 =========

 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 exec gcc -g3 -static host.c
 exec gcc -g3 -static rel2.c -c

 load a.out
 load rel2.o

 source ./load_lib.esh

 reladd 1 2

 redir puts puts_troj
 redir legit_func hook_func

 save fake_aout

 quit

 ========= END DUMP 39 =========


	Sortie épurée de l'injection :


 ========= BEGIN DUMP 40 =========
 elfsh@WTH $ ./relinject.esh

         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 ~exec gcc -g3 -static host.c

 [*] Command executed successfully

 ~exec gcc -g3 -static rel2.c -c

 [*] Command executed successfully

 ~load a.out
 [*] Sun Jul 31 16:37:32 2005 - New object a.out loaded

 ~load rel2.o
 [*] Sun Jul 31 16:37:32 2005 - New object rel2.o loaded

 ~source ./load_lib.esh
 ~load libc/init-first.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/init-first.o loaded

 ~load libc/libc-start.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/libc-start.o loaded

 ~load libc/sysdep.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/sysdep.o loaded

 ~load libc/version.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/version.o loaded

 [[... 1414 files later ...]]

 [*] ./load_lib.esh sourcing -OK-

 ~reladd 1 2

 [*] ET_REL rel2.o injected succesfully in ET_EXEC a.out

 ~redir puts puts_troj

 [*] Function puts redirected to addr 0x080B7026 <puts_troj>

 ~redir legit_func hook_func

 [*] Function legit_func redirected to addr 0x080B7000 <hook_func>

 ~save fake_aout

 [*] Object fake_aout saved successfully

 ~quit

 [*] Unloading object 1 (libpthreadnonshared/pthread_atfork.oS)
 [*] Unloading object 2 (libpthread/ptcleanup.o)
 [*] Unloading object 3 (libpthread/pthread_atfork.o)
 [*] Unloading object 4 (libpthread/old_pthread_atfork.o)

 [[... 1416 files later ...]]

         .:: Bye -:: The ELF shell 0.65

 ========= END DUMP 40 =========


	Cela fonctionne-t-il ?


 ========= BEGIN DUMP 41 =========

 elfsh@WTH $ ./fake_aout

 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [First_puts]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 First_puts
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [Second_puts]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 Second_puts
 hook func test !
 Trojan injected ET_REL takes control now [Z:legit func !:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [legit func !]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 legit func !
 ========= END DUMP 41 ========= 


	Oui, ça fonctionne. Maintenant, jetons un coup d'oeil au fichier
	static fake_aout :



 ========= BEGIN DUMP 42 =========

 elfsh@WTH $ ../../../vm/elfsh  -f ./fake_aout -s

 [*] Object ./fake_aout has been loaded (O_RDONLY)

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object ./fake_aout]

 [000] 0x00000000 -------                             foff:000000 sz:00000
 [001] 0x080480D4 a------ .note.ABI-tag               foff:069844 sz:00032
 [002] 0x08048100 a-x---- .init                       foff:069888 sz:00023
 [003] 0x08048120 a-x---- .text                       foff:69920 sz:347364
 [004] 0x0809CE10 a-x---- __libc_freeres_fn           foff:417296 sz:02222
 [005] 0x0809D6C0 a-x---- .fini                       foff:419520 sz:00029
 [006] 0x0809D6E0 a------ .rodata                     foff:419552 sz:88238
 [007] 0x080B2F90 a------ __libc_atexit               foff:507792 sz:00004
 [008] 0x080B2F94 a------ __libc_subfreeres           foff:507796 sz:00036
 [009] 0x080B2FB8 a------ .eh_frame                   foff:507832 sz:03556
 [010] 0x080B4000 aw----- .ctors                      foff:512000 sz:00012
 [011] 0x080B400C aw----- .dtors                      foff:512012 sz:00012
 [012] 0x080B4018 aw----- .jcr                        foff:512024 sz:00004
 [013] 0x080B401C aw----- .data.rel.ro                foff:512028 sz:00044
 [014] 0x080B4048 aw----- .got                        foff:512072 sz:00004
 [015] 0x080B404C aw----- .got.plt                    foff:512076 sz:00012
 [016] 0x080B4060 aw----- .data                       foff:512096 sz:03284
 [017] 0x080B4D40 aw----- .bss                        foff:515380 sz:04736
 [018] 0x080B5FC0 aw----- __libc_freeres_ptrs         foff:520116 sz:00024
 [019] 0x080B6000 aw----- rel2.o.bss                  foff:520192 sz:04096
 [020] 0x080B7000 a-x---- rel2.o.text                 foff:524288 sz:04096
 [021] 0x080B8000 aw----- rel2.o.data                 foff:528384 sz:00004
 [022] 0x080B9000 a------ rel2.o.rodata               foff:532480 sz:04096
 [023] 0x080BA000 a-x---- .elfsh.hooks                foff:536576 sz:00032
 [024] 0x080BB000 aw----- libc/printf.o.bss           foff:540672 sz:04096
 [025] 0x080BC000 a-x---- libc/printf.o.text          foff:544768 sz:04096
 [026] 0x080BD000 aw----- libc/gethostname.o.bss      foff:548864 sz:04096
 [027] 0x080BE000 a-x---- libc/gethostname.o.text     foff:552960 sz:04096
 [028] 0x080BF000 aw----- libc/perror.o.bss           foff:557056 sz:04096
 [029] 0x080C0000 a-x---- libc/perror.o.text          foff:561152 sz:04096
 [030] 0x080C1000 a--ms-- libc/perror.o.rodata.str1.1 foff:565248 sz:04096
 [031] 0x080C2000 a--ms-- libc/perror.o.rodata.str4.4 foff:569344 sz:04096
 [032] 0x080C3000 aw----- libc/dup.o.bss              foff:573440 sz:04096
 [033] 0x080C4000 a-x---- libc/dup.o.text             foff:577536 sz:04096
 [034] 0x080C5000 aw----- libc/iofdopen.o.bss         foff:581632 sz:04096
 [035] 0x00000000 ------- .comment                    foff:585680 sz:20400
 [036] 0x080C6000 a-x---- libc/iofdopen.o.text        foff:585728 sz:04096
 [037] 0x00000000 ------- .debug_aranges              foff:606084 sz:00136
 [038] 0x00000000 ------- .debug_pubnames             foff:606220 sz:00042
 [039] 0x00000000 ------- .debug_info                 foff:606262 sz:01600
 [040] 0x00000000 ------- .debug_abbrev               foff:607862 sz:00298
 [041] 0x00000000 ------- .debug_line                 foff:608160 sz:00965
 [042] 0x00000000 ------- .debug_frame                foff:609128 sz:00068
 [043] 0x00000000 ------- .debug_str                  foff:609196 sz:00022
 [044] 0x00000000 ------- .debug_macinfo              foff:609218 sz:28414
 [045] 0x00000000 ------- .shstrtab                   foff:637632 sz:00632
 [046] 0x00000000 ------- .symtab                     foff:640187 sz:30192
 [047] 0x00000000 ------- .strtab                     foff:670379 sz:25442

 [*] Object ./fake_aout unloaded

 elfsh@WTH $ ../../../vm/elfsh  -f ./fake_aout -p

 [*] Object ./fake_aout has been loaded (O_RDONLY)

 [Program Header Table .::. PHT]
 [Object ./fake_aout]

 [00] 0x8037000 -> 0x80B3D9C r-x memsz(511388) foff(000000) =>Loadable seg
 [01] 0x80B4000 -> 0x80B7258 rw- memsz(012888) foff(512000) =>Loadable seg
 [02] 0x80480D4 -> 0x80480F4 r-- memsz(000032) foff(069844) =>Aux. info.
 [03] 0x0000000 -> 0x0000000 rw- memsz(000000) foff(000000) =>Stackflags
 [04] 0x0000000 -> 0x0000000 --- memsz(000000) foff(000000) =>New PaXflags
 [05] 0x80B6000 -> 0x80B7000 rwx memsz(004096) foff(520192) =>Loadable seg
 [06] 0x80B7000 -> 0x80B8000 rwx memsz(004096) foff(524288) =>Loadable seg
 [07] 0x80B8000 -> 0x80B8004 rwx memsz(000004) foff(528384) =>Loadable seg
 [08] 0x80B9000 -> 0x80BA000 rwx memsz(004096) foff(532480) =>Loadable seg
 [09] 0x80BA000 -> 0x80BB000 rwx memsz(004096) foff(536576) =>Loadable seg
 [10] 0x80BB000 -> 0x80BC000 rwx memsz(004096) foff(540672) =>Loadable seg
 [11] 0x80BC000 -> 0x80BD000 rwx memsz(004096) foff(544768) =>Loadable seg
 [12] 0x80BD000 -> 0x80BE000 rwx memsz(004096) foff(548864) =>Loadable seg
 [13] 0x80BE000 -> 0x80BF000 rwx memsz(004096) foff(552960) =>Loadable seg
 [14] 0x80BF000 -> 0x80C0000 rwx memsz(004096) foff(557056) =>Loadable seg
 [15] 0x80C0000 -> 0x80C1000 rwx memsz(004096) foff(561152) =>Loadable seg
 [16] 0x80C1000 -> 0x80C2000 rwx memsz(004096) foff(565248) =>Loadable seg
 [17] 0x80C2000 -> 0x80C3000 rwx memsz(004096) foff(569344) =>Loadable seg
 [18] 0x80C3000 -> 0x80C4000 rwx memsz(004096) foff(573440) =>Loadable seg
 [19] 0x80C4000 -> 0x80C5000 rwx memsz(004096) foff(577536) =>Loadable seg
 [20] 0x80C5000 -> 0x80C6000 rwx memsz(004096) foff(581632) =>Loadable seg
 [21] 0x80C6000 -> 0x80C7000 rwx memsz(004096) foff(585728) =>Loadable seg

 [SHT correlation]
 [Object ./fake_aout]

 [*] SHT is not stripped

 [00] PT_LOAD            .note.ABI-tag .init .text __libc_freeres_fn .fini
                         .rodata __libc_atexit __libc_subfreeres .eh_frame
 [01] PT_LOAD           .ctors .dtors .jcr .data.rel.ro .got .got.plt 
			.data
                        .bss __libc_freeres_ptrs
 [02] PT_NOTE           .note.ABI-tag
 [03] PT_GNU_STACK
 [04] PT_PAX_FLAGS
 [05] PT_LOAD           rel2.o.bss
 [06] PT_LOAD           rel2.o.text
 [07] PT_LOAD           rel2.o.data
 [08] PT_LOAD           rel2.o.rodata
 [09] PT_LOAD           .elfsh.hooks
 [10] PT_LOAD           libc/printf.o.bss
 [11] PT_LOAD           libc/printf.o.text
 [12] PT_LOAD           libc/gethostname.o.bss
 [13] PT_LOAD           libc/gethostname.o.text
 [14] PT_LOAD           libc/perror.o.bss
 [15] PT_LOAD           libc/perror.o.text
 [16] PT_LOAD           libc/perror.o.rodata.str1.1
 [17] PT_LOAD           libc/perror.o.rodata.str4.4
 [18] PT_LOAD           libc/dup.o.bss
 [19] PT_LOAD           libc/dup.o.text
 [20] PT_LOAD           libc/iofdopen.o.bss |.comment
 [21] PT_LOAD           libc/iofdopen.o.text
 [*] Object ./fake_aout unloaded

 ========= END DUMP 42 =========


	On peut noter le ET_REL réellement injecté : printf.o@libc,
	dup.o@libc, gethostname.o@libc, perror.o@libc et iofdopen.o@libc.

	Chaque fichier injecté crée quelques segments PT_LOAD. Pour cet
	exemple, c'est bon, mais pour injecter E2dbg, c'est vraiment trop.

	Cette techniuque sera améliorée aussi vite que possible en
	réutilisant les entrées PT_LOAD quand c'est possible.



----[ D. Algorithmes indépendants de l'architecture



	Dans cette partie, nous donnons tous les algorithmes indépendants
	des architectures que nous avons développés pour la nouvelle
	technique de résidence en mémoire, librairies ET_DYN, ou
	exécutables statiques.

	Le nouvel algorithme générique d'injection ET_REL n'est pas si
	différent de celui présenté dans l'article précédant dans
	l'article Cerberus ELF Interface [0], c'est pourquoi nous ne
	montrons encore que sa version courte. Cependant, le nouvel
	algorithme a amélioré sa portabilité et modularité. Nous
	détaillerons certaines parties qui n'ont pas été expliquée dans
	les articles précédents. L'implémentation est principalement dans
	elfsh_inject_etrel() du fichier relinject.c :


	 Nouvel Algorithme de relocalisation générique
	+---------------------------------------------+
	
	1/ Injecter le BSS du ET_REL après le BSS du programme hote
	dans une nouvelle section dédiée
	
	2/ FOREACH section dans l'objet ET_REL
	[
		IF [ Section est mappee et Section n'est pas BSS ]
		[
			- Injecter la section dans le fichier hôte ou la
			  mémoire
		]
	]
	
	3/ Fusionner les tables de symboles du ET_REL et du fichier hôte
	
	4/ Reloger l'objet ET_REL (Phase 1)
	
	5/ Quand on sauvegarde, reloger l'objet ET_REL
	(Phase 2 pour les symboles old)

	Nous n'avions qu'une seule phase de relocalisation dans le passé.
	Nous devons maintenant en avoir une deuxième puisque tous les
	symboles requis ne sont pas disponibles (comme les symboles old
	issus de la redirections CFLOW qui peut apparaitre après
	l'injection ET_REL). Pour les modifications sur le disque, la
	deuxième phase est faite au moment de la sauvegarde.

	Certaines étapes dans cet algorithme sont assez évidentes, comme
	les étapes 1 et 3. Elles ont été expliquées dans le premier
	article [0], cependant l'algorithme BSS a changé par
	compatibilité avec les fichiers ET_DYN et les injections ET_REL
	multiples. Maintenant, le BSS est injecté comme une autre
	section, au lieu d'ajouter un algorithme complexe de zone BSS
	pour garder toujours un BSS dans le programme.


	 Algorithme d'injection de sections ET_DYN / ET_EXEC
	+---------------------------------------------------+

	L'algorithme d'injection pour les sections de DONNÉES ne change
	pas entre les fichiers ET_EXEC et ET_DYN. Cependant, l'injection
	de section de code change un peu pour supporter à la fois les
	hôte sous forme de binaire et de librairie. Voici le nouvel
	algorithme pour cette opération :

	* Trouver le PT_LOAD exécutable
	* Corriger la taille des sections injectées par congruence de
	  taille des pages

	IF [ Hostfile est ET_EXEC ]
	[
		* Mettre la vaddr de la section injectée à la vaddr la plus
		  basse de la section mappée
		* Soustraire la nouvelle taille de section à la nouvelle
		  adresse virtuelle de la section
	]
	ELSE IF [ Hostfile est ET_DYN ]
	[
		* Mettre la vaddr de la section injectée à la vadr la plus
		  basse de la section mappée
	]
	
	* Étendre la taille du segment de code par la taille de la section
	  injectée.
	
	IF [ Hostfile est ET_EXEC ]
	[
		* Soustraire la vadr de la section injectée à la vaddr du
		  PT_LOAD de l'exécutable
	] 
	
	FOREACH [ Entry dans PHT ]
	[
		IF [ Segment est PT_PHDR et Hostfile est ET_EXEC ]
		[
		* Soustraire la taille de la section injectée au segment
		  p_vaddr / p_paddr
		]
		ELSE IF [ Segment est après le PT_LOAD étendu ]
		[
			* Ajouter la taille de la section injectée au
			segment p_offset

			IF [ Hostfile est ET_DYN ]
			[
			   * Ajouter la taille de la section injectée au
			    segment p_vaddr et p_paddr
			]
		]
	]
	
	IF [ Hostfile est ET_DYN ]
	[
		FOREACH [ entrée de relocation dans chaque table
		          de relocation ]
		[
		IF [ offset de relocation pointe après
		     la section injectée ]
		[
			* Changer l'offset de relocation à partir de
			  la taille de la section injectée
		]
		]
	
		En utilisant la taille de la section injectée :
		* Changer les symboles quand ils pointent après elle
		* Changer les symboles dynamiques (même condition)
		* Changer les entrées dynamiques du D_PTR
		* Changer les entrées GOT
		* Si elles existent, changer les entrées ALTGOT
		* Changer DTORS et CTORS
		* Changer le point d'entrée de l'en-tête ELF
	]
	
	* Injecter le nouveau symbole SECTION dans le code injecté


	 Algorithme d'injection statique de section ET_EXEC
	+--------------------------------------------------+
	
	
	Cet algorithme est utilisé pour insérer des sections dans les
	binaires statiques. On le trouve dans libelfsh/inject.c, dans la
	fonction elfsh_insert_static_section() :

	* Changer la taille de la section injectée pour rester congru à la
	  taille de page.
	* Créer un nouvel en-tête de programme PT_LOAD dont les bornes
	  correspondent à celles de la nouvelle section
	* Insèrer la nouvelle sections en utilisant les algorithmes
	  classiques
	* Insèrer le nouvel en-tête de programme dans la PHT
	
	
	 Algorithme d'injection de section à l'exécution en mémoire
	+----------------------------------------------------------+


	Cet algorithme se trouve dans libelfsh/inject.c, dans la fonction
	elfsh_insert_runtime_section() :

	* Créer un nouvel en-tête de programme PT_LOAD
	* Insèrer une entrée SHT pour la nouvelle section à l'exécution
	  (pour garder une table statique à jours)
	* Insèrer la nouvelle section en utilisant les algorithmes
	  classiques
	* Insèrer le nouveau PT_LOAD dans la table runtime PHT (RPHT) avec
	  les mêmes bornes.

	La Runtime PHT est une nouvelle table que nous avons introduite
	pour nous permettre de séparer les segments habituellements
	mappés par l'éditeur de lien dynamique (le segment PHT original)
	des segments injectés à l'exécution. Cette manière nous conduira
	dans le furut à un algorithme plus facile pour la reconstruction
	du binaire à partir de son image mémoire.

	Nous allons maintenant détailler l'algorithme principal (à haut
	niveau) de relocation comme il est implémenté dans les fonctions
	elfsh_relocate_object() et elfsh_relocate_etrel_section() du fichier
	libelfsh/relinject.c . Ce code est commun pour tous les types de fichier
	hôtes et pour toutes les étapes de relocalisation. Il est utilisé à
	l'étape 4 de l'algorithme général :


	 Algorithme portable principal de relocation
	+-----------------------------------------------+
	
	Cet algorithme n'a pas encore été expliqué dans aucun article,
	le voici :
	
	
	FOREACH section ET_REL injectée dans le fichier hôte
	[
		FOREACH entrée de relocation dans le fichier ET_REL
		[
		* trouver les symboles nécessaires dans ET_REL pour
		  cette relocalisation
		IF [ Symbol est COMMON ou NOTYPE ]
		[
			* Trouver le symbole correspondant le fichier hôte
			IF [ Symbol est NOT FOUND ]
			[
			IF [ symbol est OLD et RELOCSTAGE == 1 ]
			[
				* Retarder sa relocalisation
			]
			ELSE
			[
				IF [ le type du symbole ET_REL
				     est NOTYPE ]
				[
				* Demander une nouvelle entrée PLT et
				  utilise son adresse pour faire la
				  relocation (Algorithme EXTPLT)
				]
				ELSE IF [ Fichier hôte est STATIC ]
				[
				* Utiliser la technique EXTSTATIC
				  (Algorithme suivant)
				]
				ELSE
				[
				* L'algorithme a échoué, retourne ERROR
				]
			]
			]
			ELSE
			[
			  * Utilise la valeur du symbole du fichier hôte
			]
		]
		ELSE
		[
			* Utilise l'adresse de base de la section
			  injectée comme valeur du symbole
		]
		- Entrée de relocalisation (switch/case entre les
		  gestionnaires dédiés aux architectures)
		]
	]
	
	
	 Extension EXTSTATIC de l'algorithme de relocalisation
	+-----------------------------------------------------+

	Dans ce cas, le fichier hôte est statique, nous pouvons essayer
	de récupérer les symboles inconnus à partir des fichiers
	relogeables des librairies statiques qui sont disponibles sur le
	disque. Un exemple d'utilisation de la technique EXTSTATIC se
	trouve dans le répertoire testsuite/etrel_inject/.

	Voici l'algorithme EXTSTATIC qui se trouve à l'endroit spécifié
	dans l'algorithme précédent pour fournir les mêmes
	fonctionnalités que EXTPLT mais pour les binaires statics :
	
	
	FOREACH objet ET_REL chargé dans ELFSH
	[
		IF [ Symbol est trouvé n'importe où dans l'ET_REL analysé
		     pour l'instant ]
		[
		IF [ Le symbole trouvé est plus fort que le résultat
		     courant ]
		[
			* Met à jours le meilleurs symbole et le fichier
			  ET_REL associé	
		]
		ELSE
		[
			* Ignore le résultat de l'itération courante
		]
		]
	]
	* Injècter les dépendances ET_REL dans le fichier hôte
	* Utiliser le nouveau symbole injecté dans le fichier hôte comme
	  symbole de relocation dans l'algorithme principal de
	  relocation.
	
	
	 Algorithme du symbole le plus fort
	+----------------------------------+
	
	Quand nous devons choisir entre plusieurs symboles qui ont le
	même nom dans différents objets (autant pendant les injections
	statiques qu'à l'exécution), nous utilisons ce simple algorithme
	pour déterminer lequel utiliser :
	
	
	IF [ Le symbole choisi pour l'instant a STT_NOTYPE ]
	[
		* Le symbole est un choix temporaire
	]
	ELSE IF [ Le symbole candidat a STT_NOTYPE ]
	[
		* Le symbole est un choix temporaire
	]
	ELSE IF [ le champ bind du symbole candidat > symbole courant ]
	[
		* Le symbole candidat devient le choix definitif
	]
	


-------[ VI. Passé et présent


	Dans le passé, nous avons montré que l'injection ET_REL dans les
	objets ET_EXEC non-relogeable était possible. Ce papier vous a
	montré des extentions multiples et des portages de cette technique
	de résidence (pour des cibles ET_DYN et des exécutables
	statiques). Couplée à la technique EXTPLT qui permet une post
	liaison complète du fichier hôte, nous pouvons ajouter des
	définitions de fonctions et utiliser des fonctions inconnues dans
	le logiciel étendu. Toutes ces techniques d'injections statiques
	marchent quand toutes les options de PaX sont activées sur
	le binaire modifié. Bien sûr, les fonctionnalités de position
	indépendante, et de protection de débordement de pile de Gentoo
	ne protègent rien quand c'est appliqué à de la manipulation de
	binaire, qu'elle ai lieu sur le disque où à l'exécution.

	Nous avons aussi montré qu'il est possible de débogué sans
	utiliser l'appel système ptrace, ce qui ouvre une porte pour le
	reverse engineering et les méthodes de déboguage embarquées qui
	contournent des techniques anti-débogue connues. Le débogueur
	embarqué n'est pas complètement Pax-Proof et il est encore
	nécessaire de désactiver le flag mrprotect. Même si ça ne semble
	pas un réel problème, nous continuons de chercher une méthode
	pour placer des breakpoints (e.g. des redirections) sans le
	désactiver.

	Nos techniques principales sont portables à beaucoup
	d'architectures (x86, alpha, mips, sparc) à la fois sur des
	fichiers 32bits et 64bits. Cependant, notre débogueur "preuve de
	concept" n'a été implémenté que pour x86. Nous pensons que nos
	techniques sont suffisament portable pour pouvoir fournir un
	débogueur pour d'autres architectures sans trop de problèmes.

	Distribuez et appréciez cette suite, les contributions sont les
	bienvenues.


-------[ VII. Remerciements


	Nous remercions tous les gens à WhatTheHack party 2005 aux
	Pays-Bas. Nous nous sommes tant amusés avec vous, et nous
	reviendrons la prochaine fois.

	Des remerciements spéciaux à andrewg pour nous avoir expliquer la
	technique sigaction, dvorak pour son intéret dans l'optimisation
	de la technique ALTPLTv2 pour SPARC, sk pour libasm, et solar
	pour nous avoir fournis les tests pour ET_DYN pie/ssp.

	Nos respects à Devhell Labs, l'équipe PaX, le Phrackstaff,
	GOBBLES, MMHS, ADM et Synnergy Networks. Un clin d'oeil final à
	s/ash de RTC pour nous avoir conduit à WTH et le Coconut Crew
	pour tout le reste, vous vous reconnaitrez.


-------[ VIII. Références


 [0] The Cerberus ELF Interface				mayhem
     http://www.phrack.org/show.php?p=61&a=8

 [1] The GNU debugger					GNU project
     http://www.gnu.org/software/gdb/

 [2] PaX / grsecurity					The PaX team
     http://pax.grsecurity.net/

 [3] binary reconstruction from a core image		Silvio Cesare
     http://vx.netlux.org/lib/vsc03.html

 [4] Antiforensic evolution: Self			Ripe & Pluf
     http://www.phrack.org/show.php?p=63&a=11

 [5] Next-Gen. Runtime binary encryption		Zeljko Vbra
     http://www.phrack.org/show.php?p=63&a=13

 [6] Fenris						Michal Zalewski
     http://lcamtuf.coredump.cx/fenris/

 [7] Ltrace						Ltrace team
     http://freshmeat.net/projects/ltrace/

 [8] The dude (replacement to ptrace)			Mammon
     http://www.eccentrix.com/members/mammon/Text/d\
     ude_paper.txt

 [9] Binary protection schemes				Andrewg	
     http://www.codebreakers-journal.com/viewar\
     ticle.php?id=51&layout=abstract

 [10] ET_REL injection in memory			JP
      http://www.whatever.org.ar/~cuco/MERCANO.TXT
      
 [11] Hardened Gentoo project				Hardened team
      http://www.gentoo.org/proj/en/hardened/

 [12] Unpacking by Code Injection			Eduardo Labir
      http://www.codebreakers-journal.com/viewart\
      icle.php?id=36&layout=abstract