IINJ
Par Baboon le lundi, juin 4 2007, 20:06 - General - Lien permanent
Ceux qui idlent sur IRC ont du remarquer le comportement bizarre de Kaine ces derniers jours ...
En effet il lui arrive de crier de façon compulsive "iiinnnnnjj".
IINJ n'est autre qu'un petit tool que j'ai bidouillé , permettant d'injecter du code dans un processus en cours et ce de façon relativement discrète.
L'idée a jailli un après midi grâce à une série de hasards ...
Je venais de faire un petit loader pour SC et je m'etais donc penché a cette occasion sur injmem, l'injecteur de virtualabs, afin de voir comment il marchait et essayer de l'améliorer avec lui.
Kaspersky le détectant, j'ai regardé la liste des apis hookées par notre ami russe et j'ai debuggé un peu injmem.
Je me suis vite aperçu que virtu se faisait avoir à cause de WriteProcessMemory, n'ayant pas trouvé d'alternatives , j'ai un peu oublié l'affaire
Et là **PAN** , une semaine après, un haiklr (hihi) de lucidité "Et si on obligeait le programme a s'auto injecter !?"
Pour injecter le code en effet je n'utilise pas d'apis propres a l'injection comme CreateRemoteThread , OpenProcess/Thread , WriteProcessMemory, je n'utilise que des apis de debug.
L'injection se deroule comme ceci :
- On scanne Kernel32 dans le processus injectant afin de trouver les adresses de 3 opcodes (nop , retn , push eax) et de quelques fonctions utiles.
- On scanne les processus , on repère le processus cible et on scanne ses modules de facon à trouver l'adresse où est loadée Kernel32.
- On debugge le processus cible via l'api DebugActiveProcess, ce qui nous permet d'avoir un handle sur le processus cible et ses threads.
- On adapte les adresses des opcodes précedemment recherchés et on injecte grâce à ces adresses et SetThreadContext
Par exemple , si je veux creer un espace memoire dans le processus cible , il me suffit d'obliger le processus cible à appeller VirtualAlloc.
Il faut donc que je push les arguments , pour ce faire , je mets dans eax la valeur à pusher et je fais pointer eip sur le "push eax" , je mets le trap flag à 1 et je lance, le programme breakera juste apres avoir executé le push eax et j'aurais alors pushé ma valeur.
Pour appeler l'api VirtualAlloc meme principe, ou presque, il me suffit de faire pointer eip vers le debut de l'api (après avoir pushé l'adresse du nop) , de mettre un HBP en execution sur le nop et de lancer le programme ,
Enfin, pour ecrire dans la mémoire allouée, plusieurs options s'offrent à vous , soit vous utilisez les apis comme createfile/readfile etc , soit vous utilisez un opcode de type mov.
Kaspersky n'aime pas que l'on ecrive dans la memoire fraichement allouée avec un mov [reg] , reg , j'ai donc utilisé (dans mon code de démo) un moyen detourné pour écrire en memoire , je deplace esp vers la zone à écrire + la taille du code et j'utilise une série de push ce n'est peu être pas tres beau mais ca a le merite de marcher ...
Enfin , Kaspersky n'aimant pas non plus que l'on fasse pointer eip sur une zone fraichement allouée , je fais un bete "push eip / retn"
(je n'ai pas testé d'autres methodes , alors faites vous plaisir )
Pour DL le pack source + exe c'est ICI (sources en NASM et C)
Dans mon exemple , j'ai créé les fonctions principales qui sont tres simples à utiliser ...
pour pusher :
push MaValeur call iPush
pour appeler :
push addrMaFonction call iCall
pour remplir une zone memoire :
push Size push addrBuffIn push addrBuffOut call iWriteMem
pour copier une zone memoire :
push size push addrBuffOut push addrMem call iReadMem
pour lancer votre code injecté :
push addrCode call iGo
Enfin un grand merci à
- Kaine (pour les phottes et en plus comme ca, hop, God certified)
- nats' et silma (pour le soutien
)
- virtualabs (pour injmem)
- Squallsurf (sinon il va pas etre content)
- a la RRF en general :p
- a tous ceux sur IRC et sur les differents forums que je frequente
voili voilou
Cette technique sera probablement hookée assez rapidement et n'a finalement pas enormement d'interet mais elle est zoulie et ca me suffit :p
[EDIT : Jeudi 07 Juin 2007] Ajout de la fonction iReadMem et "amélioration" de la fonction de recherche des opcodes , maintenant l'injecteur affiche les 16 premiers bytes injectés (pour faire un petit exemple de l'utilisation de iReadMem)
[EDIT : Samedi 09 Juin 2007] Mise à jour du code de recherche des opcodes, maintenant IINJ ne scanne plus que la section .text de kernel32 .
[EDIT : Vendredi 20 Juin 2008] Mise a jour des sources, le code en asm pourri est toujours disponible mais iinj a été recodé en C
Commentaires
ahah nice
Ca instruit le noob_windowsien que je suis.
Bonne continuation baboon.
Technique novatrice, peu détecté, beau boulot finalement

