logo Homepage
Pages: [1]
  Imprimer  
Auteur Fil de discussion: Introduction à l' Inline API Hooking  (Lu 3193 fois)
Lord357

Profil challenge

Classement : 863/54283

Néophyte
*
Hors ligne Hors ligne
Messages: 31

Malware Scientist


Voir le profil
« le: 03 Septembre 2011 à 23:58:32 »

0. Sommaire

1. Pré-requis
2. Qu'est ce que l'inline API Hooking
3. Principe de fonctionnement
4. Un peu de vocabulaire
5. Implémentation technique
6. Exemple !
7. Connaître son ennemi
8. Quelques Liens

1. Pre-requis

Pour être à même de bien comprendre le sujet, il y a quelques fondamentaux dont les bases seront préférables de connaître:
  • Une bonne base en Assembleur x86 (nous n'aborderons pas le 64-bits)
  • Un minimum de programmation sous Windows, comprenant les APIs
  • Optionnellement, le format PE/COFF des exécutables Microsoft

Techniquement :
  • Un OS Microsoft à disposition (évidemment)
  • FASM pour compiler l'exemple
  • Ollydbg (si vous souhaitez débugger l'exemple plus bas)

2. Qu'est ce que l'inline API Hooking

C'est une technique de ring3 (userland) consistant au crochetage de fonctions importées par un executable dans le but de surveiller et/ou modifier leur flux d'exécution. On entend par crochetage la redirection des appels sur des fonctions de remplacement qui pourront par la suite rappeler l'API initiale (ou pas). L'utilité ? Ca dépend ... Les antivirus s'en servent encore aujourd'hui (McAfee par exemple) pour surveiller les comportements suspects pouvant être liés à un malware tandis que les developpeurs de malware l'utilise pour developper des rootkits.

3. Principe de fonctionnement

Lorsqu'un exécutable importe les API d'une DLL (voir doc sur le format PE / COFF), le code de cette dernière (et donc les fonctions qu'elle met à disposition) est chargé dans l'espace mémoire du processus visé, dès son lancement.
L'axe de fonctionnement principal de cette technologie repose sur la réécriture partielle de ces API avec pour objectif la redirection, tel qu' expliqué dans la section précédente. La méthode la plus simple pour atteindre ce but est donc l'écriture d'un saut inconditionnel vers la fonction de remplacement, en écrasant les premiers octets de code de la fonction initiale. On pourra au préalable va bien sur sauvegarder ces octets au cas ou nous souhaitons rappeler cette dernière après la redirection du flux.

4. Un peu de vocabulaire

Voici les termes utilisés nommant chacune des parties impliquées par la mise en place du dispositif :
Trampoline : Les premiers octets de l'API visée mis à l'abris pour rappel ultérieur, auxquel nous concaténons un saut vers la suite du code de celle-ci.
Detour : Le saut inconditionnel que nous écrivons pour rediriger le flux d'exécution vers notre fonction de remplacement.

5. Implémentation technique

Nous souhaitons donc écrire un saut vers notre fonction. La taille d'un saut est de 5 octets :
Code:
jmp [Address] ;jmp = 1 octet - [Address] = 4 octets codés donc sur 32-bits

Nous écraserons donc 5 octets. Le problème essentiel se posant lors de l'implémentation du crochetage, c'est la taille des premiers octets de l'API visée, ceux que nous allons sauvegarder dans le trampoline, si nous souhaitons la rappeler. Nous ne pouvons en effet pas garantir que notre saut ne coupera pas d'instruction en deux. Imaginez le massacre lors de l'execution du trampoline...

Illustration par l'exemple (complètement factice d'ailleurs) :
Code:
;imaginons une API commençant par le code suivant
mov edx, eax  ;2 octets
mov eax, ebx  ;2 octets
call 00403108 ;5 octets

;Si on réécrit 5 octets on coupe le call en deux, le code sera corrompu et il y a 99.99% de chance pour que l'exécutable plante lamentablement :)

Rassurez-vous, pour la majorité des API, le problème ne se posera pas. En effet celles-ci commencent quasiment toute une parcelle d'instructions connue sous le nom de prologue dont voici un exemple:
Code:
mov edi, edi  ; 2 octets
push ebp       ; 1 octet
mov ebp, esp ; 2 octets

;pile poil 5 octets donc aucun problème pour les sauver et les écraser par un saut :)

Pour celles qui ne correspondent pas à cette règle, nous devrons calculer la taille des intructions avant de réécrire (LDE) - Ce n'est pas le sujet du papier, c'est assez complexe et nécéssite une parfaite connaissance de la composition des instructions, je vous renvoie vers les manuels INTEL.

Deuxième contrainte, les permissions ; une section de code est rarement "writeable", c'est un fait. C'est particulièrement vrai pour l'espace mémoire sur lequel nous essayons d'écrire et fondamentalement, une API c'est du code. Pour cela il existe une fonction parfaitement documentée : VirtualProtect() qui nous permet de changer les permissions d'une page mémoire. Vous trouverez les informations nécéssaires à sont utilisation sur MSDN ainsi que dans l'exemple suivant.

6. Exemple !

Voici un exemple de crochetage utilisant la méthode inline hook. Nous affichons une simple messagebox. Nous crochetons ensuite l'API correspondante pour modifier le message à la volée, puis nous rappelons la fonction pour constater.
Il est codé en asm (FASM). Il est sévèrement commenté pour permettre au plus grand nombre de comprendre tant qu'on a lu les quelques lignes d'explications ci-dessus.
Bien évidemment dans des cas réels d'utilisation, il faudrait que le mecanisme soit implémenté dans un process distant. Crocheter ses propres appels n'a pas grand intérêt, mais l'objectif n'est pas de montrer comment développer un rootkit.

PS : avis aux connaisseurs, ne faites pas attention aux permissions sur les sections, il n'y a pas de error handler non plus ...

Code:
format PE GUI 4.0
entry start

include "WIN32AX.inc"
include 'KERNEL32.INC'
include 'USER32.INC'

;section code
section '.text' code readable executable writeable

proc start
   call Popup ;appel initial
   call InstallHook ;happy (api?) hooking :-)
   call Popup ;on test le crochetage
   ret
