16-битные приложения, работающие под управлением NTVDM

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

  •  22-07-2019
  •  | 
  •  

Вопрос

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

Теперь проблема заключается в том, чтобы выяснить, какая программа NTVDM на самом деле работает под капотом.Очевидно, есть пара программ 1985 года, которые им СЛЕДУЕТ разрешить запускать, поэтому мне нужно увидеть фактическое имя EXE, которое скрывается под 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();
    }

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

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

Спасибо.

Это было полезно?

Решение

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

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

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

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

«Приложение, которое использует функцию vdmenumprocesswow для перечисления виртуальных машин DOS, возвращает выходной или неверный вывод на компьютере, который запускает 32-разрядную версию Windows Vista»

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


"Какой-то" рабочий код

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

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

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.Я также не смог получить два независимо созданных программы на основе MS-DOS для запуска на одном и том же сеансе NTVDM.Фактически, сеансы NTVDM, работающие с программами MS-DOS, не отображаются в перечислениях vdmenumprocesswow ».

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

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

Другие советы

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

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

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

  • Перейдите к (например) edit.com.Убедитесь, что для уровня безопасности установлено значение «Запрещено».Нажмите ОК.

Сейчас,

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

(Я получаю те же результаты от command.com и cmd.exe -- под Win XP)

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

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

Ни одна из функций VDMDBG не работает с 16-битными приложениями DOS.Чтобы перечислять DOS VDMS, вам необходимо использовать другой метод.Во -первых, вы можете использовать vdmenumprocesswow () для составления списка всех VDMS Win16, а затем перечислять все экземпляры NTVDM.Exe, используя какую -то другую схему (например, PSAPI).Любой ntvdm.exe из полного перечисления, которого не было в списке Win16, является DOS VDM.Вы можете создать и прекратить 16-битные приложения DOS с помощью CreateProcess () и TranmentProcess ().

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top