Veröffentlicht 23. Juni 200619 j Hallo Leute, ich arbeite im Moment an einem Prozess-Monitor für eines unserer Tools. Das Problem ist momentan dass das ganze ausschließlich mit Admin-Rechten läuft. Was wir prinzipiell machen ist mit java durch die Prozessliste loopen, die vorher über eine eigens programmierte C-Schnittstelle ausgelesen wird. Leider wird, zumindest so wie es bei uns implementiert ist, dir Prozessliste nicht komplett ausgegeben; stattdessen kann ich die PIDs aller Prozesse sehen, den Pfad der Prozesse die nicht von mir gestartet worden sind allerdings nicht. Allerdings muss es ja eine programmiertechnische Möglichkeit geben um da drumrum zu kommen und alle Prozesse zu sehen, sonst würden ja der Task Manager bzw. der Process Explorer von sysinternals (www.sysinternals.com) auch immer nur die eigenen Prozesse anzeigen können. Weiß jemand wie das funktioniert? Ich bin langsam mit meinem Latein am Ende. Bei google find ich auch irgendwie nichts. Ich würd unsere aktuelle Implementierung ja auch mit posten, allerdings ist die ein wenig zu lang für nen Forenbeitrag. mfg Eth
26. Juni 200619 j Ich nehme an, du sprichst von Windows. Es wäre gut zu wissen, welche Windows-Version es genau ist. Ich würd unsere aktuelle Implementierung ja auch mit posten, allerdings ist die ein wenig zu lang für nen Forenbeitrag.Du könntest aber schon die allgemeine Vorgehensweise bzw. die benutzten API-Funktionen posten. Ansonsten müsste ich meine Kristallkugel suchen Und weil das mit Standard-C++ nichts zu tun hat: Verschoben -> C++: Compiler, IDEs, APIs
26. Juni 200619 j Da ich von der eigentlichen Implementierung _relativ wenig_ ahnung hab, da ich den Basiscode nicht geschrieben hab (war nen Arbeitskollege, der ist besser in C++ als ich), poste ich hier mal die beiden hauptsächlich verwendeten Funktionen: BOOL __stdcall GetProcessPath(DWORD dwPID, char* szBuff, DWORD dwBuffSize) { HANDLE hSnap; PROCESSENTRY32 ProcInfo = {sizeof(ProcInfo)}; char* szPath = NULL; DWORD dwModh; // we just need the first handle DWORD dwBytesWritten; HANDLE hProc; BOOL bDone; if (!bNT) { // non NT ! hSnap = _CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == INVALID_HANDLE_VALUE) return FALSE; if (!_Process32First(hSnap, &ProcInfo)) { CloseHandle(hSnap); return FALSE; } if (ProcInfo.th32ProcessID == dwPID) { CloseHandle(hSnap); if (!StrNCopy( ProcInfo.szExeFile, szBuff, sizeof(ProcInfo.szExeFile), dwBuffSize)) return FALSE; return TRUE; } while (_Process32Next(hSnap, &ProcInfo)) if (ProcInfo.th32ProcessID == dwPID) { CloseHandle(hSnap); if (!StrNCopy( ProcInfo.szExeFile, szBuff, sizeof(ProcInfo.szExeFile), dwBuffSize)) return FALSE; return TRUE; } // clean up CloseHandle(hSnap); return FALSE; // PID not found } else { // NT ! // get a process handle hProc = OpenProcess(NT_PROCESS_ACCESS, FALSE, dwPID); if (!hProc) return FALSE; // get the first module handle and its path if (!EnumProcessModules( hProc, (HINSTANCE*)&dwModh, sizeof(dwModh), &dwBytesWritten)) { CloseHandle(hProc); return FALSE; } if (!GetModuleFileNameEx( hProc, (HINSTANCE)dwModh, szBuff, dwBuffSize)) bDone = FALSE; else bDone = TRUE; // clean up CloseHandle(hProc); return bDone; } } und: BOOL __stdcall GetProcessIDList(DWORD *dwIDArray, DWORD dwArraySize) { HANDLE hSnap; DWORD *pDW, dwBytesWritten; PROCESSENTRY32 ProcInfo = {sizeof(ProcInfo)}; if (dwArraySize < sizeof(DWORD)) return FALSE; if (!bNT) { // non NT ! // make snapshot hSnap = _CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == INVALID_HANDLE_VALUE) return FALSE; __try // maybe the array is not writeable { pDW = dwIDArray; if (!_Process32First(hSnap, &ProcInfo)) { CloseHandle(hSnap); return FALSE; } *pDW++ = ProcInfo.th32ProcessID; dwArraySize -= sizeof(DWORD); while (dwArraySize && _Process32Next(hSnap, &ProcInfo)) { *pDW++ = ProcInfo.th32ProcessID; dwArraySize -= sizeof(DWORD); } // clean up CloseHandle(hSnap); } __except(1) { CloseHandle(hSnap); return FALSE; } return TRUE; } else { // NT ! if (!EnumProcesses( (DWORD*)&dwIDArray[0], dwArraySize, &dwBytesWritten)) return FALSE; return TRUE; } } mfg Eth
26. Juni 200619 j Ich wiederhole die Frage: Um welche Windowsversion geht es genau? Oder ist das Verhalten immer gleich, unabhängig von der Windowsversion? Wie du vielleicht siehst, macht der Code unter NT (genauer: in Abhängigkeit der globalen Variable bNT) etwas völlig anderes.
26. Juni 200619 j Ah guter Punkt, sorry hatte ich überlesen; bin noch nicht ganz da ^^ Es geht ausschließlich um Win2k und WinXP. Der Code für Win98 ist nur aus irgendwelchen komischen Kompatibilitätsgründen noch drin.
26. Juni 200619 j Anscheinend braucht ein Prozess das Privileg SE_DEBUG_NAME, um an die Dateipfade der Prozesse zu kommen. Dieses Privileg bekommen nur Prozesse, die von einem Administrator gestartet werden, automatisch. Du kannst das Privilig aber nachträglich hinzufügen. Stichwort AdjustTokenPrivileges.
26. Juni 200619 j Ich hab das Anhand einiger Beispiele mal grad implementiert, als extra funktion in der dll: /* * Class: de_symmedia_util_windows_process_Process * Method: setCurrentProcessSEDebug */ JNIEXPORT jint JNICALL Java_de_symmedia_util_windows_process_Process_setCurrentProcessSEDebug (JNIEnv * env, jclass obj) { HANDLE hToken; /* process token */ TOKEN_PRIVILEGES tp; /* token provileges */ DWORD dwSize = sizeof (TOKEN_PRIVILEGES); LUID luid; /* now, set the SE_SYSTEMTIME_NAME privilege to our current * process, so we can call SetSystemTime() */ if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return 1; } if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid)) { //printf ("LookupPrivilege() failed with code %d\n", GetLastError()); CloseHandle (hToken); return 1; } ZeroMemory (&tp, sizeof (tp)); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* Adjust Token privileges */ if (!AdjustTokenPrivileges (hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &dwSize)) { //printf ("AdjustTokenPrivileges() failed with code %d\n", GetLastError()); CloseHandle (hToken); return 1; } CloseHandle (hToken); return 0; } mit Java-Implementierung: public static native int setCurrentProcessSEDebug(); Funktioniert aber irgendwie nicht. Der Process Explorer zeigt mir das Recht für den Prozess nicht an und die Prozessliste seh ich auch nicht komplett. Hast du noch ne Idee? Wie gesagt, bin kein C-As mfg Eth
26. Juni 200619 j Funktioniert aber irgendwie nicht.Lies meine Signatur. Welchen Rückgabewert bekommst du denn? Alle anderen Diagnosemöglichkeiten hast du ja auskommentiert.
26. Juni 200619 j Dein Code funktioniert bei mir in einer Konsolenanwendung. Der Process Explorer zeigt nach dem Aufruf von AdjustTokenPrivileges SeDebugPrivilege nicht mehr als Disabled an.
26. Juni 200619 j Könnte das eventuell an dem Aufruf in der DLL liegen? Ich will ja prinzipiell an die javaw.exe ran, die die dll als library nachgeladen hat ... EDIT: Hast du das ganze mit einem normalo-account getestet?
26. Juni 200619 j Könnte das eventuell an dem Aufruf in der DLL liegen? Ich will ja prinzipiell an die javaw.exe ran, die die dll als library nachgeladen hat ...Kann ich nicht ausschließen. Mach doch vor und nach dem Aufruf eine MessageBox, dann kannst du dir das genauer ansehen. EDIT: Hast du das ganze mit einem normalo-account getestet?Ja. Das Privileg war vor dem Aufruf Disabled.
26. Juni 200619 j Ich versteh das irgendwie nicht. Der zeigt mir das Attribut einfach im PE nicht an. Steht doch dann unter Security oder?
26. Juni 200619 j Steht doch dann unter Security oder?Genau. Es steht immer da, nur eben normalerweise Disabled. Die beiden Bilder zeigen des Zustand vorher und nachher:
26. Juni 200619 j Ein Privileg, das nicht da ist, kannst du auch nicht mit AdjustTokenPrivileges aktivieren. Haben andere (nicht-Java-) Prozesse bei dir dieses Privileg?
26. Juni 200619 j Nein haben sie nicht. Aber wie ich bereits sagte arbeite ich als normalo-benutzer ohne Admin-Rechte. Ich habe gerade mal ein wenig rumgespielt, und dabei festgestellt, dass selbst der Process Explorer im Normalbenutzerbetrieb die Pfadnamen der Prozesse nicht kennt. Allerdings kennt er den Namen der ausführbaren Datei. Wie komm ich denn da dran?
26. Juni 200619 j Aber wie ich bereits sagte arbeite ich als normalo-benutzer ohne Admin-Rechte. Hm. Ich bin hier zwar kein Admin, aber habe doch offenbar ziemlich viele Rechte. Allerdings kennt er den Namen der ausführbaren Datei. Wie komm ich denn da dran?Der Name ohne Pfad steht im szExeFile-Member der PROCESSENTRY32-Struktur.
26. Juni 200619 j Die PROCESSENTRY32 Struktur wird in unserer Implementierung anscheinend nur für win98/me genutzt. Für spätere Versionen wird PSAPI verwendet. Macht das so überhaupt sinn?
26. Juni 200619 j Was ist denn ein "Normalo-Benutzer"? Es gibt ja mehre Arten von Benutzergruppen. Z.B. Administratoren, Hauptbenutzer, Benutzer, Gäste usw...
26. Juni 200619 j Die PROCESSENTRY32 Struktur wird in unserer Implementierung anscheinend nur für win98/me genutzt. Für spätere Versionen wird PSAPI verwendet. Macht das so überhaupt sinn?Kommt drauf an. Du hast nicht gezeigt, wie bNT gesetzt wird. Allerdings vermute ich da ein Missverständnis. CreateToolhelp32Snapshot gibt es wirklich nur unter NT nicht. Unter 2000 und XP ist es da. Die OpenProcess-Lösung ist die "ältere".
26. Juni 200619 j Wie gesagt, ich hab das ganze nicht implementiert ich erweitere nur. Hab grad ein wenig MSDN zu dem Thema durchstöbert. Wir haben an sich offiziell nur noch Kompatibilität zu 2000 und XP, teilweise 2k3. So wie ich das sehe steht aber doch in der PROCESSENTRY32.szExeFile der komplette Pfad drin, oder? und auf den hab ich doch wieder keinen Zugriff ohne SE_DEBUG!
26. Juni 200619 j Zur Prozessliste: Es gibt mehrere Möglichkeiten an eine Liste der grade ausgeführten Prozesse zu kommen. Nicht jede Variante wird unter jeder Windows-Version unterstützt. Sofern es Dir nicht wichtig ist NT zu unterstützen, kannst Du CreateToolhelp32Snapshot benutzen. Um den Pfad zur Exe ohne OpenProcess herauszufinden (so wie ich Dich verstanden habe, scheitert es an dieser Funktion aufgrund der Privilegien des Benutzers), kannst Du für jeden Prozess die Liste seiner Module durchgehen (jedes Modul hat einen eigenen Pfad). Eine weitere Möglichkeit wäre es, die Liste über WMI abzufragen.
28. Juni 200619 j Ich hab es Läuft super: Kleines Beispiel: #include <windows.h> #include <stdio.h> #include <tchar.h> #include <tlhelp32.h> void main(void) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if (hSnapshot==INVALID_HANDLE_VALUE) { // error: unable to create snapshot exit(1); } PROCESSENTRY32 pe; // fill up its size pe.dwSize=sizeof(PROCESSENTRY32); BOOL retval=Process32First(hSnapshot,&pe); while(retval) { printf("Process ID : %s\n",pe.szExeFile); pe.dwSize=sizeof(PROCESSENTRY32); retval=Process32Next(hSnapshot,&pe); } // close snapshot handle CloseHandle(hSnapshot); }
Erstelle ein Konto oder melde dich an, um einen Kommentar zu schreiben.