endp

;affiche un simple msgbox
proc Popup
   push 0
   push szCaption
   push szOriginalMessage
   push 0
   call [MessageBox]
   ret
endp

proc InstallHook
   call WriteTrampoline ;on écrit le trampoline
   push 28 ;on récupere les information de la page mémoire
   push mbi
   push [MessageBox]
   call [VirtualQuery]
   push mbi ;on change un peu le mode de protection sinon on ne pourra pas écrire à l'adresse voulue (API)
   push 040h
   push 10
   push [MessageBox]
   call [VirtualProtect]
   call WriteDetour ;on écrit le détour
   ret ;normalement avant il faudrait quand même rétablir la protection avant de sortir, c'est pas propre !
endp

proc WriteTrampoline
   mov esi, [MessageBox] ;source
   mov edi, trampoline ;destination
   mov ecx, 5 ;taille du prologue
   rep movsb ;écriture
   mov dword[edi], 0E9h ;on écrit un jmp
   inc edi ;on incremente pour écrire l'adresse de notre adresse de saut juste apres le detour
   mov dword[edi],esi ;on ecrit l'adresse absolue qui suit le prologue
   sub dword[edi],trampoline ;calcul de l'adresse relative
   sub dword[edi],0Ah
   ret
endp

proc WriteDetour
   mov edi, [MessageBox] ;destination
   mov dword[edi], 0E9h  ;on écrit un jmp
   mov eax, MyMessageBox ;on pointe sur la nouvelle fonction
   sub eax, edi ;calcul de l'adresse relative
   sub eax, 5
   inc edi ;le jmp c'est fait, on veut juste ajouter l'adresse alors on enleve sa taille (au jmp)
   stosd ;ecriture
   ret
endp

