È il primo thread che deve funzionare all'interno di un processo Win32 il "thread primario"?Bisogno di capire la semantica

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

Domanda

Creo un processo usando CreateProcess() con CREATE_SUSPENDED e poi vai avanti per creare una piccola patch di codice all'interno del processo remoto per caricare una DLL e chiamare una funzione (esportata da quella DLL), utilizzando VirtualAllocEx()), ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory() , quindi chiamare FlushInstructionCache() su quella patch di memoria con il codice.

After che chiamo CreateRemoteThread() per invocare quel codice, creando un hRemoteThread. Ho verificato che il codice remoto funziona come previsto. Nota: Questo codice restituisce semplicemente, non chiamano alcuna APIS diversa da LoadLibrary() e GetProcAddress(), seguita chiamando la funzione dello stub esportato che attualmente restituisce un valore che verrà quindi passato come stato di uscita il filo.

Ora arriva l'osservazione peculiare: ricorda che il PROCESS_INFORMATION::hThread è ancora sospeso. Quando ignoro semplicemente il codice di uscita di hRemoteThread e non lo aspetti anche per uscire, tutto va "bene". La routine che chiama CreateRemoteThread() returns e PROCESS_INFORMATION::hThread viene ripresa e il programma (remoto) viene effettivamente eseguito.

Tuttavia, se chiamo WaitForSingleObject(hRemoteThread, INFINITE) o faccio quanto segue (che ha lo stesso effetto):

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

seguito da CloseHandle() Questo porta alla finitura hRemoteThread prima che il PROCESS_INFORMATION::hThread venga ripreso e il processo semplicemente "scompare". È sufficiente consentire a hRemoteThread di finire in qualche modo senza PROCESS_INFORMATION::hThread per far morire il processo.

Sembra sospettosamente come una condizione di gara, poiché in determinate circostanze hRemoteThread può essere ancora più veloce e il processo probabilmente "scompare", anche se lascio il codice come è.

fa che implica che il primo thread che deve funzionare all'interno di un processo diventa automaticamente il filo primario e che ci sono regole speciali per quel filo primario?

Sono sempre stato sotto l'impressione che un processo finisca quando la sua ultima filettatura muore, non quando una filettatura particolare muore.

Nota anche: Non vi è alcuna chiamata a ExitProcess() coinvolta qui in alcun modo, poiché hRemoteThread restituisce e PROCESS_INFORMATION::hThread è ancora sospeso quando aspetto hRemoteThread per tornare.

Questo succede su Windows XP SP3, 32 bit.

Modifica: Ho appena provato il monitor dei processi di Sysinternals per vedere cosa sta succedendo e potrei verificare le mie osservazioni da prima. Il codice iniettato non si schianta o nulla, invece vedo che se non aspetto il filo non uscirà prima di chiudere il programma in cui il codice è stato iniettato. Sto pensando se la chiamata a CloseHandle(hRemoteThread) dovrebbe essere posticipata o qualcosa del genere ...

Modifica + 1: Non è CloseHandle(). Se lo lascio solo per un test, il comportamento non cambia quando si attende il thread per terminare.

È stato utile?

Soluzione

Il primo filo da eseguire non è speciale.

Ad esempio, creare un'app console che crea un filo sospeso e termina il thread originale (chiamando EXITTHREAD).Questo processo non termina mai (comunque su Windows 7).

o effettuare il nuovo thread attendere cinque secondi, quindi uscire.Come previsto, il processo vivrà per cinque secondi e uscirà quando la filettatura secondaria termina.

Non so cosa sta succedendo con il tuo esempio.Il modo più semplice per evitare la gara è rendere il nuovo filo riprendere il filo originale.

Speciando ora, mi chiedo se ciò che stai facendo non è probabile che causi problemi comunque.Ad esempio, ciò che accade a tutti i DllMain richiede le DLL implicitamente caricate?Sono inaspettatamente accadendo sul filo sbagliato, vengono saltati, o sono posticipati fino a quando il codice è stato eseguito e inizia il filo principale?

Altri suggerimenti

Le probabilità sono buone che il filo con la funzione main (o equivalente) chiama ExitProcess (in modo esplicito che nella sua libreria di runtime).ExitProcess, beh, esce dall'intero processo, incluso l'uccisione di tutti i thread.Poiché il thread principale non sa sul tuo codice iniettato, non aspetta che finisca.

Non so che c'è un buon modo per rendere il tuo thread principale per il tuo completo ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top