Как освободить место для пещеры кода в 32-разрядном исполняемом файле Windows PE

Итак, я хочу освободить место для своего кода в minesweeper.exe (типичная игра-сапер для Windows XP, ссылка: Сапер). Поэтому я изменил PE-заголовок файла через CFF Explorer, чтобы увеличить размер раздела .text.

Сег

Я попытался увеличить необработанный размер сегмента .text на 1000h (новый размер был 3B58), но Windows не смогла найти точку входа, и игра не запустилась. Затем я попытался увеличить размер раздела .rsrc, добавить новый раздел, увеличить размер изображения, но ни одна из этих попыток не увенчалась успехом, Windows говорила, что «Это не исполняемый файл x32».

Итак, вот вопрос: как мне освободить место для моей пещеры кода? Я не хочу искать пустое место, оставленное компилятором, я хочу иметь красивые и чистые 1000 байт для моего кода. Учебник для этого и подробное объяснение того, как это сделать, не портя игру, было бы ОТЛИЧНО! (И да, я на самом деле взламываю тральщик)


person Eugen1344    schedule 28.02.2016    source источник
comment
Добавлен полный и рабочий ответ.   -  person Neitsa    schedule 05.03.2016


Ответы (1)


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

Как правило, вам просто нужно добавить раздел в конец PE и перейти туда из раздела кода. Обычно в конце раздела кода (кодовая пещера) есть немного места, поэтому вы можете поместить туда свои JMP (или небольшую заглушку кода) для перенаправления в новый раздел. Вы также можете добавить другие новые разделы для данных или новых ресурсов или чего угодно.


Примечание. Я использую два инструмента: проводник CFF в качестве PE-браузера; шестнадцатеричный редактор.

Этот файл довольно специфичен, поэтому добавить новый раздел немного сложнее, чем обычно.

Давайте начнем!

Ниже представлен шестнадцатеричный вид массива IMAGE_SECTION_HEADER:

Заголовки разделов

Обычно есть место для добавления нового раздела, но в данном конкретном случае его нет... За заголовком последнего раздела сразу следует что-то.

Судя по содержимому, это, вероятно, связанный каталог импорта, что подтверждается в CFF explorer (смещение связанного каталога 0x248):

Связанный каталог импорта

Связанный каталог импорта сегодня бесполезен, особенно с ASLR, поэтому мы можем обнулить весь каталог (его размер 0xA8 байт, как показано на предыдущем скриншоте):

Каталог импорта с нулевой привязкой

Вы также можете обнулить RVA связанного каталога импорта в каталогах данных, хотя это не является строго обязательным:

введите здесь описание изображения

Теперь пришло время добавить новый раздел.

Добавить новый раздел

Сапер поставляется с 3 разделами по умолчанию, поэтому увеличьте количество разделов с 3 до 4:

Увеличить количество разделов

Перейдите к заголовкам разделов и добавьте новый раздел (вы можете сделать это прямо в проводнике CFF; я назвал свой, .foobar, будьте осторожны, имена разделов максимум 8 символов и не должны заканчиваться с нулевым байтом):

Новый раздел

Вам нужно выбрать два числа:

  • Необработанный размер нового раздела (я выбрал 0x400); оно должно быть кратным FileAlignment (в данном случае это 0x200).

  • Виртуальный размер нового раздела (я выбрал 0x1000); оно должно быть кратно SectionAlignement (что для этого двоичного файла равно 0x1000).

Теперь нам нужно вычислить два других члена, Virtual Address и Raw Address.

Виртуальный адрес

Возьмем пример с первой и второй секцией.

Первый раздел начинается с виртуального адреса 0x1000 и имеет виртуальный размер 0x3A56. Виртуальный адрес следующего раздела должен быть выровнен по SectionAlignement (0x1000), поэтому расчет (здесь используется python):

>>> def round_up_multiple_of(number, multiple):
    num = number + (multiple - 1)
    return num - (num % multiple)

>>> hex(round_up_multiple_of(0x1000 + 0x3a56, 0x1000))
'0x5000'

Что дает 0x5000, что правильно (раздел .data начинается с виртуального адреса 0x5000).

Итак, где должен начинаться наш последний раздел?

Раздел .rsrc начинается с адреса 0x6000 и имеет размер 0x19160:

>>> hex(round_up_multiple_of(0x6000 + 0x19160, 0x1000))
'0x20000'

Таким образом, он должен начинаться с виртуального адреса 0x20000. Поместите это число в Virtual Address.

Необработанный адрес

(Обычно в этом нет необходимости, так как все разделы уже выровнены, последний раздел должен начинаться прямо в конце файла, но мы сделаем это).

Напомним, необработанный адрес — это адрес в файле (а не в памяти).

Начнем с примера (первый и второй раздел):

Необработанный адрес первого раздела — 0x400, а его необработанный размер — 0x3c00. FileAlignement равно 0x200, таким образом:

>>> hex(round_up_multiple_of(0x400 + 0x3c00, 0x200))
'0x4000'

Второй раздел должен начинаться с файла (его Raw address) с адреса 0x4000, что правильно.

Таким образом, для нашего нового раздела расчет будет следующим:

  • Раздел .rsrc начинается в файле с адреса 0x4200.
  • Размер раздела .rsrc в файле 0x19200
  • FileAligment is 0x200

Расчет следующий:

>>> hex(round_up_multiple_of(0x4200 + 0x19200, 0x200))
 '0x1d400'

Наш последний раздел начинается с необработанного адреса 0x1d400 в файле, который подтверждается шестнадцатеричным редактором:

Расположение последнего раздела

Заключительные шаги

Требуется последний шаг — вычисление поля SizeOfImage в заголовке «Необязательный». Согласно спецификации PE это поле:

Размер (в байтах) изображения, включая все заголовки, при загрузке изображения в память. Оно должно быть кратно SectionAlignment.

Следовательно, расчет можно упростить следующим образом: VirtualAddress + VirtualSize последнего раздела, выровненного по SectionAlignment (0x1000):

>>> hex(round_up_multiple_of(0x20000 + 0x1000, 0x1000))
'0x21000'

Новый размер изображения

Теперь сохраните все ваши изменения в проводнике CFF и выйдите.

Добавление места для нового раздела

Последний шаг — добавить необходимые байты для последней секции. Когда я выбираю Raw size из 0x400, я вставляю 0x400 байт по адресу Raw Address (0x1d400) с помощью шестнадцатеричного редактора.

Сохраните файл. Если вы выполнили все шаги, он должен работать (проверено на Win 10) как есть, и вы можете запустить модифицированный исполняемый файл без каких-либо ошибок.

Попробуйте использовать другой необработанный размер для нового раздела, если 0x400 недостаточно.

Теперь у вас есть новый пустой раздел, остальное зависит от вас для изменения кода :)

person Neitsa    schedule 04.03.2016
comment
Да, но, как я упоминал ранее, я пытался добавить новый раздел, но он повреждает файл, Windows продолжает говорить, что это не исполняемый файл Windows 32. Не могли бы вы дать мне более подробное объяснение? Вы даже можете скачать тральщик по моей ссылке и попробовать добавить в него новый раздел - person Eugen1344; 05.03.2016
comment
Спасибо, ты не поверишь, как сильно я тебя люблю! - person Eugen1344; 09.03.2016