En espérant qu'elle reste efficace un certains temps
Bon courage pour the second one :P
Amicalement, Squallsurf
Moué pas mal
Bravo baboon
Nickel enfin tout ca je te l'ai deja dit en pv :p
Joli travail (quoique le source est un peu crade) ! Je vais essayer de porter la technique en C++ dans injmem, ca devrait pas poser tellement de problèmes ;).
L'utilisation des Debug APIs reste tout de même flaggée par certains anti-malwares, mais peu au final.
ca y est t'es une leet ma poule :P
bon ben reste a voir combien de temps Eugène et ses comparses vont mettre à réagir, sale terroriste...
Et malgré Léon qui se fait plus attendre qu'une release Blizzard (les développeurs hein) la french touch' reste dans la place :D
wala, wala, à nouveau toutes mes congratz mon ch'tit baboonet...
bibi
Alors

Squallsurf : c'est meme pour le momment pas du tout detecté, jusqu'a preuve du contraire
Virtualabs : Oui mon code est TRES moche :p , je vais mettre quelques petites tabulations et ré-Up le tout
Silma : Les pitits coreens n'ont qu'a bien se tenir :p
[EDIT] Code source mis a jour , j'ai mis quelques tabulations en plus
[EDIT : Jeudi 07 Juin 2007 ] Ajout de la fontion iReadMem
dommage pour ton tricks les moutons sauteur l'ont detecter :DDD kotgw
bravo baboon, ta techique a tenu une semaine tu as donc un gros zizi \o/

héhé, nod32 est à la traine sur ce coup....
kaspersky mérite bien sa réputation de laboratoire le plus réactif au monde...
je trouve quand même qu'ils pourraient envoyer un petit mot aux auteurs quand ils mettent a jour leur bébé: d'abord mon ring0 killer, ensuite ton IINJ... tout ca ne donne pas envie de rendre son travail public...
bisoux baboonet
Juste comme ca
Pour le momment ni Kaspersky ni nod32 ne me detectent
Apres pour les autres anti-virus / pare-feu / anti X je ne sais pas ...
Pourrais tu preciser un peu ton commentaire ji ne sé po ?
GG mec. Et le loader SC marche, c'est surtout ca qui compte \o/
Outpost Pro grille la méthode...
merci okkixot


Je vais voir où je suis grillé
[EDIT] Bon , apres etude , Outpost Pro filtre DebugActiveProcess donc , rien a faire
Enfin je verrais ca en profondeur plus tard ...
On sent l'inspiration de la technique de GhostWriting qui ne nécessite qu'un simple handle sur un Thread du process visé cette fois ci :
et je vous tient au courant.
www.c0ding.fr/blog/?p=4
rootkit.com/newsread.php?...
Dans ton cas tu use DebugActiveProces pour recup les handles sur les thread. Bref le gros problème c'est que souvent les HIDS hook tout les Open*, j'ai p-e une idée pour contouner cela
Sinon sympa comme taff Baboon meme si c'est en asm :p
"On sent l'inspiration de la technique de GhostWriting"
mais on m'en a en effet parle quand j'ai sorti mon IINJ
Ba non ...
Pas du tout
:p
Je ne frequente pas ses deux sites
Sinon je bosse un peu pour contourner les AV qui m'embetent (je pense a emuler un peu mais sans grande conviction ..) mais n'étant pour le momment pas chez moi , je ne peu trop rien faire ...
[EDIT] Je vien de lire l'article sur le GhostWriting , je suis blazé , c'est exactement le meme esprit ....
J'ai juste ré-inventé la roue
C'est pas grave Baboon

Et c'est asm, c'est cool
Pour outpost : C'était un hook ring3 sur DebugActiveProcess.
Mais....
J'ai donc fait un hook hot patching pour sauter par dessus le hook de outpost. Résultat, je l'ai bypass
Quand j'ai dl la dernière version de outpost : même avec le unhook c'est grillé -_-
Avec un Unhook ring0 sur NtOpenProcess + unhook ring3 sur DebugActiveProcess, ca marche.
(on donne le PID à DbgActive... il doit donc faire un *Open je pense)
J'ai pensé a l'api NtDebugActiveProcess qui demande un handle sur le process. Avec IOP, peut être que ca marche. (IOP est pas grillé par outpost) Je continue mes recherches...
N'ayant pas outpost , je ne peu pas trop t'aider
Je vais bidouiller un pitit emulateur d'apis dans pas trop longtemps mais je doute que cela marche avec des AV un tant soit peu evolués qui de toute facon hookent en R0
[EDIT] Bon , ai bidouillé un pitit truc en reunissant IINJ et IOP dans un post au dessus , j'exposerai dans pas trop longtemps une technique anti-hook ring3 (qui les fait tous sauter :p)
Je viens d'y penser ...
chti hack avait codé une méthode original pour le unhook ring3.
(ils sont tous sauter aussi :p)
trojanfrance.com/Sources/...
eheh

pas con !
Sinon pour OutPost , il est TRES simple de virer les hook , un freelibrary avec une petite astuce et hop , plus de hooks
mais a ce momment là , c'est un unhook specifique
Là je bosse sur un loablibrary maison recursif , plus besoin de copier/coller quoique ce soit
Et on donne un bonon à Baboon \o/