HOOKING SOUS NT AVEC CREATEREMOTETHREAD (VC++7, COMPILABLE AC LE 6 AUSSI)
Utilisateur anonyme
-
26 mai 2003 à 20:56
taye78
Messages postés106Date d'inscriptionmardi 18 juin 2002StatutMembreDernière intervention13 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.
taye78
Messages postés106Date d'inscriptionmardi 18 juin 2002StatutMembreDernière intervention13 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és16Date d'inscriptionvendredi 27 juin 2003StatutMembreDernière intervention19 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:
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és338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 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és7Date d'inscriptiondimanche 29 décembre 2002StatutMembreDernière intervention12 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).
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és338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 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és16Date d'inscriptionvendredi 27 juin 2003StatutMembreDernière intervention19 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?
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és19Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention22 janvier 2009 12 juin 2004 à 19:19
BlackGoddess
Messages postés338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 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és19Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention22 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
Compiler en release et non en debug (je l'ai dit au dessus)
lolman27
Messages postés19Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention22 janvier 2009 12 juin 2004 à 01:26
salut j utilise vc ++ 6
Le processus cible plante systematiquement que faire?^^
BlackGoddess
Messages postés338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 juin 2005 16 juin 2003 à 23:22
np lol
cs_pow
Messages postés7Date d'inscriptiondimanche 29 décembre 2002StatutMembreDernière intervention12 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és338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 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és7Date d'inscriptiondimanche 29 décembre 2002StatutMembreDernière intervention12 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és338Date d'inscriptionjeudi 22 août 2002StatutMembreDernière intervention14 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').
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 ?
12 mai 2006 à 02:31
"
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+
22 nov. 2004 à 12:40
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
18 nov. 2004 à 19:16
16 nov. 2004 à 11:14
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)
15 nov. 2004 à 18:57
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 ...
15 nov. 2004 à 12:30
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??
12 juin 2004 à 19:19
12 juin 2004 à 19:08
http://www.freecodz.net/articles/CodeInjection.html
12 juin 2004 à 18:33
puis utilises ce bout de code pour charger la dll
12 juin 2004 à 11:14
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
12 juin 2004 à 09:27
12 juin 2004 à 01:26
Le processus cible plante systematiquement que faire?^^
16 juin 2003 à 23:22
16 juin 2003 à 14:38
Faire un projet application windows, et renommer la fonction Main, en une fonction main.
Vala, pas plus compliqué que cela :]
(encore désolé)
16 juin 2003 à 10:28
il faut donc rajouter, ds la ligne de commande du linker /entry:Main
16 juin 2003 à 10:18
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 :]
27 mai 2003 à 09:45
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').
26 mai 2003 à 20:56
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