C или C++: как загрузчики/обертки работают?

Вот пример того, что я имею в виду...

  • Пользователь запускает программу LOADER.EXE
  • LOADER.EXE загружает другой EXE, но сохраняет все это в памяти, не сохраняя его на диск
  • Выполняет загруженный EXE, как он был бы, если он выполнялся от диска, но делает это прямо из памяти

Я видел несколько приложений как это, и я никогда не видел примера или объяснения того, как это работает.

Кто-либо знает?

Другому примеру встраивали зашифрованный EXE в другой. Это извлечено и дешифровало в памяти, никогда не будучи сохраненным на диск, прежде чем это будет выполнено.

Я видел, что один использовал в некоторых приложениях предотвращать пиратство.

Править: Как заметка на полях, программам нравится работа UPX как это? Я посмотрел на код, но трудно дешифровать для меня, и я спрашиваю главным образом из любопытства, у меня нет потребности в нем.

8
задан Chris 3 May 2014 в 00:20
поделиться

2 ответа

Многие программы, которые делают это, просто распаковывают файл в %TEMP% (я знаю, что делаю), но большие мальчики, по сути, повторно реализуют загрузчик исполняемых файлов ОС, который должен:

  • отобразить исполняемый файл в память. Это не так просто, как кажется, поскольку .exe содержит несколько "секций", которые должны быть загружены с выравниванием страниц (они должны начинаться с адресов, кратных 4K), и каждая из них имеет специфические запросы - только чтение, копирование при записи, нулевая инициализация и т.д.
  • Удовлетворить статические импорты и импорты.
  • Удовлетворить статический импорт, обновляя секцию таблицы импорта, обычно используя LoadLibrary() и GetProcAddress().
  • В случае с dll (которые на самом деле почти идентичны, важная разница в том, что у них есть экспорт и импорт), загрузчику может потребоваться перебазировать dll, если адрес памяти, по которому она была скомпилирована для загрузки, уже используется (что бывает довольно часто). Обычно это невозможно для exe'шников, потому что они не включают секцию перемещения, в которой перечислены места в загружаемом коде, которые необходимо обновить, так как обычно они загружаются первыми в процесс и поэтому не могут быть заблокированы чем-либо. Это означает, что загрузчик должен иметь необычный адрес загрузки для своего собственного exe, который не будет блокировать загруженный exe.

Подводя итог: это большая работа. Если вам интересно, посмотрите спецификацию формата PE, которая описывает файлы .exe и .dll, и функцию VirtualAlloc().

4
ответ дан 5 December 2019 в 23:13
поделиться

Ну, если вы знаете, где находится смещение точки входа исполняемого файла, и знаете, какие параметры он принимает, то все, что вам нужно сделать, это вызвать функцию по адресу "exeBase + entryPointOffset", используя указатель функции.

Стоит отметить, что операционные системы, по крайней мере, системы x86, обычно не позволяют исполнять память, помеченную как данные. В windows, например, это можно изменить с помощью функции "Virtual ProtectEx", чтобы пометить память как исполняемую.

На самом деле, в старые добрые времена это была обычная система для экономии памяти. У вас были "оверлеи", которые позволяли экономить память, меняя местами код по мере необходимости.

1
ответ дан 5 December 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: