IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

Erreur avec ReadProcessMemory


Sujet :

Windows

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut Erreur avec ReadProcessMemory
    Bonjour,

    je cherche à récupérer les valeurs des variables utilisées par un autre processus (processus appelé ici "FT").

    Voici le code :
    Code : 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
    int main()
    {
        // Variables
        STARTUPINFO startupInfo; // Information about the FT startup
        PROCESS_INFORMATION processInformation; // Information about the FT process
        MEMORY_BASIC_INFORMATION memoryBasicInformation; // Basic information about the memory of the FT process
    
        // Initialize the STARTUPINFO structure for the FT process
        memset(&startupInfo, 0, sizeof(startupInfo));
        startupInfo.cb = sizeof(startupInfo);
    
        // Create the FT process
        if(
            CreateProcess(NULL,
                "FT_Client.exe 0",
                NULL,
                NULL,
                TRUE,
                CREATE_BREAKAWAY_FROM_JOB,
                NULL,
                NULL,
                &startupInfo,
                &processInformation
            )
        ==0){
            cout << "Unable to create the FT process : " << GetLastError() << endl;
            return(-1);
        }
    
        // Display the FT process Id
        cout << "FT process Id : " << processInformation.dwProcessId << endl;
    
        // Get basic information about the memory of the FT process
        if(
            VirtualQueryEx(processInformation.hProcess,
                NULL,
                &memoryBasicInformation,
                sizeof(memoryBasicInformation)
            )
        == 0){
            cout << "Unable to get basic information about the memory of the FT process :" << GetLastError();
            return(-1);
        }
    
        // Read the FT process memory
        if(
            ReadProcessMemory(processInformation.hProcess,
                &memoryBasicInformation.BaseAddress,
                &memoryBasicInformation,
                sizeof(memoryBasicInformation),
                NULL
            )
        ==0){
            cout << "Unable to read the FT process memory : " << GetLastError() << endl;
            return(-1);
        }
    
        // Close the FT process handle
        if(CloseHandle(processInformation.hProcess)==0){
            cout << "Unable to close the FT process handle : " << GetLastError() << endl;
            return(-1);
        }
    
        return 0;
    }
    Le résultat sur le flux de sortie standard est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FT process Id : 2008
    Unable to read the FT process memory : 299
    L'erreur 299 signifie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ERROR_PARTIAL_COPY 
    299 (0x12B) Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
    Donc il semble y avoir un problème au moment de la lecture de la mémoire utilisée par le processus FT.

    Voyez-vous une (ou plusieurs) erreur dans mon code?

    Merci bien.

  2. #2
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    Bonjour,

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        if(
            ReadProcessMemory(processInformation.hProcess,
                &memoryBasicInformation.BaseAddress,
                &memoryBasicInformation,
                sizeof(memoryBasicInformation),
                NULL
            )

    1) Tu essaye de lire dans le processus cible à l'adresse où se situe &memoryBasicInformation.baseAddress, ce qui n'a pas beaucoup de sens

    solution: enlève le '&'

    2) N'utilise pas memoryBasicInformation comme buffer de sortie non plus !

    solution: alloue un buffer (new ou une API windows type VirtualAlloc()) pour y mettre les données en sortie de ReadProcessMemory()

    3) Si tu passes NULL à VirtualQueryEx comme deuxième param. il va te donner les informations concernant la page à l'adresse 0, et celle-ci on ne peut pas y lire grand chose.

    solution: tout dépend de l'adresse que tu veux lire... Si tu veux lire dans le processus cible, commence par trouver l'adresse de base où est mappé le programme.

  3. #3
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Pour le 1), je suis tout à fait d'accord. memoryBasicInformation.BaseAddress pointe déjà vers l'adresse de base qui m'intéresse. Le '&' n'a donc rien à faire ici. Je viens de le retirer.

    Pour le 2), utiliser memoryBasicInformation comme buffer est une erreur je te l'accorde. En effet, memoryBasicInformation n'est qu'une structure qui est sensée contenir seulement des informations sur l'usage de la mémoire d'un processus. J'ai donc créé un tableau de char de taille 100 en espérant que ça fera l'affaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char buffer[100];
    ...
    ReadProcessMemory(processInformation.hProcess,
                memoryBasicInformation.BaseAddress,
                buffer,
                sizeof(buffer),
                NULL
    )
    Pour le 3), j'essaye de passer à VirtualQueryEx l'adresse de base de mon processus cible, mais il est difficile de la trouver. En effet, la structure memoryBasicInformation ne contient pas cette information. La fonction GetSystemInfo qui récupère une structure SYSTEM_INFO ne semble pas contenir cette information également. Enfin, processInformation qui est une structure PROCESS_INFORMATION ne contient pas non plus l'adresse de base de mon processus.

    Donc au final, je cherche à savoir :
    -comment créer un buffer pour ReadProcessMemory de façon plus propre? (un tableau de char de taille 100 ne doit pas être une bonne solution)
    -comment trouver l'adresse de base de mon processus cible?

  4. #4
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    Hello,

    ne sachant pas trop ce que tu souhaites, j'ai codé un petit truc vite fait.

    Cela démarre un processus (calc.exe en l'occurrence) et affiche quelque infos sur les modules chargés dans l'espace d'adressage du processus.

    On récupère ensuite l'adresse de base du module principal et on lit la totalité de la page (soit 4096 octets) à cette même adresse.

    Code c++ : 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
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
     
    #include <windows.h>
    #include <iostream>
    #include <psapi.h>
    #include <string>
     
    using namespace std;
     
    #ifdef _UNICODE
    #define _tcout std::wcout
    #define _tstring std::wstring
    #else
    #define _tcout std::cout
    #define _tstring std::string
    #endif
     
    PVOID FindProcessBaseAddress(HANDLE hProcess);
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        // various structs init
    	STARTUPINFO startupInfo = {0}; 
    	PROCESS_INFORMATION processInformation = {0};
    	MEMORY_BASIC_INFORMATION meminfo = {0};
     
     
        // Initialize the STARTUPINFO structure
        memset(&startupInfo, 0, sizeof(startupInfo));
        startupInfo.cb = sizeof(startupInfo);
     
        // Create the desired process
        if(
    		CreateProcess(_T("C:\\windows\\system32\\calc.exe"),
                NULL,
                NULL,
                NULL,
                TRUE,
                0,
                NULL,
                NULL,
                &startupInfo,
                &processInformation) == 0 )
    	{
            cout << "Unable to create the FT process : " << GetLastError() << endl;
            return -1;
        }
     
        // Display the process Id
        cout << "Process Id : " << processInformation.dwProcessId << endl;
     
    	// if it's too quick, our process can't read remote process modules info, so wait a little bit.
    	Sleep(1000);
     
    	// get exe base address (and print some info)
    	PVOID exeBaseAddress = FindProcessBaseAddress(processInformation.hProcess);
     
    	// get page info at exe base address
    	VirtualQueryEx(processInformation.hProcess, exeBaseAddress, &meminfo, sizeof(MEMORY_BASIC_INFORMATION));
     
    	// alloc some room for bytes to read
    	PVOID pMembytes = VirtualAlloc(NULL, meminfo.RegionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
     
    	//read proc memory at base address
    	DWORD nobr = 0;
    	ReadProcessMemory(processInformation.hProcess, exeBaseAddress, pMembytes, meminfo.RegionSize, &nobr);
     
    	//release buffer
    	VirtualFree(pMembytes, 0, MEM_RELEASE);
     
        return 0;
     
    }
     
    PVOID FindProcessBaseAddress(HANDLE hProcess)
    {
    	DWORD cbNeeded = 0;
    	SIZE_T Number_of_HMODS = 1024 * sizeof(HMODULE);//array can hold 1024 HMODULES
    	MODULEINFO ModuleInfo = {0};
    	PVOID exeBase = NULL;
    	_tstring exeExtension = _T(".exe");
     
    	//allocate array for all HMODULEs in the process
    	HMODULE * pModules = (HMODULE *) VirtualAlloc(NULL, Number_of_HMODS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
     
    	std::wstring module_name(MAX_PATH * sizeof(TCHAR), '\0');
     
    	// enum all process modules (.exe + .dll)
        if( EnumProcessModulesEx(hProcess, pModules, Number_of_HMODS, &cbNeeded, LIST_MODULES_ALL))
        {
            for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
            {
    			// get info about module
    			GetModuleInformation(hProcess, pModules[i], &ModuleInfo, sizeof(MODULEINFO));
    			// get its name
    			GetModuleFileNameEx(hProcess, pModules[i], &module_name.at(0), MAX_PATH * sizeof(TCHAR));
     
    			// print info and name
    			_tcout << _T("[+] Found module: ") << module_name.c_str() << endl;
    			_tcout << _T("\tModule base: 0x") << hex << ModuleInfo.lpBaseOfDll << endl;
     
    			//just check if it ends with ".exe" (there's only one '*.exe' by process!)
    			int pos = module_name.find(exeExtension);
    			if(pos != _tstring::npos)
    			{
    				// found executable base address!
    				exeBase = ModuleInfo.lpBaseOfDll;
    			}
            }
        }
     
    	//free buffer
    	VirtualFree(pModules, 0, MEM_RELEASE);
     
    	return exeBase;
    }

  5. #5
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Hum... Je comprends pourquoi j'avais du mal à trouver facilement mon adresse de base du processus.

    En lisant ton code, je vois que pour la trouver, tu as eu besoin de créer une fonction dédiée à cette tâche qui utilise plusieurs fonctions (VirtualAlloc, EnumProccessModule, GetModuleInformation). Aussi dans la structure MODULEINFO, il semble que ce soit le membre lpBaseOfDll qui corresponde à l'adresse de base que je cherche.

    Je ne sais pas ce que c'est qu'un module... Apparemment un processus possède plusieurs modules... Un module est caractérisé par une adresse de base.

    Il faut donc que pour chaque module de mon processus, j'en extrait l'adresse de base, ce qui me permettra ensuite de les lire un par un avec la fonction ReadProcessMemory.

    Ça doit être quelque chose dans le genre... Bref je vais analyser tout ça en détails et tester.

    Je rappel que mon objectif est simplement de lire des valeurs utilisées par le processus cible. J'aimerai bien les afficher dans la console. Par exemple, si dans le processus FT, il y a une valeur '115' qui correspond au nombre de pièces d'or du joueur, j'aimerai afficher : "Golds : 115" dans le flux de sortie standard.

    Qui peut m'expliquer ce que c'est qu'un "module" pour un processus donné qui lit et écrit dans sa zone mémoire?

  6. #6
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par défaut
    D'une manière générale (encore que sous ces acceptions, les termes sont plutôt orientes pour Windows):

    - Un processus est un conteneur qui dispose d'un espace d'adressage (ce qui fait qu'un processus croit disposer de toute la mémoire disponible) et contient des threads.

    - Un thread est une unité d'exécution de code.

    - Un module est une entité physique (un exécutable, des DLLs) qui contient notamment du code est des données (le point important est de comprendre que tant que le module n'est pas mappé, le code et les données sont dans un état statique). Ce module est placé (on dit "mappé") par le système d'exploitation dans l'espace d'adressage du processus.

    Lorsque le système crée un processus, il alloue de la mémoire pour celui-ci (création de l'espace d'adressage) et "mappe" les modules (l'exécutable [*.exe] et ses DLLs [*.dll]). Ensuite il crée un premier thread (dit "thread primaire") qui exécute du code. La première instruction exécutée par le thread primaire est située au point d'entrée de l'exécutable.

    C'est grossièrement résumé et certaines descriptions souffre d'exception mais cela te donne un point de vue général.

    Ceci dit:

    Je rappel que mon objectif est simplement de lire des valeurs utilisées par le processus cible. J'aimerai bien les afficher dans la console. Par exemple, si dans le processus FT, il y a une valeur '115' qui correspond au nombre de pièces d'or du joueur, j'aimerai afficher : "Golds : 115" dans le flux de sortie standard.
    Si tu cherche à lire une valeur dans un processus encore faut-il savoir à quelle adresse elle se situe. Dans le cas d'un trainer tu sera forcé de passer par un désassemblage...

Discussions similaires

  1. Erreur Avec Interbase
    Par smokemon dans le forum Bases de données
    Réponses: 1
    Dernier message: 29/10/2004, 07h24
  2. Erreur avec procédure LockWorkStation ...
    Par simonseztech dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 16/08/2004, 15h33
  3. [Débutant][Conception] Erreur avec une classe interne
    Par Devil Redneck dans le forum Général Java
    Réponses: 5
    Dernier message: 11/06/2004, 15h45
  4. Erreur avec les ADO
    Par megane dans le forum Bases de données
    Réponses: 7
    Dernier message: 08/03/2004, 21h37
  5. Erreur avec WM_COMMAND (BN_CLICKED)
    Par cyberlewis dans le forum Windows
    Réponses: 2
    Dernier message: 09/02/2004, 00h25

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