16-битные приложения, работающие под NTVDM - PullRequest
6 голосов
/ 30 октября 2009

Я в ловушке для выполнения некоторых старых 16-битных приложений, которые наши внутренние люди больше не должны использовать. Они являются приложениями 1985 года для DOS, поэтому отловить их было легко ... захватить любой процесс, который запускается под NTVDM.exe

Теперь проблема состоит в том, чтобы выяснить, какая программа NTVDM фактически работает под капотом. Очевидно, есть пара программ 1985 года, которые им СЛЕДУЕТ запускать, поэтому мне нужно увидеть фактическое имя EXE, которое скрыто под NTVDM.

</p> <pre><code> 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(); }

Когда я получаю информацию об экземпляре, я могу получить командную строку, но аргументы: "-f -i10" ... В командной строке нет имени EXE. Есть ли другой метод / свойство, на которое я должен обратить внимание, чтобы определить имя EXE 16-разрядного приложения, которое на самом деле работает?

ОБНОВЛЕНИЕ: Позвольте мне уточнить вопрос: если я могу найти процесс NTVDM, как я могу - программно - узнать фактический путь к EXE, который выполняется под ним?

Спасибо.

Ответы [ 3 ]

5 голосов
/ 09 ноября 2009

Хитрость заключается не в использовании VDMEnumProcessWOW (который дает VDM), а в использовании VDMEnumTasksWOW . Функция перечисления, которую вы передаете этой функции, будет вызываться для каждой 16-битной задачи в указанном VDM.

Я не проверял это сам, но согласно документации, эта библиотека CodeProject делает именно это, если вы передаете значение перечисления PROC16. Это C ++, если вам нужна помощь в компиляции этого кода и вызове его из C #, дайте мне знать, и я приведу вам пример.

Программа, использующая эту технику: Process Master , поставляется с полным исходным кодом. Я предлагаю вам запустить его, чтобы выяснить, дает ли он необходимую вам информацию, и если да, то вы можете применить этот метод к своему собственному приложению (он не работает в Windows Vista или 7, он использует старый код VB5, по-видимому, это не так). совместимо. Должно работать на XP).

Если что-то с этими функциями идет не так, как запланировано, возможно, вы работаете в Vista, и вам может понадобиться исправление, описанное в этом вопросе StackOverflow , который указывает на загрузку исправления , которое в свою очередь описано здесь :

"Приложение, которое использует Функция VDMEnumProcessWOW для перечислять виртуальные DOS машины возвращаются нет вывода или неправильный вывод на компьютер под управлением 32-битной версия Windows Vista "

Обновление: , хотя это кажется многообещающим, я применил патч, запустил несколько версий кода, включая Microsoft, и, хотя все они работают на XP, они молча терпят неудачу (нет ошибка или неверное возвращаемое значение) в Vista.


Рабочий код "своего рода"

Обновление: Я экспериментировал (среди прочего) со следующим кодом, который прекрасно компилируется в C # (и может быть написан проще, но я не хотел запускать риск ошибки маршала). Когда вы добавляете эти функции, вы можете вызвать Enum16BitProcesses, который запишет имена файлов EXE-файлов 16-битных процессов в консоль.

Я не могу запустить его в Vista 32 bit. Но, возможно, другие могут попытаться скомпилировать его или найти ошибку в коде. Было бы неплохо узнать, работает ли он на других системах:

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
    }

}

Обновление: Интригующее чтение от известного Мэтта Пьетрека. Помните предложение где-то ближе к концу:

"Для начинающих, программы на базе MS-DOS кажется, всегда работают в отдельном NTVDM сессий. Я так и не смог получить Программа на базе MS-DOS для запуска в тот же сеанс, что и 16-разрядный Windows-based программа. Я не смог получить два самостоятельно запустил MS-DOS на основе программы для запуска в том же NTVDM сессия. На самом деле сеансы НТВДМ запущенные программы MS-DOS не отображаются в перечислениях VDMEnumProcessWOW. "

Похоже, что для того, чтобы узнать, какие процессы загружены, вам нужно записать хук в NTVDM или написать слушатель, который контролирует доступ к файлу. Когда приложение, которое пытается прочитать определенный файл DOS, - это NTVDM.exe, это бинго. Возможно, вы захотите написать библиотеку DLL, которая подключена только к NTVDM.exe, но теперь мы немного опережаем себя. Короче говоря: эта маленькая поездка в НТВДМ показала «возможности», которые в конце концов стали настоящим обманом.

Есть еще один способ, но времени слишком мало, чтобы создать пример. Вы можете копаться в сегментах памяти DOS, и EXE обычно загружается в тот же сегмент. Но я не уверен, приведет ли это в конечном итоге к тому же результату и стоит ли оно усилий.

2 голосов
/ 09 ноября 2009

Это работает для меня:

  • Следуйте инструкциям на Описание политик ограниченного использования программ в Windows XP , чтобы открыть редактор локальной политики или политики домена.

  • В разделе «Политики ограниченного использования программ» -> «Дополнительные правила» щелкните правой кнопкой мыши и выберите «Новое правило хэширования».

  • Просмотрите (например) edit.com. Убедитесь, что уровень безопасности установлен на Disallowed. Нажмите ОК.

Сейчас

C:\>edit
The system cannot execute the specified program.

(я получаю одинаковые результаты с command.com и cmd.exe - под Win XP)

1 голос
/ 03 ноября 2009

Из этой ссылки о функциях VDMDBG вы можете выполнить P / Invoke "VDMEnumProcessWOW ()", затем перечислить модули внутри процесса, используя PSAPI .

Примечание относительно 16-битных приложений для DOS:

Ни одна из функций VDMDBG не работает с 16-битные DOS-приложения. Перечислять DOS VDM, вам нужно использовать другой метод. Во-первых, вы могли бы использовать VDMEnumProcessWOW (), чтобы составить список все Win16 VDM, а затем перечислить все экземпляры NTVDM.exe с использованием некоторых другая схема (например, PSAPI). любой NTVDM.exe из полного перечня это не было в списке Win16 является ДОС ВДМ. Вы можете создать и прекратить 16-битные DOS-приложения с CreateProcess () и TerminateProcess ().

Надеюсь, это поможет ...

...