¿Cómo consultar un proceso en ejecución para su lista de parámetros? (ventanas, C ++)

para un proceso de Windows dado, quiero saber con qué parámetros de línea de comandos se inició. El administrador de tareas de Windows puede mostrar eso, por ejemplo.

¡Gracias de antemano!

Suponiendo que conozca la ID del proceso, use OpenProcess para obtener un control (esto requiere privilegios elevados como se indica en los documentos). Luego use NtQueryInformationProcess para obtener información detallada del proceso. Use la opción ProcessBasicInformation para obtener el PEB del proceso; este contiene otro puntero de estructura, a través del cual puede obtener la línea de comando.

Inyección remota de hilo:

Utiliza la inyección de subprocesos remota, llame a GetCommandLine() , y luego el resultado de IPC. Esto podría funcionar la mayor parte del tiempo en Windows XP, pero en Windows Vista o posterior no funciona en los procesos del sistema y del servicio. Esto se debe a que CreateRemoteThread solo funciona en procesos en la misma ID de sesión que la persona que llama: en Windows Vista, los servicios y otros procesos del sistema se ejecutan en la sesión 0 mientras que los progtwigs de usuario se ejecutan en sesiones más altas. La mejor y más segura forma es leer una estructura presente en cada proceso de Windows.

Estructura PEB:

El bloque de entorno de proceso (PEB) generalmente se almacena en las regiones altas de la memoria de proceso, por encima de 0x7ff00000 . Estas regiones también contienen bloques de entorno de subprocesos (TEB). La dirección PEB es diferente para casi todos los procesos, por lo que no puede usar simplemente una constante codificada.

 #include  #include  #include "Winternl.h" typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)( HANDLE ProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, DWORD ProcessInformationLength, PDWORD ReturnLength ); PVOID GetPebAddress(HANDLE ProcessHandle) { _NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); PROCESS_BASIC_INFORMATION pbi; NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL); return pbi.PebBaseAddress; } int wmain(int argc, WCHAR *argv[]) { int pid; HANDLE processHandle; PVOID pebAddress; PVOID rtlUserProcParamsAddress; UNICODE_STRING commandLine; WCHAR *commandLineContents; if (argc < 2) { printf("Usage: getprocesscommandline [pid]\n"); return 1; } pid = _wtoi(argv[1]); if ((processHandle = OpenProcess( PROCESS_QUERY_INFORMATION | /* required for NtQueryInformationProcess */ PROCESS_VM_READ, /* required for ReadProcessMemory */ FALSE, pid)) == 0) { printf("Could not open process!\n"); return GetLastError(); } pebAddress = GetPebAddress(processHandle); /* get the address of ProcessParameters */ if (!ReadProcessMemory(processHandle, &(((_PEB*) pebAddress)->ProcessParameters), &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) { printf("Could not read the address of ProcessParameters!\n"); return GetLastError(); } /* read the CommandLine UNICODE_STRING structure */ if (!ReadProcessMemory(processHandle, &(((_RTL_USER_PROCESS_PARAMETERS*) rtlUserProcParamsAddress)->CommandLine), &commandLine, sizeof(commandLine), NULL)) { printf("Could not read CommandLine!\n"); return GetLastError(); } /* allocate memory to hold the command line */ commandLineContents = (WCHAR *)malloc(commandLine.Length); /* read the command line */ if (!ReadProcessMemory(processHandle, commandLine.Buffer, commandLineContents, commandLine.Length, NULL)) { printf("Could not read the command line string!\n"); return GetLastError(); } /* print it */ /* the length specifier is in characters, but commandLine.Length is in bytes */ /* a WCHAR is 2 bytes */ printf("%.*S\n", commandLine.Length / 2, commandLineContents); CloseHandle(processHandle); free(commandLineContents); return 0; } 

Para obtener más detalles, echa un vistazo a Obtener la línea de comandos de un proceso

EDITAR (Información adicional):

El primer autor dijo:

CreateRemoteThread solo funciona en procesos en la misma ID de sesión que la persona que llama: en Windows Vista, los servicios y otros procesos del sistema se ejecutan en la sesión 0 mientras que los progtwigs de usuario se ejecutan en sesiones más altas. La mejor y más segura forma es leer una estructura presente en cada proceso de Windows.

Es lo mismo con OpenProcess , no puede abrir un proceso que es un servicio o un proceso abierto por SYSTEM o LOCAL SERVICE o NETWORK SERVICE , si está ejecutando su progtwig por un usuario (incluso administrador).

Si su progtwig es un servicio, probablemente ya esté funcionando con la cuenta del sistema local , por lo que no hay problema. Pero si no, una solución es lanzarlo con psexec :

  1. Descarga PSEXEC y descomprime en alguna carpeta.
  2. Abra un aviso de CMD elevado como administrador.
  3. Navega a la carpeta donde descomprimiste PSEXEC.EXE
  4. Ejecutar: PSEXEC -i -s -d CMD
  5. Tendrá un nuevo prompt de CMD abierto.
  6. Escriba lo siguiente en el nuevo aviso de CMD para probar quién es usted: WHOAMI

Debería ver que es SYSTEM , ahora puede iniciar su progtwig y ver la línea de comando para todos los procesos.

Bueno, podría inyectar un dll en el espacio de direcciones de procesos en el extranjero y luego llamar a GetCommandLine .

No puede obtener esa información de manera confiable . Hay varios trucos para intentar recuperarlo, pero no hay garantía de que el proceso objective no haya destrozado esa sección de la memoria. Raymond Chen discutió este tiempo en The Old New Thing .