;Fonction de remplacement
proc MyMessageBox
   lea ebx,[esp + 8h] ;direction la pile, sur l'adresse contenant le pointeur sur le message
   Mov dword[ebx], szBetterMessage ;on la change (l'adresse !)
   Jmp trampoline ;on exécute le code du trampoline
endp

;notre backup du prologue suivi d'un saut vers la suite de l'API
trampoline rb 10


;section data
section '.data' data readable writeable

mbi rb 28
szCaption db "Hello !",0
szOriginalMessage db "Hello World",0
szBetterMessage db "Hello NewbieContest World",0


;imports
section '.idata' import data readable writeable

library kernel32, "kernel32.dll", user32, "user32.dll"

7. Connaître son ennemi

L'inline hook est une méthode qui nécéssite d'être couplée à un vecteur d'infection lorsqu'elle est utilisée pour le developpement d'un rootkit. Il faut bien évidemment crocheter les API ciblées dans l'ensemble des processus du système pour cacher les éléments dont la detection mettrait en évidence un acte de piratage. En général, ce vecteur est une injection de code ou de DLL contenant le rootkit en question. Il convient donc se se prémunir en amont à l'aide de logiciels spécifiquement conçus dans l'objectif de protéger la mémoire du système. Process Guard en est l'exemple, il est d'ailleurs particulièrement efficace s'il est correctement configuré. Les antivirus (performance mise à part) vont également (en général) vérifier les comportements de ce type à l'aide d'analyse heuristique. Les firewall personnels (comme BlackIce ou ZoneAlarm) fournissent quant à eux une protection en temps réel en crochetant (et oui) les API (userland ou kernel) servant ce but, et offre ainsi une protection relativement efficace.

Il est également possible de constater un inline hook manuellement, vous chercherez Ice Sword (logiciel gratuit) qui est spécifiquement developpé pour repérer un processus ayant subit l'attaque. RK Unhooker et d'autres programmes anti-rootkit permettent aussi de detecter un rootkit. Le reste du travail : la rétro-ingénierie des fonctions de remplacement mais c'est un autre sujet.

Ceci dit, si vous n'avez aucune protection et que ces utilitaires vous donne un résultat positif, vos données vous ont probablement déja été dérobées ...

8. Quelques liens

Et pour finir, quelques liens vers des documents permettant d'approfondir le sujet :
« Dernière édition: 06 Septembre 2011 à 17:44:57 par Lord357 » Journalisée

lord | asm x86 (FASM © Powered) | .NET | Viruses and Backdoors Technologies
pwns Microsoft systems since 2003.
the lsd
Administrateur

Profil challenge

Classement : 190/54283

Membre Héroïque
*****
Hors ligne Hors ligne
Messages: 3096

poulping for fun & profit


Voir le profil WWW
« #1 le: 04 Septembre 2011 à 00:43:38 »

Ma foi, c'est un très bon tuto. Bien mis en forme, pas de faute (bon j'ai pas fait très attention, mais j'ai pas vu d'énormité). En plus sur un sujet peu abordé sur NC, c'est cool.
Je suis pas un pro du inline hook, mais je crois pas avoir vu d'erreur.

Maintenant, les reproches !

Déjà mettre des liens, tu parles d'aller voir la doc à certains moments, ça serait cool de mettre des liens vers cette doc.
Après, il y a un truc que je comprend pas trop. Sans vouloir t'offenser, t'es pas dans le top ten de NC, tu n'as pas résolu beaucoup d'épreuves en général, et particulièrement de crackme, et tu ponds un truc pareil. J'ai du zapper un truc...

Bon, je suis pas le seul décideur, qu'en penses les autres relecteurs ?

Enjoy

The lsd
Journalisée

Newbie Contest Staff :
The lsd - Th3_l5D (IRC)
Statut :
Administrateur
Citation :
Cartésien désabusé : je pense, donc je suis, mais je m'en fous !
Lord357

Profil challenge

Classement : 863/54283

Néophyte
*
Hors ligne Hors ligne
Messages: 31

Malware Scientist


Voir le profil
« #2 le: 04 Septembre 2011 à 10:24:42 »

Merci ! Il doit y avoir quelques fautes, je vais relire de toute façon. Et puis je sais déja aussi qu'il manque deux trois infos, comme ce que fais le POC (même si le code est très commenté). Je voulais rajouter des références docs liens et autres aussi mais il était un peu tard, je vais amender le doc dans la journée.

