SYSENTER из NTVDM

Тема в разделе "WASM.WIN32", создана пользователем Ykidia, 12 май 2010.

  1. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Приветствую!

    Моя задача следующая - выяснить, с некоторыми подробностями, в какой среде запустили exe-шник со встроенным DOS32A, т.е. это программа защищенного режима для DOS с DOS-extender-ом.
    Пока суть такова - при запуске выясняем, в Windows мы или в DOS. Затем, если в Windows, то пытаемся узнать, в какой версии, по крайней мере, имеется в виду линейка NT. Все это можно выяснить при помощи серии фиктивных вызовов Native API.
    Однако, как было где-то здесь на форуме экспериментальным путем выяснено и подтверждено, int 2Eh под NTVDM не работает так, как ожидается, т.е. вызов Native API не производится, хотя первый этап (DOS или Windows) таким образом пройти все равно можно.
    Другой способ - SYSENTER - работает в NTVDM, определение версии Windows проходит на ура, однако после первого же выполнения SYSENTER (и возврата из ядра) среда перестает быть такой, какой была ДО выполнения SYSENTER. Пока я выяснил, что:
    1) отваливается DPMI API - тот самый, который предоставляется прослойкой DOS32A; любой вызов int 31h приводит к ошибке NTVDM;
    2) DOS API, по крайней мере функции вывода на экран, продолжают работать, как ни в чем не бывало, даже при перенаправлении вывода в файл;
    3) отваливаются порты ввода-вывода, по крайней мере команды типа out вызывают ту же реакцию системы, как и в п.1.
    4) команды SIDT/SGDT/SLDT/STR показывают одни и те же значения - что до SYSENTER, что после; сегментные регистры я сохраняю и затем восстанавливаю; само собой и ESP на месте.

    Вопрос - а что собственно происходит? Что еще можно проверить на предмет изменений? И еще - можно ли все вернуть взад (т.е. порты, DPMI и т.д.), и если да, то как?
     
  2. fragment

    fragment New Member

    Публикаций:
    0
    Регистрация:
    11 июн 2008
    Сообщения:
    266
    Я конечно неособо грамотный для тебя вариант предложить хочу ибо не профи в етом и все дела, нощас у сех стоит либо виста либо семерка хпшек осталось ой как немного, если тебя интересует чистый дос то он не поддерживает 32битные регисторы, во время ошибку можешь смело прыгнуть на секцию кода для виндовс NT ибо 98 врятли ты щас где найдешь , помойму вариантов тут много и ты все просто усложняешь и совсем понятно с какой целью. Можно было бы еще включить в прогрмму проверку на Wine, WMware...
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Для прерывания нужно наверно IOPL = 3, а Sysenter сбрасывает EFlags.VM.
     
  4. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    А разве код, выполняющийся с EFLAGS.VM вообще может исполнять инструкции защищенного режима? Насколько я помню, регистры и инструкции защищенного режима вообще не доступны в V86.
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Mika0x65
    Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A, p.467:
     
  6. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    А флаг VM и должен быть сброшен, я не зря написал про DPMI - перед запуском непосредственно "пользовательского" кода DOS32A подготавливает для него среду защищенного режима с плоской моделью памяти, в том числе и с обработчиками программных прерываний для перенаправления некоторых из них в V86 (тот же int 21h или int 10h).
    Т.е. SYSENTER я выполняю уже из 32-битного защищенного режима, но в окружении DOS-экстендера. А после выполнения SYSENTER int 31h (DPMI API) уже не работает (выдает ошибку NTVDM), также не работает ввод-вывод в порты. В итоге 2 вопроса - какого фига? и как исправить?
     
  7. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Clerk
    Ykidia
    Я не об этом, меня удивляет, как будет работать экстендер в v86. Если я правильно помню, то он просто не сможет переключить процессор в защищенный режим: инструкция 'mov cr0, eax' должна сгенерировать #UD.
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Это V8086 режим, тоесть аппаратный эмулятор. Для доступа к портам нужно чтоб IOPL = 3, ну или IOPM настроена(уже не помню как там с вдм).
     
  9. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Mika0x65
    Под NTVDM экстендер всего лишь перенаправляет запросы в DPMI, предоставляемый NTVDM, так что конфликта нет; если же экстендер запускается в среде, где нет DPMI, то он предоставляет его самостоятельно. Я говорю про этот

    Clerk
    Нет, это НЕ V86. V86 - это только при запуске NTVDM. Но затем, при помощи DPMI, который имеется в NTVDM (или через экстендер), я могу перейти в защищенный режим с вожделенным IOPL=3 (кстати для безоговорочного доступа к портам нужен IOPL=0, а при IOPL=3 уже нужна битовая маска портов, разрешающая доступ к конкретным портам).
    Экстендер делает работу по переходу за меня, в итоге при запуске своего exe-шника я уже нахожусь в PM с IOPL=3; также он делает за меня работу по переназначению привычных int XX из защищенного режима в V86.

    При старте своей проги под NTVDM с экстендером, кроме PM с IOPL=3 я имею:
    1) более или менее свободный доступ у портам (NTVDM либо эмулирует, либо "пропускает", как минимум это порты PS/2, VGA и SB);
    2) эмуляцию привычного окружения вызовов DOS: экстендер перенаправляет большинство вызовов int 10h/21h/33h в DOS, который, в свою очередь, эмулируется NTVDM. При таком перенаправлении учитывается трансляция адресов из формата PM в формат RM и обратно (по документации);
    3) DPMI API, позволяющий мне делать то, что нельзя или затруднительно с помощью пп.1-2.

    После выполнения команды SYSENTER я имею другую картину:
    1) доступ к портам запрещен;
    2) эмуляция привычного окружения вызовов DOS вроде остается - как минимум вывод на экран работает;
    3) DPMI API отсутствует.

    Я думал, может кто знает и/или сталкивался - в чем причина и как вернуть пп.1 и 3 на место.
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Не понятно ничего. Во первых что за переключения между режимами, Win95 ?
    Во вторых IOPL - он должен быть выше чем CPL, тогда всё пространство I/O доступно, иначе начинает работать маска в IOPM.
     
  11. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Clerk
    А, да, забыл подробности. Вот вроде нашел:
    Выполнение команд ввода/вывода разрешено, если CPL <= IOPL. При CPL > IOPL производится проверка содержимого битовой таблицы разрешения ввода/вывода.
    Ну мне пофиг - работает же все до выполнения долбаного SYSENTER. Т.е. есть подозрения, что после - IOPL стал меньше 3? Надо будет проверить, бляймух...
    А что тогда происходит с DPMI API (int 31h), он-то куда девается?

    Это не зависит от версии Windows, важно, что его окно DOS поддерживает DPMI, почти полностью (в т.ч. и переход в защищенный режим и обратно). В моем случае это делается автоматитьки экстендером, так что я могу не страдать болезнью "делать все вручную", как это было когда-то.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Вы обращаетесь к ядру через Sysenter. Прежде VM = 1. Иначе никакие сервисы DPMI и остальная дос-надстройка не доступна. Далее вызов Int 0x32 должен сгенерировать #GP.
     
  13. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Перед выполнением SYSENTER по расписанным мной выше причинам VM=0. Я может чего-то и подзабыл, но не выжил еще из ума, иначе почему я тогда работаю с селекторами (смещениями в LDT), а не параграфами, и размер всех сегментов = 4G (кроме PSP, селектор которого при запуске загружен в ES, и его размер ограничен вроде 256 байтами)? И программные прерывания в защищенном режиме никто не отменял, они хоть и работают по-другому, но экстендер транслирует в привычные вызовы. Но после SYSENTER int 21h продолжает работать, а int 31h уже нет...
    P.S. а вот если меняется IOPL, тогда уже никак не исправить :mad:
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Програмный эмулятор, который отвечает за трап-процессинг в NT выполняет эмуляцию только если VM = 1 и VdmObject установлен у процесса. Что вы там наделали не знаю.)
    Вот например начало #GP:
    Код (Text):
    1.         public  _KiTrap0D
    2. _KiTrap0D       proc
    3.  
    4.  
    5.         ;
    6.         ; Did the trap occur in a VDM in V86 mode? Trap0d is not critical from
    7.         ; performance point of view to native NT, but it's super critical to
    8.         ; VDMs. So here we are doing every thing to make v86 mode most
    9.         ; efficient.
    10.  
    11. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
    12.         test    byte ptr [esp]+0ch+2,EFLAGS_V86_MASK/010000h
    13.         jz      Ktdi
    14.  
    15. KtdV86Slow:
    16.         ENTER_TRAPV86 kitd_a, kitd_v
    17.  
    18. KtdV86Slow2:
    19.         mov     ecx,PCR[PcPrcbData+PbCurrentThread]
    20.         mov     ecx,[ecx]+ThApcState+AsProcess
    21.         cmp     dword ptr [ecx]+PrVdmObjects,0 ; is this a vdm process?
    22.         jnz     short @f                        ; if nz, yes
    23.  
    24.         sti                                     ; else, enable ints
    25.         jmp     Kt0d105                         ; and dispatch exception
    26.  
    27. @@:
    28.         ; Raise Irql to APC level, before enabling interrupts
    29.         RaiseIrql APC_LEVEL
    30.         push    eax                             ; Save OldIrql
    31.         sti
    32.  
    33.         stdCall   _VdmDispatchOpcodeV86_try,<ebp>
    34. KtdV86Exit:
     
  15. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Clerk
    Так ведь в моем случае эмуляция производится через DPMI, т.е. int 21h, к примеру, вызывает обработчик соответствующего прерывания защищенного режима, а тот уже проверяет, какой вызов, при необходимости подготавливает сегментные регистры и смещения и передает вызов в V86 посредством функции 0300h "вышестоящего" DPMI (который предоставляется NTVDM-ом). В случае с NTVDM-ом дальнейшего переключения в V86 нет, вместо этого делаются соответствующие вызовы сервисов ОС.
    А если бы я не пользовал DPMI/экстендеров, то конечно же торчал бы в V86, и все происходило бы именно так, как Вы говорите. И любой int вызывал бы в первую очередь #GP, как у Вы и пишете. Когда-то мне приходилось эмулировать DOS в V86 - такой геморрой! Еще и этот himem.sys, для работы кода которого мне приходилось временно отключать защиту или что-то такое делать. И все конечно это хорошо, да только нафиг не нужно, ибо уже сделано - DPMI в таких случаях рулит.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Вот именно, V86 это рудимент и всё что с этим связано, который введён для совместимости и сейча наверно только в стенах учебных заведений юзается. Ядро вызывается через шлюзы, когда окружение нормальное, либо V86. Вызовы из всяких промежуточных режимов, не допустимы, это битая среда. Например вы не можите вызывать сервисы не из контекста или с не запущенным ядром.
     
  17. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Проверил - как до, так и после выполнения SYSENTER значение поля IOPL=0. Значит, доступ к портам в V86 полностью контролируется (что логично), но не с тотальным запретом, а с эмуляцией. Какие-то порты эмулируются простой передачей из/в физические порты (как минимум это порты VGA и, скорее всего, PS/2), что не совсем безопасно, ибо, скажем, некоторые "безобидные" на первый взгляд манипуляции с портом PS/2 могут заморозить мышь в Windows до перезагрузки.
    Итак, VM всегда 0 (имеется в виду после переключения в PM при помощи DPMI), IOPL всегда 0, другие параметры тоже на месте - сегментные регистры и регистры IDTR/GDTR/LDTR/TR.
    Вроде как обработчик 21h остается тот же, даже некоторые специфические вызовы DOS32A работают, но в общем и целом большинство привычных вызовов, работающих до SYSENTER, после - уже не работают, а вываливают DOS-сессию в ошибку. Соответственно, есть подозрения, что и другие обработчики должны быть на месте (тот же 31h), просто они аналогично обламываются с ошибкой.
    Что еще можно посмотреть на предмет изменений?
     
  18. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Оказалось, что SYSENTER и дальнейшие манипуляции в ядре некорректно восстанавливают CS (и вроде как SS). Восстановил (CS с помощью IRETD, а SS просто со стека), и все вернулось на свои места. Уф...
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ykidia
    Разумеется что диспетчер восстанавливает сегментные регистры. При смене кпл формируется нормальный трап-фрейм в случае быстрых вызовов. Предполагалось что сегменты у вас нормальные. Кстате вы можите использовать 0x2A прерывание для создания дескрипторов в LDT, если у вас Cs отличен от дефолтного.
     
  20. Ykidia

    Ykidia Member

    Публикаций:
    0
    Регистрация:
    21 июн 2005
    Сообщения:
    99
    Адрес:
    Санкт-Петербург
    Тут я ничего менял, что мне DPMI выдал, тем и пользуюсь.

    Идиотский вопрос - а в WinNT и Win2k SYSENTER как себя проявляет? Насколько я знаю, там-то нужные MSR не проинициализированы?