EnglishРусский Map

Определение DOSBox через опкод обратного вызова

title
Определение DOSBox через опкод обратного вызова
type
summary
summary
Трюк от Snow: распознавание DOSBox через запуск его опкода FE/7 и проверку, сработал ли обработчик #UD
tags
retro-computing, x86, emulators, dos
created
2026-04-25
updated
2026-04-25
lang
ru
source_updated
2026-04-25
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Заметка Snow от декабря 2025 года на datagirl-xyz с подробным разбором того, как надёжно определить, что DOS-программа выполняется внутри DOSBox. Подход не опирается на хрупкие признаки вроде строки версии BIOS по адресу FE00:0061 или наличия диска Z:, а использует нестандартную x86-инструкцию, которую DOSBox придумал для собственных нужд.

Как это устроено

DOSBox - это эмулятор MS-DOS, который в привычном смысле не содержит ни самого DOS, ни BIOS. Доступ из гостевой системы к функциональности хоста DOSBox организует через виртуальные COM-файлы вроде MOUNT.COM. Дизассемблирование MOUNT.COM показывает обычный x86-код (уменьшение стека, INT 21h), за которым следует нечто похожее на мусор:

0000000A  FE 38 05 00       ; ndisasm: db 0xfe / cmp [di],al / ...

Эта последовательность - не мусор, а обратный вызов (callback) в эмулятор. В файле src/cpu/core_normal/prefix_none.h DOSBox декодирует группу опкодов FE: /0 - это настоящий INC Eb, /1 - настоящий DEC Eb, а /7 - собственный CallBack DOSBox'а. Он считывает 16-битный идентификатор вызова из следующих двух байтов и передаёт управление на хост. Таким образом, FE 38 00 00 вызывает callback 0x0005 и продолжает выполнение дальше, как если бы это был четырёхбайтовый NOP.

Метод определения

На любом реальном x86-процессоре, начиная с 80186, неизвестный опкод вызывает исключение #UD (прерывание 06h). Поэтому тест симметричен поведению DOSBox'а:

  1. Установить собственный обработчик INT 06h.
  2. Выполнить db 0xfe, 0x38, 0x00, 0x00 (обратный вызов с ID 0).
  3. Если обработчик сработал, сдвинуть IP за четырёхбайтовую последовательность и обнулить AX. Восстановить прежний обработчик.
  4. После последовательности проверить значение AX: если там осталось значение до теста, хост молча проглотил опкод, и мы находимся внутри DOSBox.

В посте приведён полный код обработчика исключения на NASM. Рутины там хватает: обработчик должен пройтись по сохранённому в стеке значению IP, подсмотреть проблемные байты опкода (bx == 0x38fe после загрузки в little-endian) и либо сдвинуть IP со значением "не DOSBox", либо восстановить оригинальную запись в IVT и дать настоящему обработчику #UD повторить попытку.

Ошибка в 86Box

Первый тест "под железо" Snow провёл в 86Box (эмуляторе реального ПК, отдельном от DOSBox), и детектор ошибочно выдал "DOSBox". Пошаговая отладка в DEBUG.COM показала, что 86Box без проблем выполнял FE 38 00 00 вместо генерации исключения. Причина: 86Box унаследовал ошибку из PCem, где любой байт ModR/M для FE с ненулевым полем /n декодировался как FE /1 (DEC). В итоге FE /2, /4, /7 молча что-то декрементировали вместо прерывания.

Исправление оказалось несложным и уже влито в upstream в 86Box PR #6561. Snow благодарит Linear (linear.network) за перепроверку на реальном железе, позволившую исключить неточность в документации Intel.

Почему это правильный путь

В посте прямо указано, что существуют более простые, но хрупкие методы:

  • Строка версии BIOS по адресу FE00:0061, начинающаяся с DOSBox (в комментариях к DOSBox-X уже написано, что они хотят дать пользователю возможность её менять)
  • Наличие диска Z: или его серийный номер
  • Специфичные особенности MOUNT и VER в DOSBox-X

Всё это можно подделать правкой конфигурации или пересборкой. Опкод обратного вызова, напротив, неотъемлемая часть архитектуры DOSBox: если убрать его, перестанут работать MOUNT.COM, IMGMOUNT.COM и остальные виртуальные команды.

Другие эмуляторы

В заключение статьи отмечается, что распознавать другие DOS-подобные среды куда проще:

  • NTVDM и командная строка MS-DOS в Win9x: один вызов INT 2Fh
  • DOSEMU: неожиданно большое количество API обратного вызова хоста реализовано в виде COM-файлов (UNIX.COM выполняет произвольные команды на хосте), поэтому для проверки достаточно выяснить, доступны ли эти программы

Ни один из этих вариантов не защищён от подделки так же надёжно, как нестандартная процессорная инструкция, но каждый из них несёт больше побочных эффектов, чем чтение строки из BIOS.

Тестовая программа выложена в git-репозитории Snow: git.2ki.xyz/snow/dostests (исходник на NASM).