Pour répondre à ta question je suis pas un super caid en reverse engineering (je parle même pas du reste), je suis pas nullissime non plus mais c'est vraiment pas le top.

Par contre (j'espere pas avoir l'air trop prétentieux) je connais très bien les systèmes MS, le domaine du malware en règle générale que ce soit les virus, les backdoor, les méthodes de contournement antivirus, firewall etc (j'ai été assez actif sur cette scene pendant une période), et j'ai fait beaucoup d'ASM (debugger mon propre code c'est bien plus simple que débugger le code d'un crackme !).

En esperant que ça réponde à ton interrogation :-)
« Dernière édition: 04 Septembre 2011 à 11:45:57 par Lord357 » Journalisée

lord | asm x86 (FASM © Powered) | .NET | Viruses and Backdoors Technologies
pwns Microsoft systems since 2003.
_o_
Relecteur

Profil challenge

Classement : 42/54283

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #3 le: 04 Septembre 2011 à 11:23:19 »

Pas mieux que the_lsd. J'attends que tu amendes pour donner le feu vert à la publi.

Juste une faute qui m'a sautée aux yeux :
Citation
nous devrons calculer la tailles des intructions
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
Lord357

Profil challenge

Classement : 863/54283

Néophyte
*
Hors ligne Hors ligne
Messages: 31

Malware Scientist


Voir le profil
« #4 le: 04 Septembre 2011 à 11:42:57 »

J'étais justement en train de modifier. J'ai rajouter quelques liens pour approfondir, et vers les docs que je cite. J'ai corrigé la faute d'analphabète que j'ai commise (je suis pas sur qu'il n'y en ai pas d'autres, mais elles seront plus discrètes je pense).

J'ai aussi rajouté une section de pre-requis histoire que les gens lisent pas pour rien (compréhension & testing). Ca m'a l'air OK sauf si vous voyez d'autres éléments.
Journalisée

lord | asm x86 (FASM © Powered) | .NET | Viruses and Backdoors Technologies
pwns Microsoft systems since 2003.
Asteriksme
Modérateur Global

Profil challenge

Classement : 37/54283

Membre Héroïque
*****
Hors ligne Hors ligne
Messages: 785

.


Voir le profil WWW
« #5 le: 04 Septembre 2011 à 11:45:10 »

J'aime bien aussi, au niveau de la forme j'ai juste relevé deux trois autres coquilles sans importance : il manque quelques accents notamment sur les "exécutables", avant le code de l'exemple, il manque un l à "handler", et un u à "pointeur" (vers la fin du code). Sinon pour le fond, j'y connais rien donc je pourrais pas trouver d'erreur, par contre c'est vrai que c'est clair, j'ai tout compris !
Journalisée

"It's a funny thing about some mathematicians. We often don't care if the results have applications because the results are themselves so pretty."
Lord357

Profil challenge

Classement : 863/54283

Néophyte
*
Hors ligne Hors ligne
Messages: 31

Malware Scientist


Voir le profil
« #6 le: 04 Septembre 2011 à 11:49:42 »

Accent corrigé également, pointeur et handler aussi

EDIT : Ne publiez pas de suite, je vais ajouter quelques éléments de prévention (comme demandé sur le tuto TLS).
« Dernière édition: 05 Septembre 2011 à 09:48:15 par Lord357 » Journalisée

lord | asm x86 (FASM © Powered) | .NET | Viruses and Backdoors Technologies
pwns Microsoft systems since 2003.
Lord357

Profil challenge

Classement : 863/54283

Néophyte
*
Hors ligne Hors ligne
Messages: 31

Malware Scientist


Voir le profil
« #7 le: 06 Septembre 2011 à 17:42:48 »

J'ai rajouter un petit chapitre sur la protection. Vous pouvez balancer
Journalisée

lord | asm x86 (FASM © Powered) | .NET | Viruses and Backdoors Technologies
pwns Microsoft systems since 2003.
Pages: [1]
  Imprimer  
 
Aller à: