¿El primer hilo que se ejecuta dentro de un proceso Win32 es el "hilo principal"?Necesidad de entender la semántica.

StackOverflow https://stackoverflow.com//questions/9695370

Pregunta

Creo un proceso usando CreateProcess() con el CREATE_SUSPENDED y luego continúe para crear un pequeño parche de código dentro del proceso remoto para cargar una DLL y llamar a una función (exportada por esa DLL), usando VirtualAllocEx() (con ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory(), luego llame FlushInstructionCache() en ese trozo de memoria con el código.

Después de eso llamo CreateRemoteThread() para invocar ese código, creándome un hRemoteThread.He verificado que el código remoto funciona según lo previsto. Nota: este código simplemente devuelve, no llama a ninguna API que no sea LoadLibrary() y GetProcAddress(), seguido de llamar a la función stub exportada que actualmente simplemente devuelve un valor que luego se pasará como el estado de salida del hilo.

Ahora viene la observación peculiar:recuerda que el PROCESS_INFORMATION::hThread sigue suspendido.Cuando simplemente ignoro hRemoteThreadel código de salida y tampoco espere a que salga, todo va "bien".La rutina que llama CreateRemoteThread() devoluciones y PROCESS_INFORMATION::hThread se reanuda y el programa (remoto) realmente se ejecuta.

Sin embargo, si llamo WaitForSingleObject(hRemoteThread, INFINITE) o haga lo siguiente (que tiene el mismo efecto):

DWORD exitCode = STILL_ACTIVE;
while(STILL_ACTIVE == exitCode)
{
    Sleep(500);
    if(!GetExitCodeThread(hRemoteThread, &exitCode))
        break;
}

seguido por CloseHandle() esto lleva a hRemoteThread terminando antes PROCESS_INFORMATION::hThread se reanuda y el proceso simplemente "desaparece".basta con permitir hRemoteThread terminar de alguna manera sin PROCESS_INFORMATION::hThread para hacer que el proceso muera.

Esto parece sospechosamente una condición de carrera, ya que bajo ciertas circunstancias hRemoteThread aún puede ser más rápido y el proceso probablemente "desaparecerá", incluso si dejo el código como está.

¿Eso implica que el primer subproceso que se ejecuta dentro de un proceso se convierte automáticamente en el subproceso principal y que existen reglas especiales para ese subproceso principal?

Siempre tuve la impresión de que un proceso termina cuando muere su último hilo, no cuando un particular el hilo muere.

Tenga en cuenta también: no hay llamada a ExitProcess() involucrado aquí de ninguna manera, porque hRemoteThread simplemente regresa y PROCESS_INFORMATION::hThread Todavía está suspendido mientras espero. hRemoteThread regresar.

Esto sucede en Windows XP SP3, 32 bits.

Editar: Acabo de probar Sysinternals Process Monitor para ver qué está sucediendo y pude verificar mis observaciones anteriores.El código inyectado no falla ni nada por el estilo; en cambio, puedo ver que si no espero el hilo, no sale antes de cerrar el programa donde se inyectó el código.Estoy pensando si la llamada a CloseHandle(hRemoteThread) debería posponerse o algo así...

Editar+1: que no es CloseHandle().Si dejo eso solo para una prueba, el comportamiento no cambia cuando espero que finalice el hilo.

¿Fue útil?

Solución

El primer hilo que se ejecuta no es especial.

Por ejemplo, cree una aplicación de consola que cree un subproceso suspendido y finalice el subproceso original (llamando a ExitThread).Este proceso nunca finaliza (al menos en Windows 7).

O haga que el nuevo hilo espere cinco segundos y luego salga.Como se esperaba, el proceso durará cinco segundos y finalizará cuando finalice el subproceso secundario.

No sé qué está pasando con tu ejemplo.La forma más sencilla de evitar la carrera es hacer que el nuevo hilo reanude el hilo original.

Especulando ahora, me pregunto si lo que estás haciendo no causará problemas de todos modos.Por ejemplo, ¿qué pasa con todos los DllMain ¿Requiere las DLL cargadas implícitamente?¿Ocurren inesperadamente en el hilo equivocado, se omiten o se posponen hasta que el código se haya ejecutado y se inicie el hilo principal?

Otros consejos

Es muy probable que el hilo con el main (o equivalente) llamadas a funciones ExitProcess (ya sea explícitamente o en su biblioteca de tiempo de ejecución). ExitProcess, Bueno, sale de todo el proceso, incluida la eliminación de todos los subprocesos.Dado que el hilo principal no conoce el código inyectado, no espera a que finalice.

No sé si hay una buena manera de hacer que el hilo principal espere a que el tuyo se complete...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top