Welcome to Coding : Sécurité Programmation Réseaux

Search   in  

 Create an Account Home | Submit News Your Account Content | Topics | Top 10  


Accueil
· Home
· Listing des Articles
· Top 10
· Repository des Exploits

Les sujets / parties
· C / C ++
· Visual Basic
· Asm
· Reseaux
· Java
· Securite
· Divers

Utile
· Listing des Articles

· Telecharger
· Le Forum
· Liens
· Proposer un article

Top20 des Downloads
· 1: Etude des reseaux generalites et protocoles
· 2: Cheval de troie en VB avec sources
· 3: Netcat 1.1
· 4: Keylogger
· 5: Etudes des reseaux hauts debits architectures et protocoles
· 6: Ecoute de port
· 7: Etude du Smart Spoofing
· 8: Win Packet Capture Utils
· 9: Tutorial on Traffic Interception on Switched Lan using ARP spoofing
· 10: Cours de C

User Info
Welcome, Anonymous
Nickname
Password
(Register)
Membership:
Latest: trapcodien
New Today: 1
New Yesterday: 0
Overall: 2207

People Online:
Visitors: 43
Members: 1
Total: 44

Online Now:
01: trapcodien

  
Injection de code dans une application
Posted on Saturday, May 14 @ 22:41:40 CEST
Topic: Divers
Divers

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

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

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

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

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

L'exercice :

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

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

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

Le code :

Commençons par nous attaquer à la DLL, cette dll va tout simplement afficher un message lors de son chargement et déchargement pour nous avertir de la réussite de l'injection. Nous allons la realiser en assembleur pour une question de facilité. Voici le code : MODULE INJECTION.ASM ;=========================
; Assemblé avec Masm32
;=========================

.386
.model flat, stdcall
option casemap :none include windows.inc
include user32.inc
include kernel32.inc includelib user32.lib
includelib kernel32.lib .data Msg1 db "#Library Loaded" ,0
Msg2 db "#Library Unloaded" ,0 .code LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
.if reason == DLL_PROCESS_ATTACH
invoke MessageBox,NULL,addr Msg1,NULL,MB_OK
.elseif reason == DLL_PROCESS_DETACH
invoke MessageBox,NULL,addr Msg2,NULL,MB_OK
.endif
mov eax,1
ret
LibMain Endp End LibMain Assemblez-le de la manière suivante :
MASM32BINML.EXE /c /coff Injection.asm
MASM32BINLINK.EXE /SUBSYSTEM:WINDOWS /DLL Injection.obj

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

hWnd2 = FindWindow(vbNullString, "Document - WordPad")

Ensuite on recupère l'id du Process et du Thread de l'application :

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

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

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

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

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

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

Call LoadLibrary("INJECTION.DLL")

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

Récupérer l'adresse de LoadLibrary, rien de plus simple LoadLibrary est à la même adresse dans toutes les applications :

ModHdl = GetModuleHandle("KERNEL32")
ProcAddr = GetProcAddress(ModHdl, "LoadLibraryA")

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

ResumeAddr = lpContext.Eip

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

ChaineAddr = hVirutal + CodeSize + Align

Passons au code, il est plutôt simple, il n'utilisera que le registre arithmétique eax :
CODE MACHINE
MNEMONIQUE
B8 XX XX XX XX MOV EAX, ChaineAddr 50 PUSH EAX B8 XX XX XX XX MOV EAX, ProcAddr FF D0 CALL EAX B8 XX XX XX XX MOV EAX, ResumeAddr FF E0 JMP EAX Comme vous le constatez, le code ne prend que 20 octets. Nous placerons donc notre chaine de caractère au 32ème octet pour une question d'alignement, et remplirons les xx par les adresses respectives en vb. Cela donnerait :

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

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

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

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

 
Liens connexes
· Plus à propos de Divers
· Nouvelles transmises par Romain_Le_Guen


L'article le plus lu à propos de Divers:
Tutorial sur le fonctionnement de GDB (debugger sous linux)


Article Rating
Average Score: 5
Votes: 1


Please take a second and vote for this article:

Excellent
Very Good
Good
Regular
Bad


Options

 Format imprimable Format imprimable


PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Page Generation: 0.63 Seconds