HOOKING SOUS NT AVEC CREATEREMOTETHREAD (VC++7, COMPILABLE AC LE 6 AUSSI)

Utilisateur anonyme - 26 mai 2003 à 20:56
taye78 Messages postés 106 Date d'inscription mardi 18 juin 2002 Statut Membre Dernière intervention 13 janvier 2007 - 12 mai 2006 à 02:31
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/10743-hooking-sous-nt-avec-createremotethread-vc-7-compilable-ac-le-6-aussi

taye78 Messages postés 106 Date d'inscription mardi 18 juin 2002 Statut Membre Dernière intervention 13 janvier 2007
12 mai 2006 à 02:31
salut, bon qqs années après... hehe
"
int cbCodeSize = ((LPBYTE) EndRemoteEntry - (LPBYTE) RemoteEntry);
"
Içi tu supposes l'ordre des fonctions en mémoire(l'une apres lautre). Cependant, le linker peut changer l'ordre des fonctions, il peut par exemple mettre RemoteEntry avant EndRemoteEntry. Ce qui planterait le process cible!
Malgrés l'option /ORDER cela reste considere "risque".

Bon code, 9/10, a+
cancooler Messages postés 16 Date d'inscription vendredi 27 juin 2003 Statut Membre Dernière intervention 19 novembre 2006
22 nov. 2004 à 12:40
Bon maintenant que j'en sais un peu plus, quelques petites modifs sont a apporter a ton code pour le rendre 'clean'- j'espere que tu m'en voudras pas ;) -

D'abord, le flag "MEM_COMMIT" est suffisant pour l'appel a VirtualAllocEx: la memoire sera reservee uniquement dans l'espace memoire virtuel du process cible.

Ensuite pour ne pas laisser de trace, il faut faire appel a VirtualFreeEx de cette facon:

VirtualFreeEx(hProc, CodeMem, 0, MEM_RELEASE);
VirtualFreeEx(hProc, DataMem, 0, MEM_RELEASE);

Mais attention, il faut etre sur que le remote thread ait bien termine son execution: pour cela on place un

WaitForSingleObject(hThread, INFINITE);

avant l'appel a VirtualFreeEx.

Enfin un CloseHandle(hProc); pour finir.


L'injection dans un process systeme fonctionne egalement - pas pour tous a priori et certains aiment pas du tout!.
Pour l'affichage de la MsgBox par ex, je recupere le hWnd de la TaskBar ( avec un FindWindow(TEXT("Shell_TrayWnd"),NULL); ) et je rajoute un champ HWND phWnd dans la struct InJack, par ex...

Pour finir je conseille a quiconque voulant *tout* savoir sur l'injection de code l'excellent article de Robert Kuster : "Three Ways to Inject Your Code into Another Process" a l'@: http://www.codeproject.com/threads/winspy.asp
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
18 nov. 2004 à 19:16
le problème est qu'un process systeme de dépend pas d'un utilisateur, aussi il ne sait pas dans quel contexte afficher la fenetre (sur quelle session utilisateur)
cs_pow Messages postés 7 Date d'inscription dimanche 29 décembre 2002 Statut Membre Dernière intervention 12 janvier 2007
16 nov. 2004 à 11:14
"lorsque je veux afficher une MsgBox par ex en passant par un process systeme, le code est execute sans plantage, le signal sonore de la MsgBox est la, mais pas de MsgBox a l'ecran!?! Explications pliz??"

Imo, ca c'est parsque le process cible n'a pas d'handle parent (genre pas de gestion des events/fenetres).

int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);

le premier parametre doit être un handle vers une fenetre parent, j'ai eu des cas où en mettant null, cela ne fonctionnait pas... (probleme que tu décris)
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
15 nov. 2004 à 18:57
mmh c'est en effet un problème ... je ne vois aucun moyen d'y parvenir ...

si tu libères ta propre mémoire, au retour du VirtualFreeEx, le pointeur d'execution pointera vers une adresse de la mémoire libérée, donc désormais inaccessible.

charger une dll puis appeler une fonction exportée qui libérerait la mémoire et ferait un ExitThread pour etre dur que le pointeur ne revienne jamais ?
mais la dll resterait chargée pour le processus hôte, on tourne en rond ...
cancooler Messages postés 16 Date d'inscription vendredi 27 juin 2003 Statut Membre Dernière intervention 19 novembre 2006
15 nov. 2004 à 12:30
Tres interessant ce code: clair et efficace, bravo :)

Bon deux petites questions:

no1 - Que devient la memoire allouee dans le process cible lorsque le remote thread se termine?

J'ai essayer d'utiliser la fonction

VirtualFreeEx(hProc, CodeMem, 0, MEM_RELEASE )
ou
VirtualFreeEx(hProc, CodeMem, cbCodeSize, MEM_DECOMMIT )

Dans les deux cas il en resulte un plantage du process cible bien que la fonction VirtualFreeEx semble executee avec succes!?!


no2- J'ai ajoute la fonction suivante au debut de ton main: comme son nom l'indique elle permet d'activer les privileges 'debug'

bool EnableDebugPrivileges( void )
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;

if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
//SeDebugPrivilege is not available
return 0;
}

if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
//SeDebugPrivilege is not available
return 0;
}

tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
{
//SeDebugPrivilege is not available
CloseHandle( hToken );
return 0;
}



CloseHandle( hToken );

return 1;
}


