Можно также отредактировать установки флагов. Для этого нужно ввести такую разновидность команды: r f, после чего перед вами отобразится установка флагов в текущий момент и приглашение для редактирования флагов. Чтобы отредактировать один из флагов, нужно ввести в приглашении противоположный ему флаг. Например, для флага cy (перенос) нужно указать флаг nc (нет переноса).
W «адрес»
И наконец, с помощью этой команды записывается содержимое памяти на диск в виде программы Win32. Без аргумента данная команда начинает запись файла из адреса памяти CS:100, но можно самому указать адрес памяти, из которого будет начинаться запись.
Q
Эта команда закрывает окно отладчика.
Описание кода
Теперь, когда вы знаете описание необходимых команд, можно заняться описанием самого кода программы. И описывать его будем так: сначала указывается адрес памяти (или команда), а потом кратко говорится о том, для чего мы записываем по этому адресу памяти данные.
ПРИМЕЧАНИЕ
Еще перед описанием кода стоит сказать о командах db и dw, с которых начинается запись значений в адреса памяти — эти команды указывают на размер одной записываемой ячейки (ячейки отделяются запятыми). Если указана первая команда, то одна ячейка будет занимать в памяти 1 байт, а если указана вторая команда, то одна ячейка будет занимать 2 байта.
И еще одно — все значения в коде приведены в шестнадцатиричном виде и пишутся в обратном порядке.
Сначала нужно заполнить нулями (то есть очистить) диапазоны памяти от 0 до 400 и от 1000 до 1200. В первом диапазоне будет содержаться сама программа, а второй диапазон будет рабочим — именно в нем для удобства и будет вначале собрана программа.
Начиная с адреса 0 и заканчивая адресом 15c, формируется заголовок РЕ-файла: вначале пишется заголовок DOS-файла (адрес 0, записывается MZ), потом указывается, с какого адреса будет начинаться заголовок РЕ-файла (содержимое адреса 3c), и в этом адресе пишется сам заголовок РЕ-файла (адрес 40, записывается «Р», «Е», 0,0). По этому же адресу записывается идентификатор процессора, для которого предназначена программа (для i386 вводится 14c), и количество секций, из которых она будет состоять. Дальше, по адресу 54, указывается размер NT-заголовка, флаги программы и «магическое значение». Если значения предыдущих адресов были статичны, то содержимое адреса 68 зависит от самой программы — оно указывает на адрес точки входа в программу. Начиная с этого адреса, будет вводиться сам код программы. По адресу 74 вводится базовый адрес загрузки (0,40), выравнивание в памяти и в файле (1000,0,200,0), а также версия операционной системы и версия подсистемы (4,0,0,0,4). По адресу 90 указывается размер образа с заголовками в памяти (2000), размер заголовка в файле (200) и подсистема (2). По адресу b4 указывается количество входов в каталоге смещений (10), а по адресу c0 описываются сами входы в каталог (мы используем только один): адрес таблицы импорта (1090) и ее размер (3c). По адресу 140 начинается таблица объектов (опять имеет один вход): занимаемый объем памяти (1000), с какого адреса начинается (1000), сколько места занимает в файле (200) и по какому смещению в нем находится (200). И последний адрес заголовка — 15c. В нем хранятся флаги (секция кодовая, имеет разрешения на чтение, запись и исполнение).
После формирования заголовка формируются данные программы — в диапазоне адресов от 1010 до 1070. Сначала записывается заголовок сообщения и его текст (адреса 1010 и 1020), потом названия библиотек, из которых будут взяты функции MessageBox (выводит наше окно) и ExitProcess (завершает программу) (адрес 1040 — USER32.DLL, а адрес 1050 — KERNEL32.DLL). И наконец, сами названия функций (адрес 1060 — MessageBoxA и адрес 1070 — ExitProcess), которые пишутся с учетом регистра.
Теперь нужно сформировать таблицу поиска, импортируемых адресов и таблицу импорта.