Hooking sous nt avec createremotethread (vc++7, compilable ac le 6 aussi)

Soyez le premier à donner votre avis sur cette source.

Vue 7 064 fois - Téléchargée 307 fois

Description

bin ... ya pas grand chose a dire ...
l'executable copie une partie de son code dans la mémoire du process 'cible', et l'execute

Source / Exemple :


// code compilé avec vc++7
// c compilable aussi sur le 6, mais a vous de jouer avec les options du compilo pour que ca marche
#include <windows.h>

typedef HMODULE (WINAPI* fnLoadLibrary)(LPCTSTR LibName);
typedef FARPROC (WINAPI* fnGetProcAddress)(HMODULE hLib, LPCTSTR FuncName);
typedef int (WINAPI* fnMessageBox)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
typedef BOOL (WINAPI* fnFreeLibrary)(HMODULE hLib);
typedef void (WINAPI* fnExitThread)(DWORD dwxitCode);

typedef struct InJack
{
	fnLoadLibrary pLoadLibrary;
	fnGetProcAddress pGetProcAddress;
} InJack, *pInJack;

static DWORD WINAPI RemoteEntry(pInJack Data)
{
	// vc++ (6 et 7) alloue la mémoire ds le code avec cette méthode, ainsi on a pas de lien vers le segment de données (qui n'est pas copié)
	char szUser[] = {'u','s','e','r','3','2',0};
	char szMsgBox[] = {'M','e','s','s','a','g','e','B','o','x','A',0};
	char szKernel[] = {'k','e','r','n','e','l','3','2',0};
	char szFreeLib[] = {'F','r','e','e','L','i','b','r','a','r','y',0};
	char szExitThread[] = {'E','x','i','t','T','h','r','e','a','d',0};

	HMODULE hKern = Data->pLoadLibrary(szKernel);
	fnFreeLibrary pFreeLibrary = (fnFreeLibrary)Data->pGetProcAddress(hKern, szFreeLib);
	fnExitThread pExitThread = (fnExitThread)Data->pGetProcAddress(hKern, szExitThread);
	pFreeLibrary(hKern);

	HMODULE hUser = Data->pLoadLibrary(szUser);
	fnMessageBox pMessageBox = (fnMessageBox)Data->pGetProcAddress(hUser, szMsgBox);

	pMessageBox(NULL, szUser, szMsgBox, NULL);

	pFreeLibrary(hUser);
	
	pExitThread(0); 
	// apparement sinon il aime pas le return 0, il fait une violation mémoire
	// il me semble que le compilo ne l'ait pas pris en compte ...
	return 0;
}

static void EndRemoteEntry() {}

void Main()
{
	BOOL k;
	
	// on ouvre le processus
	HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 1356); // pid du process ... (ds le gestionnaire des tâches)
	int cbCodeSize = ((LPBYTE) EndRemoteEntry - (LPBYTE) RemoteEntry);
	
	// on copie le code
	LPVOID CodeMem = VirtualAllocEx(hProc, NULL, cbCodeSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	k = WriteProcessMemory(hProc, CodeMem, &RemoteEntry, cbCodeSize, 0);
	
	// on remplit les données
	InJack Data;
	HMODULE hKern = LoadLibrary("kernel32");
	Data.pGetProcAddress = (fnGetProcAddress)GetProcAddress(hKern, "GetProcAddress");
	Data.pLoadLibrary = (fnLoadLibrary)GetProcAddress(hKern, "LoadLibraryA");
	FreeLibrary(hKern);

	LPVOID DataMem = VirtualAllocEx(hProc, NULL, sizeof(Data), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
	k = WriteProcessMemory(hProc, DataMem, &Data, sizeof(Data), 0);

	DWORD ThreadID;
	HANDLE hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)CodeMem, DataMem, 0, &ThreadID);
	CloseHandle(hThread);
}

Conclusion :


Dites moi si vous avez d'autres méthodes / des améliorations :)

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
106
Date d'inscription
mardi 18 juin 2002
Statut
Membre
Dernière intervention
13 janvier 2007

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+
Messages postés
16
Date d'inscription
vendredi 27 juin 2003
Statut
Membre
Dernière intervention
19 novembre 2006

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
Messages postés
338
Date d'inscription
jeudi 22 août 2002
Statut
Membre
Dernière intervention
14 juin 2005

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)
Messages postés
7
Date d'inscription
dimanche 29 décembre 2002
Statut
Membre
Dernière intervention
12 janvier 2007

"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)
Messages postés
338
Date d'inscription
jeudi 22 août 2002
Statut
Membre
Dernière intervention
14 juin 2005

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 ...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.