2016-06-27 11 views
0

Ich setze ein PLOAD_IMAGE_NOTIFY_ROUTINE, um einen bestimmten Image-Namen zu erkennen und wenn es eine Übereinstimmung gibt, dann beende es. Ich bekomme jedoch einen KERNEL_APC_PENDING_DURING_EXIT BSOD. Der BSOD passiert irgendwo in meiner KillProcess-Funktion, die einfach ein Kernel-Handle mit ObOpenObjectByPointer öffnet und dann ZwTerminateProcess für dieses Handle aufruft.KERNEL_APC_PENDING_DURING_EXIT BSOD

Was könnte falsch sein? Der Code funktioniert gut außerhalb der Routine. Muss ich es posten? Ich erhalte einen BSOD in meinem PLOAD_IMAGE_NOTIFY_ROUTINE, wenn ich KillProcess anrufe.

Hier ist meine Killprocess Funktion:

NTSTATUS KillProcess(HANDLE ProcessId) 
{ 
PEPROCESS Process; 
HANDLE newProcessHandle = NULL; 
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &Process); 

do 
{ 
    if (!NT_SUCCESS(status)) 
    { 
#ifdef DEBUGPRINT 
     DbgPrint("Process with id %d does not exist\n", ProcessId); 
#endif 
     break; 
    } 

    if (NT_SUCCESS(status = ObOpenObjectByPointer(
     Process, 
     OBJ_KERNEL_HANDLE, 
     NULL, 
     PROCESS_TERMINATE, 
     *PsProcessType, 
     KernelMode, 
     &newProcessHandle 
    ))) 
    { 
     if (newProcessHandle != NULL) 
     { 
      status = ZwTerminateProcess(newProcessHandle, 0); 

      ZwClose(newProcessHandle); 
     } 
     else 
     { 
      ObDereferenceObject(Process); 
      break; 
     } 

     if (NT_SUCCESS(status)) 
     { 
#ifdef DEBUGPRINT 
      DbgPrint("Successfully killed process with id %d\n", ProcessId); 
#endif 
     } 
     else 
     { 
#ifdef DEBUGPRINT 
      DbgPrint("Failed to kill process with id %d\n", ProcessId); 
#endif 
     } 
    } 
    else 
    { 
#ifdef DEBUGPRINT 
     DbgPrint("Failed to open process with id %d\n", ProcessId); 
#endif 
    } 

    ObDereferenceObject(Process); 

} while (FALSE); 

return status; 
} 
+1

geändert hat Without Code wird es schwierig sein, Fehler zu bestimmen. Aber überprüfen Sie, ob Sie alle Sperren, kritischen Abschnitte usw. in der Routine freigeben. – Rohan

+0

Okay, du hast Recht und ich habe es gepostet. – user1304765

Antwort

0

Das Problem ist, ich habe versucht, den Prozess in seinem eigenen Kontext zu beenden, die zu einem BSOD führen. Lösung:

  1. eine globale Variable erstellen die pid
  2. Stellen Sie die globale Variable
  3. In einem System-Thread zu halten, überprüfen, ob die globale Variable
  4. beenden den Prozess
+0

Beachten Sie, dass es je nach Szenario eine potentielle Race-Bedingung gibt - wenn zwei Prozesse, die eine Terminierung benötigen, gleichzeitig gestartet werden, erhalten Sie möglicherweise nur eine davon. Sie können dies beheben, indem Sie eine Warteschlange anstelle einer einzelnen Variablen verwenden. Sie sollten auch die Priorität Ihres System-Threads erhöhen, um sicherzustellen, dass er so schnell wie möglich ausgeführt wird, obwohl auf einem Multicore-System immer noch nicht garantiert wird, dass der neue Prozess nicht startet, bevor Sie ihn beenden (wahrscheinlich ziemlich sicher)). –

1

Die documentation for PsSetLoadImageNotifyRoutine sagt:

Wenn die ausführbare Haupt Bild für eine neu erstellte Prozess geladen wird, wird die Last-Bild benachrichtigen Routine läuft im Rahmen des neuen Prozesses.

(Es scheint auch wahrscheinlich, dass, wenn eine DLL geladen wird, wird der Anruf im Rahmen des Prozesses der DLL-Laden erfolgt.)

Also von den Klängen der es, Sie beenden den Prozess, das Kontext, in dem Sie gerade laufen. Sie tun dies an einem besonders verwundbaren Punkt während eines Callbacks für eine Bildladeoperation. Es ist nicht überraschend, dass dies Probleme verursacht.

Die documentation for ZwTerminateProcess impliziert, dass ein Fahrer kann den aktuellen Prozess beenden, vorausgesetzt, dass sie sicherstellt, dass Mittel aus dem Kernel-Stack befreit worden, aber ich glaube nicht, dass in dieser Situation gilt. (Außerdem weiß ich nicht, wie Sie das machen würden.)

Es könnte stattdessen möglich sein, den Prozess zu unterbrechen und später von einem Systemthread zu beenden.

+0

Stattdessen werde ich versuchen, eine DLL einzufügen, die ExitProcess() aufrufen wird. – user1304765

+0

Das könnte auch funktionieren. Ich bin nicht sicher, ob es sicherstellen würde, dass die ausführbare Datei beendet wird, bevor es gestartet wird, wenn das ein Problem ist. –

+0

Ich dachte daran, eine APC in die Warteschlange zu stellen und so zu injizieren, aber ich merkte, dass das nur auf 32-Bit-Systemen funktioniert und ZwSuspendProcess nirgendwo dokumentiert ist und normalerweise keine gute Idee ist. Jetzt denke ich, dass ich sie finden muss eine andere Injektionsmethode. Ich werde wahrscheinlich eine neue Frage stellen. – user1304765