1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Lycéen
    Inscrit en
    décembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : décembre 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut Problème Injection Dll Windows

    Bonjour,
    Je commence avec l'API Windows et je me suis lancé dans un projet d'injection de DLL. Le but du projet est simplement d'injecter une DLL qui interagit avec la sortie standard du processus cible (pour prouver la réussite de l'opération). Le problème est que, malgré aucune erreur apparente, aucun message n'est affiché dans la console du processus cible. Voici mon code:

    DLL.dll
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    #include <windows.h>
    #include <iostream>
     
    #define DLL_EXPORT extern "C"
     
     
    DLL_EXPORT BOOL _stdcall DllMain(
    	_In_ HINSTANCE hinstDLL,
    	_In_ DWORD fdwReason,
    	_In_ LPVOID lpvReserved)
    {
    	std::cout << "dll correctly loaded" << std::endl;
    	return TRUE;
    }

    Injector.cpp
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    #include <iostream>
    #include <string>
     
    #include <windows.h>
    #include <tlhelp32.h>
    #include <tchar.h>
     
     
    const std::string process_name = "console_target.exe";
     
    int main(int argc, char* argv[])
    {
    	const DWORD BUFSIZE = 4096;
    	TCHAR dllPath[BUFSIZE] = TEXT("");
    	TCHAR size = GetFullPathName(_T("DLL.dll"), BUFSIZE, dllPath, NULL);
     
    	std::wstring processName(process_name.begin(), process_name.end());
     
    	PROCESSENTRY32 processInfo;
    	processInfo.dwSize = sizeof(processInfo);
     
    	HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    	if (processesSnapshot == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Failed to create the processes snapshot: " << GetLastError() << std::endl;
    		system("pause");
    		return EXIT_FAILURE;
    	}
     
    	DWORD procID = -1;
    	Process32First(processesSnapshot, &processInfo);
    	if (!processName.compare(processInfo.szExeFile))
    	{
    		CloseHandle(processesSnapshot);
    		procID = processInfo.th32ProcessID;
    	}
    	while (Process32Next(processesSnapshot, &processInfo))
    	{
    		if (!processName.compare(processInfo.szExeFile))
    		{
    			CloseHandle(processesSnapshot);
    			procID = processInfo.th32ProcessID;
    		}
    	}
     
    	if (procID == -1)
    	{
    		CloseHandle(processesSnapshot);
    		std::cerr << "Failed to get the process ID: " << GetLastError() << std::endl;
    		system("pause");
    		return EXIT_FAILURE;
    	}
     
    	HANDLE process = OpenProcess(PROCESS_CREATE_THREAD
    							| PROCESS_QUERY_INFORMATION
    							| PROCESS_VM_OPERATION
    							| PROCESS_VM_WRITE
    							| PROCESS_VM_READ, FALSE, procID);
     
    	if (process == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Failed to open the process: " << GetLastError() << std::endl;
    		system("pause");
    		return EXIT_FAILURE;
    	}
     
    	LPVOID remoteDllAddr = VirtualAllocEx(process, NULL, wcslen(dllPath) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	if (!WriteProcessMemory(process, remoteDllAddr, dllPath, wcslen(dllPath) + 1, NULL))
    	{
    		std::cerr << "Failed to write in the process memory: " << GetLastError() << std::endl;
    		system("pause");
    		return EXIT_FAILURE;
    	}
     
    	FARPROC startAddr = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
     
    	HANDLE rThread = CreateRemoteThread(process, NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(startAddr), remoteDllAddr, 0, NULL);
    	WaitForSingleObject(rThread, INFINITE);
     
    	if (rThread == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Failed to create the remote thread: " << GetLastError() << std::endl;
    		system("pause");
    		return EXIT_FAILURE;
    	}
     
    	CloseHandle(process);
     
    	std::cout << "The dll have been successfully injected" << std::endl;
    	system("pause");
    	return EXIT_SUCCESS;
    }

    console_target.cpp
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int main(int argc, char* argv[])
    {
    	while (true) {}
    	return 0;
    }

    Je pense que l'erreur vient de "Injector.cpp" car j'ai testé la DLL et elle fonctionne correctement (il me semble). Voici le code de test:

    Loader.cpp
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include <windows.h>
    #include <tchar.h>
     
    int main(int argc, char* argv[])
    {
    	HMODULE dll = LoadLibrary(_T("DLL.dll"));
     
    	system("pause");
    	return 0;
    }

    On obtient alors la sortie attendue lors de l'exécution: "dll correctly loaded"

    Dans tous les cas la DLL est bien placée dans le même répertoire que l'exécutable.
    Merci par avance.

    PS: je sais que l'utilisation de la fonction system() n'est pas sûre mais c'est le moindre de mes problèmes pour le moment.

  2. #2
    Expert éminent sénior

    Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    6 186
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : novembre 2006
    Messages : 6 186
    Points : 11 916
    Points
    11 916

    Par défaut

    salut dans injector.cpp
    pourquoi utiliser des std::string donc des char améliorés d'un côté et des wstring donc des wchar_t de l'autre ?
    Ensuite créer une appli console de test c'est pas terrible parce qu'effectivement il faut pauser avec system() et en win32 le programme rend la main...
    avec une appli fenêtrée en win32 ( sous visual Studio c'est facile à créer ) tu peux rajouter des zones de textes c'est plus souple
    Ensuite il faudrait mettre des breakpoints et déboguer pas-à-pas; j'aurais pu tester les lignes de code postées mais je n'ai pas Visual Studio sous la main ( pas avant la semaine prochaine )
    * Descartes: "je pense donc je suis"
    * Bob l'éponge : "je pense donc j'essuie"
    * l'infirmière : "je panse donc je suis"

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Lycéen
    Inscrit en
    décembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : décembre 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Merci d'avoir pris le temps de répondre. Je vais tenter de mettre en oeuvre vos suggestions.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 383
    Points : 37 865
    Points
    37 865

    Par défaut

    Comme le dit Mat. M, ton code se trompe entre wchar_t et char.

    Tu alloues la mémoire avec une taille basée sur wcslen() (sans tenir compte de la taille d'un wchar_t, d'ailleurs), puis tu appelles LoadLibraryA()...

    Pour ce genre de chose, tu devrais bosser avec des wchar_t partout, prendre en compte leur taille dans tes allocations mémoire et tes copies, et appeler LoadLibraryW().

    Edit: De plus, tu n'es pas censé faire quoi que ce soit dans DllMain() qui dépende d'autre chose que Kernel32. Je te conseille d'y faire un CreateThread() pour ta vraie payload (du fait de la nécessité d'appeler les DllMain() pour les nouveaux threads, le nouveau thread devrait démarrer après que ton DllMain() ait retourné). Ou mieux, tu pourrais mettre ta payload dans une autre fonction de la DLL chargée.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Lycéen
    Inscrit en
    décembre 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : décembre 2016
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Comme le dit Mat. M, ton code se trompe entre wchar_t et char.
    Effectivement, j'ai modifié mon code suite à la réponse de Mat.M. Cela n'a cependant pas résolu le problème.

    Pour ce genre de chose, tu devrais bosser avec des wchar_t partout, prendre en compte leur taille dans tes allocations mémoire et tes copies, et appeler LoadLibraryW().
    Je vais mettre ça en oeuvre.

    Edit: De plus, tu n'es pas censé faire quoi que ce soit dans DllMain() qui dépende d'autre chose que Kernel32.
    En effet, j'avais oublié.

    Edit: [...] Je te conseille d'y faire un CreateThread() pour ta vraie payload (du fait de la nécessité d'appeler les DllMain() pour les nouveaux threads, le nouveau thread devrait démarrer après que ton DllMain() ait retourné). Ou mieux, tu pourrais mettre ta payload dans une autre fonction de la DLL chargée.
    Je n'ai pas tout compris.
    Qu'appelles-tu "payload"?
    Tu me suggères de créer un thread dans DllMain() pour exécuter une autre fonction de la DLL?

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 383
    Points : 37 865
    Points
    37 865

    Par défaut

    Tu me suggères de créer un thread dans DllMain() pour exécuter une autre fonction de la DLL?
    Oui, parce que le thread ne démarrera qu'une fois tous les DllMain() exécutés et finis.

    Et par "payload", je voulais dire ton code actuel de DllMain() (le std::cout << "dll correctly loaded" << std::endl;).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    avril 2004
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : avril 2004
    Messages : 339
    Points : 172
    Points
    172

    Par défaut

    Au cas où ça peut aider, j'ai codé un petit programme faisant comme l'outil 'memcheck' de valgrind (en moins puissant), et qui utilise une injection de dll. Il y a même une biblithèque que tu peux utiliser directement pour injecter une DLL (mon programme l'utilise). Le code se trouve ici.
    L'Opus attire les Prélats

Discussions similaires

  1. Problème de EZTW32.dll Windows 7
    Par Chrysostome dans le forum Access
    Réponses: 0
    Dernier message: 30/11/2012, 11h35
  2. Windows Mobile problème de dll
    Par asnaeb dans le forum Windows Mobile
    Réponses: 1
    Dernier message: 10/03/2011, 15h33
  3. Injecter dll dans windows, dragdropevent hanlder
    Par alpha_one_x86 dans le forum C++
    Réponses: 7
    Dernier message: 12/11/2008, 09h22
  4. Problème de DLL WMI sous Windows 2000 pro
    Par manwax dans le forum API, COM et SDKs
    Réponses: 8
    Dernier message: 11/03/2008, 15h32
  5. Problème de DLL.
    Par Lunedor dans le forum C++Builder
    Réponses: 2
    Dernier message: 29/11/2003, 10h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo