Ist der erste Thread, der innerhalb eines Win32-Prozesses ausgeführt werden darf, der „primäre Thread“?Die Semantik muss verstanden werden

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

Frage

Ich erstelle einen Prozess mit CreateProcess() mit dem CREATE_SUSPENDED und erstellen Sie dann einen kleinen Code-Patch innerhalb des Remote-Prozesses, um eine DLL zu laden und eine Funktion (von dieser DLL exportiert) aufzurufen VirtualAllocEx() (mit ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory(), Dann ruf an FlushInstructionCache() auf diesem Speicherfleck mit dem Code.

Danach rufe ich an CreateRemoteThread() um diesen Code aufzurufen, erstelle ich einen hRemoteThread.Ich habe überprüft, dass der Remote-Code wie vorgesehen funktioniert. Notiz: Dieser Code kehrt einfach zurück und ruft keine anderen APIs auf als LoadLibrary() Und GetProcAddress(), gefolgt vom Aufruf der exportierten Stub-Funktion, die derzeit lediglich einen Wert zurückgibt, der dann als Exit-Status des Threads übergeben wird.

Jetzt kommt die eigenartige Beobachtung:Denken Sie daran, dass die PROCESS_INFORMATION::hThread ist immer noch suspendiert.Wenn ich es einfach ignoriere hRemoteThreadGeben Sie den Exit-Code ein und warten Sie auch nicht, bis er beendet wird. Alles läuft „gut“.Die Routine, die ruft CreateRemoteThread() Retouren und PROCESS_INFORMATION::hThread wird fortgesetzt und das (Remote-)Programm kann tatsächlich ausgeführt werden.

Allerdings, wenn ich anrufe WaitForSingleObject(hRemoteThread, INFINITE) oder machen Sie Folgendes (was den gleichen Effekt hat):

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

gefolgt von CloseHandle() Dies führt zu hRemoteThread vorher fertig PROCESS_INFORMATION::hThread wird fortgesetzt und der Vorgang „verschwindet“ einfach.Es genügt zu erlauben hRemoteThread irgendwie ohne fertig werden PROCESS_INFORMATION::hThread um den Prozess zum Absterben zu bringen.

Dies sieht verdächtig nach einer Rennbedingung aus, da unter bestimmten Umständen hRemoteThread ist möglicherweise immer noch schneller und der Prozess würde wahrscheinlich immer noch „verschwinden“, selbst wenn ich den Code unverändert lasse.

Bedeutet das, dass der erste Thread, der innerhalb eines Prozesses ausgeführt werden darf, automatisch zum primären Thread wird und dass es spezielle Regeln für diesen primären Thread gibt?

Ich hatte immer den Eindruck, dass ein Prozess endet, wenn sein letzter Thread stirbt, und nicht, wenn a besondere Faden stirbt.

Beachten Sie außerdem: Es gibt keinen Anruf ExitProcess() hier in keiner Weise involviert, denn hRemoteThread einfach zurück und PROCESS_INFORMATION::hThread ist immer noch ausgesetzt, wenn ich darauf warte hRemoteThread zurückgeben.

Dies geschieht unter Windows XP SP3, 32bit.

Bearbeiten: Ich habe gerade Sysinternals Process Monitor ausprobiert, um zu sehen, was passiert, und konnte meine Beobachtungen von früher überprüfen.Der eingefügte Code stürzt nicht ab oder so. Stattdessen sehe ich, dass der Thread nicht beendet wird, wenn ich nicht auf ihn warte, bevor ich das Programm schließe, in das der Code eingefügt wurde.Ich überlege, ob der Anruf an CloseHandle(hRemoteThread) sollte verschoben werden oder so ...

Bearbeiten+1: es ist nicht CloseHandle().Wenn ich das nur testweise weglasse, ändert sich das Verhalten beim Warten auf das Ende des Threads nicht.

War es hilfreich?

Lösung

Der erste Thread, der ausgeführt wird, ist nichts Besonderes.

Erstellen Sie beispielsweise eine Konsolen-App, die einen angehaltenen Thread erstellt und den ursprünglichen Thread beendet (durch Aufruf von ExitThread).Dieser Prozess wird nie beendet (zumindest unter Windows 7).

Oder lassen Sie den neuen Thread fünf Sekunden warten und beenden Sie ihn dann.Wie erwartet bleibt der Prozess fünf Sekunden lang bestehen und wird beendet, wenn der sekundäre Thread beendet wird.

Ich weiß nicht, was mit Ihrem Beispiel passiert.Der einfachste Weg, das Rennen zu vermeiden, besteht darin, den neuen Thread so zu gestalten, dass er den ursprünglichen Thread fortsetzt.

Wenn ich jetzt spekuliere, frage ich mich, ob das, was Sie tun, nicht sowieso wahrscheinlich Probleme verursachen wird.Was zum Beispiel mit all dem passiert DllMain fordert die implizit geladenen DLLs?Geschehen sie unerwartet im falschen Thread, werden sie übersprungen oder werden sie verschoben, bis Ihr Code ausgeführt wurde und der Hauptthread startet?

Andere Tipps

Die Chancen stehen gut, dass der Thread mit dem main (oder gleichwertige) Funktionsaufrufe ExitProcess (entweder explizit oder in seiner Laufzeitbibliothek). ExitProcess, nun ja, beendet den gesamten Prozess, einschließlich des Beendens aller Threads.Da der Hauptthread nichts von Ihrem injizierten Code weiß, wartet er nicht, bis er fertig ist.

Ich weiß nicht, dass es eine gute Möglichkeit gibt, den Hauptthread auf den Abschluss Ihres Threads warten zu lassen ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top