16-Bit-Anwendungen laufen unter NTVDM
Frage
Ich bin Trapping für die Ausführung von einigen alten 16-Bit-Anwendungen, die unsere intern Leute nicht mehr verwendet werden sollen. Sie sind 1985 DOS-Anwendungen, so dass für sie Trapping war einfach ... jeder Prozess erfassen, die unter NTVDM.exe startet
Nun, das Problem ist, herauszufinden, welches Programm NTVDM tatsächlich unter der Haube läuft. Offenbar gibt es eine coupleof die 1985-Programme, die sie ausgeführt werden dürfen, sollten Sie auf, also muß ich die eigentlichen EXE Namen, um zu sehen, die unter NTVDM versteckt.
WqlEventQuery query =
new WqlEventQuery("__InstanceCreationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_Process\"");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
...
static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
ProcessInfo PI = new ProcessInfo();
PI.ProcessID = int.Parse(instance["ProcessID"].ToString());
PI.ProcessName = instance["Name"].ToString();
PI.ProcessPath = instance["ExecutablePath"].ToString();
// Here's the part I need...
PI.ActualEXE = ???;
// ... do the magic on the PI class ...
instance.Dispose();
}
Wenn ich die Instanzinformationen erfassen, kann ich die Befehlszeile, aber die Argumente „-f -i10“ ... Es gibt keinen EXE-Namen auf der Kommandozeile. Gibt es eine andere Methode / Eigenschaft ich suchen soll den EXE-Namen der 16-Bit-Anwendung, um zu bestimmen, die tatsächlich ausgeführt wird?
UPDATE: Lassen Sie mich die Frage verfeinern: Wenn ich den NTVDM-Prozess finden kann, wie kann ich - programmatisch - den tatsächlichen Pfad zur EXE kennen, die unter ausgeführt wird
Danke.
Lösung
Der Trick zu verwenden, ist nicht VDMEnumProcessWOW (die die VDMs gibt), aber VDMEnumTasksWOW
Ich habe es selbst nicht geprüft, sondern nach der Dokumentation, das Process Master , kommt es mit volle Quelle. Ich schlage vor, Sie laufen, um herauszufinden, ob sie die Informationen, die Sie brauchen, und wenn ja, können Sie diese Methode, um Ihre eigene Anwendung anwenden (es ist nicht auf Windows Vista läuft oder 7, verwendet er alte VB5-Code, es ist offenbar nicht kompatibel. Es sollte auf XP laufen).
Wenn die Dinge mit diesen Funktionen gehen nicht wie geplant, können Vista sein kann und den Hotfix in diesem Frage Stackoverflow , die ein Hotfix herunterzuladen, die wiederum hier beschrieben:
"Eine Anwendung, die verwendet die VDMEnumProcessWOW Funktion aufzuzählen virtuelle DOS-Maschinen zurückkehren keine Ausgabe oder fehlerhafte Ausgabe auf einem Computer, auf dem eine 32-Bit Version von Windows Vista "
Update: , während dies scheint vielversprechend, ich den Patch angewendet, lief mehrere Versionen des Codes, einschließlich Microsoft, und während sie alle arbeiten auf XP, sie nicht still (kein Fehler oder falscher Rückgabewert) auf Vista.
Der "irgendwie" Arbeits Code
Update: Ich experimentierte mit (unter anderem) mit dem folgenden Code, der in C # fein kompiliert (und kann einfacher geschrieben werden, aber ich wollte nicht führt ein Marschall-Fehler-Risiko). Wenn Sie diese Funktionen hinzufügen, können Sie rufen Enum16BitProcesses
, welche die Dateinamen der EXE-Dateien der 16-Bit-Prozesse auf die Konsole schreiben.
Ich kann es nicht ausführen auf Vista 32 Bit. Aber vielleicht können andere versuchen, und kompilieren Sie es, oder den Fehler finden im Code. Es wäre schön zu wissen, ob es auf anderen Systemen funktioniert:
public class YourEnumerateClass
{
public static void Enum16BitProcesses()
{
// create a delegate for the callback function
ProcessTasksExDelegate procTasksDlgt =
new ProcessTasksExDelegate(YourEnumerateClass.ProcessTasksEx);
// this part is the easy way of getting NTVDM procs
foreach (var ntvdm in Process.GetProcessesByName("ntvdm"))
{
Console.WriteLine("ntvdm id = {0}", ntvdm.Id);
int apiRet = VDMEnumTaskWOWEx(ntvdm.Id, procTasksDlgt, IntPtr.Zero);
Console.WriteLine("EnumTaskWOW returns {0}", apiRet);
}
}
// declaration of API function callback
public delegate bool ProcessTasksExDelegate(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
);
// the actual function that fails on Vista so far
[DllImport("VdmDbg.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern int VDMEnumTaskWOWEx(
int processId,
ProcessTasksExDelegate TaskEnumProc,
IntPtr lparam);
// the actual callback function, on Vista never gets called
public static bool ProcessTasksEx(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
)
{
// using PtrToStringAnsi, based on Matt's comment, if it fails, try PtrToStringAuto
string filename = Marshal.PtrToStringAnsi(ptrFileName);
Console.WriteLine("Filename of WOW16 process: {0}", filename);
return false; // false continues enumeration
}
}
Update: Intriguing lesen durch den Ruhm Matt Pietrek. Mind the Satz, irgendwo in der Nähe des Ende:
"Für den Anfang MS-DOS-Programme scheinen immer in separaten NTVDM laufen Sitzungen. Ich war nie in der Lage ein bekommen MS-DOS-Programm in der laufen derselben Sitzung als 16-Bit-Windows-basierten Programm. Ebenso wenig konnte ich zwei bekommen unabhängig started-MS-DOS-basierte Programme in der gleichen NTVDM laufen Session. In der Tat, NTVDM Sitzungen MS-DOS-Programme nicht zeigen, bis in VDMEnumProcessWOW Aufzählungen. "
Es scheint, dass, um herauszufinden, welche Prozesse geladen werden, benötigen Sie einen Haken in NTVDM zu schreiben oder einen Zuhörer schreiben, den Zugriff auf die Datei überwacht. Wenn die Anwendung, die eine bestimmte DOS-Datei zu lesen versucht NTVDM.exe ist, dann ist es Bingo. Möglicherweise möchten Sie eine DLL schreiben, die sich nur auf NTVDM.exe angebracht ist, aber jetzt sind wir ein bisschen vor uns bekommen. Lange Rede kurzer Sinn: diese kleine Fahrt in NTVDM hatgezeigt „Möglichkeiten“, die real Hoaxes am Ende erschien.
Es gibt einen anderen Weg, aber die Zeit ist zu kurz, um ein Beispiel zu erstellen. Sie können in den DOS-Speichersegmente herumzustochern und die EXE in der Regel auf dem gleichen Segment geladen wird. Aber ich bin nicht sicher, ob das schließlich zu dem gleichen Ergebnis führen wird und ob es sich lohnt die Mühe.
Andere Tipps
Dies funktioniert für mich:
-
Folgen Sie den Anweisungen unter Beschreibung der Richtlinien für Softwareeinschränkung in Windows XP öffnen Sie die lokale oder Domänenrichtlinien-Editor.
-
Unter Richtlinien für Softwareeinschränkung. -> Zusätzliche Regeln mit der rechten Maustaste und New Hashregel wählen
-
Wechseln Sie zu (zum Beispiel)
edit.com
. Stellen Sie sicher, Sicherheitsstufe wird auf Unzulässig. Klicken Sie auf OK.
C:\>edit
The system cannot execute the specified program.
(I erhalten die gleichen Ergebnisse aus command.com
und cmd.exe
- unter Win XP)
Link zu VDMDBG Funktionen , können Sie in der Lage sein zu P / Invoke „VDMEnumProcessWOW ()“, dann aufzuzählen Module innerhalb des Prozesses unter Verwendung PSAPI .
Hinweis in Bezug auf 16-Bit-DOS-Anwendungen:
Keine der VDMDBG Funktionen arbeiten mit 16-Bit-DOS-Anwendungen. aufzuzählen DOS VDMs, müssen Sie eine andere verwenden, Methode. Erstens könnten Sie VDMEnumProcessWOW (), um eine Liste der alle Win16 VDMs, und dann alle aufzählen Instanzen von NTVDM.exe einige mit anderes Schema (wie PSAPI). Irgendein NTVDM.exe aus der vollständigen Aufzählung das war nicht in der Win16-Liste a DOS VDM. Sie können erstellen und beenden 16-Bit-DOS-Anwendungen mit Createprocess () und TerminateProcess ().
Ich hoffe, das hilft ...