[gelöst] Problem beim auslesen des Prozessspeichers (ehemals: Problem beim öffnen eines Prozess-Handles)



  • Hi Leute,
    ich wollt mir mal einen "Debugger" stricken. Die Anführungszeichen deshalb, weil er nur Speicherbereiche des Prozesses auslesen (und vielleicht später auch schreiben) können soll. Es gibt sicher 1000 andere Programme, die das können, aber ich wollte es als Übungsprogramm für den Zugriff auf "Fremdspeicher" machen.
    Zum Problem: Folgender Code funktioniert, im VS-Debugger ausgeführt, einwandfrei. Sobald ich die Exe abder dierekt starte findets den Prozess nicht.

    #include <windows.h>
    #include <TlHelp32.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    	PROCESSENTRY32 pe32Helper;
    	pe32Helper.dwSize = sizeof(PROCESSENTRY32);
    
    	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
    	HANDLE hProcess = NULL;
    
    	string sProzessName;
    	cin  >> sProzessName;
    
    	if(Process32First(hSnap, &pe32Helper))
    	{
    		do
    		{
    			if(strcmp(pe32Helper.szExeFile, sProzessName.c_str()) == 0)
    			{
    				hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32Helper.th32ProcessID);
    			}
    		}
    		while(Process32Next(hSnap, &pe32Helper));
    	}
    	else
    		cout << "Fehler: Kann Prozessliste nicht öffnen" << endl;
    
    	if(hProcess)
    	{
    		cout << "Prozess gefunden" << endl
    			 << "Handle: " << (unsigned int)hProcess << endl
    			 << "ID:     " << (unsigned int)GetProcessId(hProcess) << endl;
    
    		//TODO: Prozess-Speicher auslesen usw.
    
    		CloseHandle(hProcess);
    	}
    	else
    		cout << "Fehler: Prozess nicht gefunden";
    
    	cin.ignore(0xFFFF, '\n'); //Workaround
    	cin.get();
    
    	return 0;
    }
    

    VS-Debugger:

    explorer.exe
    Prozess gefunden
    Handle: 6132
    ID:     2820
    

    Normal ausgeführt:

    explorer.exe
    Fehler: Prozess nicht gefunden
    

    Was mache ich falsch?

    MfG :xmas1: :xmas2:

    EDIT: Thread-Titel treffender formuliert



  • Nutz mal GetLastError() und gib dir mal die Fehler-ID aus.

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360%28v=vs.85%29.aspx



  • Änderungen:
    Zeile 16 - 17 (formal):

    string sProzessName;
    cout << "Prozessname: ";
    cin  >> sProzessName;
    

    Zeile 23 - 26 (wichtige Änderung m. GetLastError()):

    if(strcmp(pe32Helper.szExeFile, sProzessName.c_str()) == 0)
    {
    	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32Helper.th32ProcessID);
    	cout << "GetLastError returned: " << GetLastError() << endl;
    }
    

    VS-Debugger:

    Prozessname: explorer.exe
    GetLastError returned: 127
    Prozess gefunden
    Handle: 4084
    ID:     2820
    

    Normal ausgeführt:

    explorer.exe
    GetLastError returned: 5
    Fehler: Prozess nicht gefunden
    


  • Nachgeschaut in der MSDN:

    MSDN schrieb:

    ERROR_ACCESS_DENIED Access is denied.
    5 (0x5)

    Was soll das jetzt heißen?



  • Ach so, ich arbeite mich gerade auch zurzeit rein. Nutzt du XP oder höher?

    //edit : Schau dir http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx OpenProcess() an und dann wirst du weiter auf diese müssen http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880%28v=vs.85%29.aspx, die wird auch innerhalb der OpenProcess() Beschreibung verlinkt.



  • zuckerlie schrieb:

    Nutzt du XP oder höher?

    Geheiligt sei XP - jo benutz ich. Die Links kau ich dann mal nach der Schule durch.



  • Jonas OSDever schrieb:

    zuckerlie schrieb:

    Nutzt du XP oder höher?

    Geheiligt sei XP - jo benutz ich. Die Links kau ich dann mal nach der Schule durch.

    Ja geheiligt sei XP!Wobei 7 doch auch gut ist 🙂

    Hm, ich weiß allerdings nicht, ob das, was ich dir geschickt habe auf XP zutrifft. Schau mal durch, dort ist jedoch auch

    ERROR_ACCESS_DENIED

    erwähnt



  • Starte dein Program mal testweise mit Admin Rechten.

    Wenn das nicht hilft, führe am Anfang (direkt nach main) mal versuchsweise diesen code aus (Und ebenfalls als Admin starten):

    bool EnableDebugPrivilege() 
    { 
    	TOKEN_PRIVILEGES priv; 
    	HANDLE hThis, hToken; 
    	LUID luid; 
    
    	hThis = GetCurrentProcess(); 
    
    	OpenProcessToken(hThis, TOKEN_ADJUST_PRIVILEGES, &hToken); 
    
    	LookupPrivilegeValue(0, "seDebugPrivilege", &luid); 
    
    	priv.PrivilegeCount = 1; 
    	priv.Privileges[0].Luid = luid; 
    	priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
    
    	AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0); 
    
    	CloseHandle(hToken); 
    	CloseHandle(hThis); 
    
    	return true; 
    
    }
    


  • cout << "Prozess gefunden" << endl
                 << "Handle: " << (unsigned int)hProcess << endl
                 << "ID:     " << (unsigned int)GetProcessId(hProcess) << endl;
    

    Was man noch erwähnen kann, hier nutzt du C-Casts, sollte in C++ nicht genutzt werden. Zudem hat die Struktur PROCESSENTRY32 ein Member Namens "th32ProcessID", d.h, du musst nicht extra GetProcessId() aufrufen.



  • @Andreas XXL: Mit Admin-Rechten hab ich (selbstverständlich) schon immer gestartet. Aber die Routine, die du gepostet hast hat funktioniert, ich kann den Prozess öffnen - Juhu! Danke dafür.

    @zuckerlie:

    zuckerlie schrieb:

    Was man noch erwähnen kann, hier nutzt du C-Casts, sollte in C++ nicht genutzt werden. Zudem hat die Struktur PROCESSENTRY32 ein Member Namens "th32ProcessID", d.h, du musst nicht extra GetProcessId() aufrufen.

    Ich benutz bei einfachen Datentypen aus Gewohnheit C-Casts. Ich weiß das selbige nicht gern gesehen sind, aber hier ist der Rückgabetyp ja nur ein typedef von unsigned int, weshalb es keine Probleme geben dürfte. Und der Cast is auch nur da, weil ich negativen Zahlen vorbeugen wollte. Außerdem war das ja nur Testweise im Programm um zu prüfen ob alles glatt gelaufen ist.
    Und dass die PRE32-Stuktur den Member besitzt wusste ich auch schon, aber ich wollte prüfen ob das Handle wirklich gültig ist.
    Trotzdem Danke für die Hilfe.





  • Ok, ich muss nochmal weiter fragen.

    Ich bin mittlerweile etwas weiter, bekomm jetzt aber das eigentliche auslesen des Prozessspeichers nicht hin.

    Hier der, auf die wesentliche Stelle beschränkte Code:

    DWORD dOffset;
    DWORD dLength;
    
    int ret = sscanf(sCommand.c_str(), "read %lX %lX", &dOffset, &dLength);
    
    if(ret && ret != EOF)
    {
    	BYTE *bBuffer = new BYTE[dLength];
    
    	if(ReadProcessMemory(hProcess, (LPCVOID)dOffset, bBuffer, dLength, NULL))
    	{
    		for(int i = 0; i < dLength; i += 8)
    		{
    			printf("0x%08X  |  0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X  |  %c %c %c %c %c %c %c %c\n",
    				i,
    				bBuffer[i], bBuffer[i+1], bBuffer[i+2], bBuffer[i+3],
    				bBuffer[i+4], bBuffer[i+5], bBuffer[i+6], bBuffer[i+7],			isprint(bBuffer[i]) ? bBuffer[i] : '.',
    				isprint(bBuffer[i+1]) ? bBuffer[i+1] : '.',
    				isprint(bBuffer[i+2]) ? bBuffer[i+2] : '.',
    				isprint(bBuffer[i+3]) ? bBuffer[i+3] : '.',
    				isprint(bBuffer[i+4]) ? bBuffer[i+4] : '.',
    				isprint(bBuffer[i+5]) ? bBuffer[i+5] : '.',
    				isprint(bBuffer[i+6]) ? bBuffer[i+6] : '.',
    				isprint(bBuffer[i+7]) ? bBuffer[i+7] : '.');		}
    		delete[] bBuffer;
    	}
    	else
    	{
    		cout << "Fehler: Kann nicht aus Prozess lesen" << endl
    		     << "GetLasError() returned " << GetLastError() << "." << endl;
    	}
    }
    else
    	cout << "Fehler: Falsche Syntax fuer read-Command. Bitte Lesen sie die Dokumentation" << endl;
    

    Und hier die Ausgabe:

    Prozessname: TestProzess.exe
    Prozess gefunden
            Handle: 4008
            ID:     800
    
    debug> read 40000 100
    Fehler: Kann nicht aus Prozess lesen
    GetLasError() returned 299.
    
    debug>
    

    Weiß jemand was das Problem ist?



  • Hat das Handle das nötige Zugriffsrecht PROCESS_VM_READ?



  • 299=ERROR_PARTIAL_COPY schrieb:

    Hat das Handle das nötige Zugriffsrecht PROCESS_VM_READ?

    Jonas OSDever schrieb:

    //...
    if(strcmp(pe32Helper.szExeFile, sProzessName.c_str()) == 0)
    {
    	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32Helper.th32ProcessID);
    }
    //...
    

    Ich denke mal, dass PROC_ALL_ACC sollte das machen.

    EDIT: Hat sich erledigt. Das Problem war nich im Programmcode, sondern in der Speicherverwaltung von Windows. Auf 0x40000 kann man nich zugreifen. 0x400000 geht dagegen schon. Egal, ich schreib mal meinen Debugger weiter.

    Schöne Vorweihnachtszeit :xmas1: :xmas2:


Anmelden zum Antworten