Pregunta

Estoy atrapando la ejecución de algunas aplicaciones antiguas de 16 bits que nuestros amigos internos ya no deberían usar. Son aplicaciones DOS de 1985, por lo que atraparlas fue fácil ... capturar cualquier proceso que se inicie con NTVDM.exe

Ahora, el problema es descubrir qué programa NTVDM se está ejecutando realmente bajo el capó. Aparentemente, hay un par de programas de 1985 que DEBEN permitir que se ejecuten, por lo que necesito ver el nombre real de EXE que se esconde bajo NTVDM.

        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();
    }

Cuando capturo la información de la instancia, puedo obtener la línea de comando, pero los argumentos son " -f -i10 " ... No hay un nombre EXE en la línea de comando. ¿Hay algún otro método / propiedad que debería considerar para determinar el nombre de EXE de la aplicación de 16 bits que realmente se está ejecutando?

ACTUALIZACIÓN: Permítanme refinar la pregunta: si puedo encontrar el proceso NTVDM, ¿cómo puedo, programáticamente, conocer la ruta real al EXE que se está ejecutando debajo?

Gracias.

¿Fue útil?

Solución

El truco es no usar VDMEnumProcessWOW (que proporciona los VDM), pero para usar VDMEnumTasksWOW . La función de enumerador que pase a esta función se llamará para cada tarea de 16 bits en el VDM especificado.

No lo he verificado yo mismo, pero de acuerdo con la documentación, esto biblioteca de CodeProject hace exactamente eso, si pasa el valor de enumeración PROC16. Es C ++, si necesita ayuda para compilar ese código y llamarlo desde C #, hágamelo saber y le daré un ejemplo.

Un programa que utiliza esta técnica es Process Master , viene con fuente completa Le sugiero que lo ejecute para averiguar si brinda la información que necesita, y si es así, puede aplicar este método a su propia aplicación (no se ejecuta en Windows Vista o 7, usa el código VB5 anterior, aparentemente no es así). compatible. Debería ejecutarse en XP).

Si las cosas con estas funciones no salen según lo planeado, es posible que esté en Vista y necesite la revisión descrita en este Pregunta StackOverflow , que apunta a descargando una revisión , que a su vez se describe aquí :

  

" Una aplicación que utiliza el   Función VDMEnumProcessWOW para   enumerar devoluciones de máquinas virtuales de DOS   sin salida o salida incorrecta en un   computadora que ejecuta una unidad de 32 bits   versión de Windows Vista "

Update: aunque esto parece prometedor, apliqué el parche, ejecuté varias versiones del código, incluido el de Microsoft, y aunque todos funcionan en XP, fallan en silencio (sin error o valor de retorno incorrecto) en Vista.


El " un poco " código de trabajo

Update: Experimenté (entre otros) con el siguiente código, que se compila bien en C # (y se puede escribir de manera más simple, pero no quería correr un riesgo de error de mariscal). Cuando agrega estas funciones, puede llamar a Enum16BitProcesses , que escribirá los nombres de los archivos EXE de los procesos de 16 bits en la consola.

No puedo ejecutarlo en Vista 32 bit. Pero quizás otros puedan intentar compilarlo o encontrar el error en el código. Sería bueno saber si funciona en otros sistemas:

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: Intrigante leído por el reconocido Matt Pietrek. Cuidado con la oración, en algún lugar cerca del final:

  

" Para empezar, programas basados ??en MS-DOS   parece que siempre se ejecuta en NTVDM por separado   sesiones Nunca pude obtener un   Programa basado en MS-DOS para ejecutar en   misma sesión que una de 16 bits basada en Windows   programa. Tampoco pude conseguir dos   iniciado independientemente basado en MS-DOS   programas para ejecutarse en el mismo NTVDM   sesión. De hecho, sesiones de NTVDM   ejecutar programas de MS-DOS no aparecen   en enumeraciones VDMEnumProcessWOW. "

Parece que, para averiguar qué procesos se cargan, necesitará escribir un enlace en NTVDM o escribir un oyente que monitoree el acceso al archivo. Cuando la aplicación que intenta leer cierto archivo DOS es NTVDM.exe, es bingo. Es posible que desee escribir una DLL que solo esté adjunta a NTVDM.exe, pero ahora nos estamos adelantando un poco. Larga historia corta: esto

Otros consejos

Esto funciona para mí:

  • Siga las instrucciones en Descripción de las Políticas de restricción de software en Windows XP para abra el editor de políticas local o de dominio.

  • Bajo Políticas de restricción de software - > Reglas adicionales, haga clic derecho y seleccione Nueva regla de hash.

  • Busque (por ejemplo) edit.com . Asegúrese de que el Nivel de seguridad esté configurado como No permitido. Haga clic en Aceptar.

Ahora,

  

C: \ > edit
   El sistema no puede ejecutar el programa especificado.

(obtengo los mismos resultados de command.com y cmd.exe - en Win XP)

Desde este enlace sobre las funciones de VDMDBG , puede P / Invocar " VDMEnumProcessWOW () " ;, luego enumerar módulos dentro del proceso usando PSAPI .

  

Nota sobre aplicaciones DOS de 16 bits:

     

Ninguna de las funciones VDMDBG funciona con   Aplicaciones DOS de 16 bits. Enumerar   VDM de DOS, necesita usar otro   método. Primero, podrías usar   VDMEnumProcessWOW () para hacer una lista de   todos los VDM de Win16 y luego enumere todos   instancias de NTVDM.exe usando alguna   otro esquema (como PSAPI). Ninguna   NTVDM.exe de la enumeración completa   que no estaba en la lista Win16 es un   DOS VDM. Puedes crear y terminar   Aplicaciones DOS de 16 bits con   CreateProcess () y   TerminateProcess ().

Espero que ayude ...

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