Interet? Avec l'utilisation de cette fonction il est possible de creer un remote thread dans un process system. Donc a priori executer des instructions privilegiees...C cool mais bon be careful le systeme plante facilement suivant le process cible :))
Cependant, lorsque je veux afficher une MsgBox par ex en passant par un process systeme, le code est execute sans plantage, le signal sonore de la MsgBox est la, mais pas de MsgBox a l'ecran!?! Explications pliz??
lolman27 Messages postés 19 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 22 janvier 2009
12 juin 2004 à 19:19
merci bien
Utilisateur anonyme
12 juin 2004 à 19:08
La technique est décrite ici :
http://www.freecodz.net/articles/CodeInjection.html
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
12 juin 2004 à 18:33
utilises une dll pour faire ton "application" (dont les sockets)
puis utilises ce bout de code pour charger la dll
lolman27 Messages postés 19 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 22 janvier 2009
12 juin 2004 à 11:14
Exact .J arrive a faire tourner le code,et jai peu pres compris ms je n arrive pas a coder ce que je veux faire...
C est a dire charger un socket ds le prog cible et l utilise depuis le process principale...
Le pb c que je suis pas(encore ;)) une bete en c++
Un peu d aide ne serait pas de refus :P thx
msn: lolman27@hotmail.com
Utilisateur anonyme
12 juin 2004 à 09:27
Compiler en release et non en debug (je l'ai dit au dessus)
lolman27 Messages postés 19 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 22 janvier 2009
12 juin 2004 à 01:26
salut j utilise vc ++ 6
Le processus cible plante systematiquement que faire?^^
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
16 juin 2003 à 23:22
np lol
cs_pow Messages postés 7 Date d'inscription dimanche 29 décembre 2002 Statut Membre Dernière intervention 12 janvier 2007
16 juin 2003 à 14:38
Oui, ben en fait j'ai trouvé la solution :{
Faire un projet application windows, et renommer la fonction Main, en une fonction main.
Vala, pas plus compliqué que cela :]
(encore désolé)
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
16 juin 2003 à 10:28
tu as ignoré toutes les libs par defaut comme j'avais dit pour avoir cette erreur.

il faut donc rajouter, ds la ligne de commande du linker /entry:Main
cs_pow Messages postés 7 Date d'inscription dimanche 29 décembre 2002 Statut Membre Dernière intervention 12 janvier 2007
16 juin 2003 à 10:18
Code très interessant, cependant je n'utilise pas Visual .net, et avec ma version 6.0, j'obtiens ce message en projet console :

error LNK2001: unresolved external symbol _main

si je passe en application windows :

error LNK2001: unresolved external symbol _WinMain@16

Quelqu'un aurait une solution?

Merci d'avance :]
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
27 mai 2003 à 09:45
alors ... j'essaye d'expliquer :)

un fichier est composé de plusieurs sections, dont le header, le code, les data (pour ce qui nous interresse). un .exe est en général chargé a l'offset 400000 (en hexa). donc, pour lui, il pourra par exemple appeler l'offset 410000, et ca pointera ds le segment de data sur une chaine.

dans le processus cible, je n'ai copié que la fonction RemoteEntry, en effet, il ne sera de toutes facons pas copié a l'offset 400000 (etant deja occupé par le processus cible), donc tout ses appels à d'autres sections seront erronés -> plantage.

spécialement sou vc++ (ca marche p-e avec d'autre compilo), qd on déclare char *szUser = "user32"; il ecrit user32 dans le segment de data, et szUser devient un pointeur vers le 'u' dans le segment.

par contre, lorsqu'on déclare char szUser[] = {'u','s','e','r','3','2',0}; le compilo alloue directement les lettres une par une dans la pile par leur code ascii, donc il n'y a pas d'appel vers aucun segment.

ah, oui, qd je parle d'offset 400000, chaque processus est chargé à partir de l'offset 400000 (du moins c'est ce qu'il voit). en effet, la mémoire d'un processus n'est pas accessible aux autres (sauf cas exceptionnels).

voila, donc avec l'astuce char szUser[] = {'u','s','e','r','3','2',0}; on peut eviter les appels aux data pour les chaines. reste plus que faire pareil pour les appels de fonctions. pour cela, j'ai créé une structure dans laquel j'ai mis les adresses de GetProcAddress et LoadLibrary (cette lib etant chargée en mémoire 'partagée' .Je n'ai pas encore super bien compris le concept, mais je sais que kernel32.dll est TJS chargée au mm endroit par OS (WinMe = BFF60000 par exemple il me semble). ensuite, on ecrit donc le contenu de la structure (les 2 adresses) dans la mémoire qu'on a alloué ds le processus cible, et on envoit en paramètre de la fonction injecté un ptr vers cette structure.

ensuite, avec ces 2 api, on peut charger toutes les dll qu'on veut.

donc, ceci est juste un exemple, mais on peut faire pas mal de choses dans le processus cible. (d'apres les MSDN, CreateRemoteThread a été créé pour le débogage ... qd on cherche sur le net, on voit que bcp de code de virus l'utilise. cette api n'est pas supportée par win 9x, elle existe fait elle retourne tjs FALSE avec en GetLastError 'non pris en charge par le système').
Utilisateur anonyme
26 mai 2003 à 20:56
Toutes mes félicitations, ton code marche et c pas partout qu'on trouve des choses de ce genre.
Petite précision pour VC++ 6 : compiler en release sans quoi ce code devient un trés bon killer de processus ;-)
Sinon, pourrais tu commenter un peu + le code ?
Nous dire par exemple à quoi servent les fonctons et à quoi correspondent les paramètres ?
Détal bizarre : pourquoi faut il initialiser les variables d'une manière barbare {'?','?','?'} plutot que d'utiliser la manière habituelle "user32" ?
Je vois bien que sa plante mais pourquoi ?

merci d'avance et encore bravo :-D
Rejoignez-nous