Пишем на русском в Native Mode

Недавно у меня возникла необходимость писать на русском в нативном приложении, но, как оказалось, добиться этого не так-то просто.
Для того, чтобы получить возможность вывода русских букв, нужно разобраться, где и в каком формате хранятся глифы символов, которые отображаются на экране. Если подробнее рассмотреть функцию winx_printf (в своем проекте я использовал ZenWINX и NDK для упрощения разработки приложения), то мы увидим, что она в свою очередь вызывает winx_print, далее вызывается NtDisplayString, которая преобразует входящую строку с помощью RtlUnicodeStringToOemString, далее идет вызов функции InbvDisplayString, которая обращается к VGA Boot Driver (bootvid.dll).

Отображаемые глифы хранятся в bootvid.dll в следующем формате (на примере английской буквы A):

00000000 - 0×00
00000000 - 0×00
00011000 - 0×18
00011000 - 0×18
00100100 - 0×24
00100100 - 0×24
00100100 - 0×24
01111110 - 0×7E
01000010 - 0×42
10000001 - 0×81
00000000 - 0×00
00000000 - 0×00
00000000 - 0×00

Посмотреть остальные символы можно с помощью следующего нехитрого скрипта на Perl:

Таким образом, каждый символ имеет размер 8x13 пикселей и, соответственно, занимает 13 байт. Всего под символы отведено 256 * 13 = 3328 байт. То есть, чтобы добавить поддержку русского, необходимо найти начало таблицы глифов в памяти и заменить неиспользуемые символы своими глифами. Начало таблицы может меняться в зависимости от версии ОС, например, в Windows 7 смещение от начала составляет 0x2610, в Vista 0x2420, а в XP SP3 0x1938. Найти таблицу довольно просто, для этого достаточно найти в памяти первый глиф (0x00, 0x00, 0x3C, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x3C, 0x00, 0x00, 0x00).
Для начала необходимо составить свою таблицу глифов, чтобы заменить ею часть существующей таблицы. Вручную "рисовать" такое довольно муторно, поэтому я поступил следующим образом: вывел в консоли windows список необходимых символов, сделал скриншот и преобразовал его в эдакий ASCII-арт.

Делается это следующим образом:

И сразу же сворачиваем получившуюся таблицу в массив байт:

Конечно, последние два скрипта можно объединить в один, но так нагляднее. Также можно заметить, что у меня в консоли выведен не только русский алфавит. Это связано с тем, что по-умолчанию русские буквы не располагаются непрерывно в шрифте (0x80 - 0xAF и 0xE0 - 0xF1), поэтому проще захватить весь интервал (0x80 - 0xF1).

Теперь, когда у нас есть готовая таблица, нам необходимо написать код, который найдет и перезапишет необходимый фрагмент памяти.
Сначала мы должны найти bootvid.dll и адрес, по которому он загружен:

Также нам понадобятся дополнительные функции, с помощью которых мы будем читать и писать в память:

Теперь прочитаем память bootvid и найдем начало таблицы:

И, наконец, переписываем часть памяти:

Таким образом, мы получили готовую функцию для добавления поддержки русского языка. Следующий код позволяет убедиться в том, что она отлично работает на XP SP3:

А вот как выглядит результат работы:

Однако, у этого кода есть минус - он не работает под ОС выше XP SP3 и я пока что не разобрался, как адаптировать его под них.
Исходный код проекта: скачать.

Пишем на русском в Native Mode: 10 комментариев

  1. >Ага, вот кто пишет винлокеры!

    А Вы anonymous совсем не знаете Windows

    WinLocker работает не как Native, он запускается уже после авторизации в системе

    1. Ну, в общем то можно сделать нативный винлокер, вот только маловероятно, что антивирус даст изменить нужную ветку реестра и скинуть файл в system32.

      1. А закидывать в system32 не обязательно. Можно прописать в BootExecute полный путь, приложение запустится из другого места. Остаётся только решить проблему доступа к самому ключу реестра.

  2. Ф-ия "NtSystemDebugControl" - не работает начиная с XP SP3. И хз как теперь выводить кириллицу в native режиме. Может есть какие нибудь другие варианты?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *