• Уменьшение отступа

    Обратная связь

    (info@ru-sfera.pw)

ВАЖНО А не написать-ли нам Джойнер самим !?

Нужно-ли развивать данную тематику ?

  • Да

    Голосов: 20 100.0%
  • Нет

    Голосов: 0 0.0%

  • Всего проголосовало
    20

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 068
Репутация
8 175
Праздники, после двух бутылок водки я неожиданно задумался, как дольше жить а не написать-ли свой Джойнер (Склейщик файлов + запуск нужных)…

В начале начал писать на си билдере, но как оказалась, что она глючит с 7-ой, запарился перед тем-как понял это, было у меня перекрытие памяти при работе с AnsiString, из-за чего такое возникло не знаю, может даже дело и не в винде, а в руках лень разбиратьтся, да и пофиг…
Вспомнил я что на виртуалбоксе у меня стоит делфя, ну и решил я переделать там, благо использовал в основном APIвинды, переделать не составило не какого труда…

Что-то я отвлёкся, ах-да теперь по делу:

Для начала разберёмся, что должен делать наш джойнер:
1)Распаковывать в темп нужные файлы;
2)Запускать необходимые файлы из темпа;
3)Я ещё сделал смену иконки в билде, но не доделал, это ложится на Вас гы-гы…

Данные штуки можно делать по всякому, но я делал по такому алгоритму:

Так-же как и у крипторов, наша прога будет состоят из двух частей (Две программы):
1)Первая программа – Это конструктор, он имеет графический интерфейс, предназначен для сборки нашего билда, т.е. он в зависимости от настроек пользователя создаст нам джойнер (билд):

1.png


2)Вторая программа – Это загрузчик (Stub), это по сути и есть основная программа, она отвечает за «Мозги», она и вытаскивает файлы из нашего джойнера при запуске, а также запускает их из папки темп !

Лучше стабы писать на асме, т.к. будет маленький размер, работать будет быстрее, да и вообще меньше будет глюков…

Конструктор-же лучше писать на языках высокого уровня типо там Делфи и т.д.

Мы-же в этой статье напишем и-то и-то на делфи, т.к. статья учебная, что-бы вкурить суть, да и с асмом мне лень разбираться, может позже перепишу, но там всё переделывать надо будет…

Итак начнём:

1)Пишем Конструктор:

Создаём стандартный проект в Делфи…

Создали, теперь что будет делать наш конструктор:

1)Записывать в конец нашего стаба служебную информацию, у нас это: Размер файла, Имя Файла, Имя файла, который нужно запустить, общее число файлов, общее число файлов которые нужно запустить !

Для этих целей я создал структуру, да-да схитрил, можно конечно сделать проще и лучше, но я что-бы не тратить время тупо записывал «слепок» структуры в стаб, а потом стабом и считывал её…

Делается всё на самом деле легко, ниже покажу как, сейчас покажу код самой структуры:

Type
FileInfRecord = record //Это наша структура куда будет считываться вся информация из стаба
_filesize: array [0..1000] of cardinal; // Размерфайла
_filename: array [0..1000] of string[100]; //Имяфайла
_filenameStart: array [0..1000] of string[100]; //Имяфайла, которыйнужнозапустить
_fileCount: cardinal; //Числофайлов (Общее)
_fileCountStart: cardinal; //Число файлов (Которые нужно запустить)
End;

Далее для работы с ней объявляем переменную: _FileHeader: FileInfRecord;

В общем-то весь код объяснять не буду, кому интересно глянете исходник, а расскажу основные моменты и принцип действия:

Нам нужно для начала наполнить структуру необходимыми данными: Размер файла, Имя Файла, Имя файла, который нужно запустить, общее число файлов, общее число файлов которые нужно запустить !

Для этого используем APIвинды, смотри комменты в коде:

Наполняем нашу структуру данными, которые ввёл пользователь в GUI-интерфейсе:

Код:
for i:=0 to ListView1.Items.Count-1 do  //Наполняем нашу структуру данными, т.е. заносим имя наших файлов и размер в цикле
  begin
	_fileHeader._filename[i]:=ListView1.Items.Item[i].Caption;	  //Имя файла
	_fileHeader._filesize[i]:=GetFileSized(ListView1.Items.Item[I].SubItems.Strings[0]+ ListView1.Items.Item[I].Caption);	  //Размер
  end;
for i:=0 to memo1.lines.count-1 do _FileHeader._filenameStart[i]:=Memo1.Lines[i]; //Сюда заносим имя файла, который нужно запускать
  _fileHeader._fileCount:=ListView1.Items.Count;  //Cюда количество таких файлов
Далее копируем наш стаб, что-бы не портить исходный, в него и будем заносить служебную информацию, а также файлы которые нужно склеить:
Код:
CopyFile(pchar(extractFilePath(application.ExeName)+ 'stub.exe'), pchar(SaveDialog1.FileName), false);	//Скопируем наш стаб в указанный пользователем путь			
  Sleep(100);	//Ждём 100 миллесекунд, это что-бы файл успел скопироваться
Далее, когда структура заполнена нужными данными, нужно её записать в стаб, для этого:
1)Открываем наш скопированный стаб;

2)Перемещаемся в конец файла;

3)Записываем нашу структуру;

4)Далее в цикле записываем файлы, которые нужно склеить.

Смотрите код и читайте комментарии:
Код:
_distFile:=CreateFile(pchar(SaveDialog1.FileName), GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0); //Открываем наш уже скопированный стаб
 
SetFilePointer(_distFile, 0, nil, FILE_END); //Перемещаемся в конец стаба
  WriteFile(_distFile, _fileHeader, sizeOf(_fileHeader), _temp, nil);  //Записываем нашу структуру в стаб
  for i:=0 to ListView1.Items.Count-1 do  //Далее нам нужно записать сами файлы, которые мы хотим склееть в стаб, делаем это в цикле
  begin
	_fromFile:=CreateFile(pchar(ListView1.Items.Item[i].SubItems.Strings[0]+			  ListView1.Items.Item[i].Caption), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);	//Открываем файл который хотим склееть
repeat
ReadFile(_fromFile, _buff, sizeOf(_buff), _temp, nil); //Читаем файл который хотим склееть
WriteFile(_distFile, _buff, _temp, _temp2, nil);//Записываем эти данные в стаб
ZeroMemory(@_buff, sizeOf(_buff));//Чистим буфер
until _temp<>1025;
	CloseHandle(_fromFile);
  end;
  CloseHandle(_distFile);
  ShowMessage('Склейка успешно завершилась!');
Для ускорения копирования чтение файла-источника происходит блоком. За один раз читается и записывается ровно 1024 байта. После записи очередной порции данных нужно позаботиться об очищении памяти. В модуле Windows.pas для этого предусмотрена процедура ZeroMemory. От нас требуется только передать ей два параметра: указатель на буфер, который подлежит очистке, и его размер. В общем-то и всё, переходим к созданию стаба !

2)Конструктор у нас есть. Но вот беда: без программы-загрузчика он мало чем полезен, поэтому нам придется создать новый пустой проект и написать в нем несколько строчек кода. Для программы-загрузчика форма нам не потребуется, поэтому сразу ее удаляй. Вообще, программа-загрузчик должна иметь минимальный размер, а значит, нужно избавиться от всего лишнего. Удали из Uses все модули, оставь лишь Windows и ShellAPI. Их нам будет вполне достаточно. Опиши структуру FileInfRecord. Она должна выглядеть точно так же, как и в программе-конструкторе. Если ты укажешь разные размеры массивов или еще чего-нибудь, то наш загрузчик будет неправильно работать (точнее, не будет работать вовсе).

Для начала разберёмся что-же делает наш стаб:

1)При запуске открывает сам-себя;

2)Считывает нашу структуру;

3)На основании данных в структуре, вытаскивает файлы в папку темп и запускает их.

В общем-то и всё, теперь как это сделать:

Объявляем структуру ТАКУЮ-ЖЕ что и в конструкторе:

type
FileInfRecord = record //Это наша структура куда будет считываться вся информация из стаба
_filesize: array [0..1000] of cardinal; // Размерфайла
_filename: array [0..1000] of string[100]; //Имяфайла
_filenameStart: array [0..1000] of string[100];
_fileCount: cardinal; //Числофайлов (Общее)
_fileCountStart: cardinal; //Число файлов (Которые нужно запустить)
End;

Далее создаём переменную для работы со структурой, например так:_fileHeader:FileInfRecord;

Далее читайте коментраии в коде:
Код:
_fileSource:=Createfile(pchar(ParamStr(0)), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); //Открываем сами себя :)
SetFilePointer(_fileSource, mySize, nil, FILE_BEGIN); //Перемещаемся в конец стаба
ReadFile(_fileSource, _fileHeader, sizeOf(_fileHeader), _temp, nil); // Считываем загаловок в нашу структуру
Start:=_fileHeader._fileCountStart;//В эту переменную заносим число файлов которые нужно запустить
 
 
 
  if _fileHeader._fileCount=0  //Если не хуя не считалось
  then
  begin
  Exit; //И выйдем
  end;
  GetTempPath(MAX_PATH, ShortPath); //Определим папку темп
 
for i:=0 to _fileHeader._FileCount-1 do
begin
//Создаём файл, в который будем записывать данные, это и есть склеенный файл:
_fileDist:=CreateFile(pchar(string(ShortPath)+string(_fileHeader._filename[i])), GENERIC_WRITE, FILE_SHARE_WRITE,nil,CREATE_NEW, 0, 0);
 
for j:=1 to _fileHeader._filesize[i] do
begin
ReadFile(_fileSource, _buff, sizeOf(_buff), _temp, nil);// Считываем данные из стаба
WriteFile(_fileDist, _buff, sizeOf(_buff), _temp, nil); // Записываем эти данные в файл, который создали
end;
  CloseHandle(_fileDist);
  Sleep(100);
end;

Создай константу mySize. В этой константе у нас будет храниться наш собственный размер стаба, то есть размер программы-загрузчика. На данном этапе мы его не знаем, поэтому пока указываем 0. Код программы-загрузчика приведён выше, но не всё а основные моменты !

Сначала нам нужно открыть для чтения файл программы-загрузчика, то есть самого себя. После открытия выполняем смещение до адреса, с которого начинается код нашего блока с информаций. Как его узнать? Очень просто! Поскольку программа-конструктор записала структуру с информаций в самый конец программы-загрузчика, нужно просто перейти в файле на размер файла загрузчика. Этот размер у нас будет определен в объявленной ранее константе. Позиционирование в файле опять же выполняется с помощью SetFilePointer.

При переходе на нужную позицию становится возможным считать структуру. А раз так, то после выполнения «ReadFile(_fileSource, _fileHeader, sizeOf(_fileHeader), _temp, nil); » вся наша структура будет считана. Ну а это значит, что мы обладаем всей необходимой информацией для выдергивания остальных файлов. Код разбивки тела загрузчика на файлы похож на код программы-конструктора, поэтому не будем на нем останавливаться.

Окончательно дописав код и прочитав предыдущие строки, скомпилируй проект. После завершения компиляции зайди в меню «Project -> Information» и обрати внимание на строку File Size.

В ней указан конечный размер exe нашего проекта. У меня он равен 16384. Именно это число нужно присвоить нашей константе mySize. После этого еще раз сохраняй все изменения в проекте и выполняй компиляцию. Все, наш joiner полностью готов.

Разместите две программы (Два экзешника) в одной папки:

Я назвал их так Joiner.exe– конструктор, Stub.exe– Это наш стаб !

Далее запускаете Joiner.exeесли хотите что-то склеить…

Во вложении (Джойнер.rar) исходники стаба (Папка Stub2) и конструктора (Папка Bulder), а также уже готовый вариант в папке «Бинарник», я также реализовал смену иконки, но глючит, можете доделать ! ;)

И ещё не смог сдержаться и склеил с картинкой страшный руткит, файл Блондинка.exe, во вложении гы-гы-гы !

И ещё вопрос нужно-ли развивать данную тему ?

Могу доработать Джойнер:

1)Переписать стаб на асме;

2)Сделать опцию криптования файлов, т.е. склеевать их шифруя;

3)Доделать смену иконок нормально;

4)Сделать протектор.

Кто-что думает ?

Обновил исходник, "Джойнер2.rar" более новый, немного другой функционал, читай тему ! ;)
 

Вложения

  • Блондинка.rar
    253.6 КБ · Просмотры: 47
  • ДЖОЙНЕР.rar
    506 КБ · Просмотры: 85
  • ДЖОЙНЕР2.rar
    502.9 КБ · Просмотры: 98

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 068
Репутация
8 175
Нормальный мануал!А почему в джойнере нужно второй раз прописывать вручную имена файлов?
Это-те которые нужно запустить после распаковки...

Он может и не запускать, какие не пропишешь, не будет запускать...

И не ошибись, иначе стаб зависнет, особо не напрягался когда писал !Отдыхай!!!

Смена иконок, может также крашить файлы, так-что осторожно, делайте копии оригиналов !WinkSmile
 

Антоха

Уважаемый пользователь
Форумчанин
Регистрация
26.12.2012
Сообщения
2 780
Репутация
4 652
Это-те которые нужно запустить после распаковки...
Он может и не запускать, какие не пропишешь, не будет запускать...
Ну так по идее,джойнер и создан,чтобы склеивать и запускать.Зачем нужна просто распаковка,без запуска?
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 068
Репутация
8 175
Ну так по идее,джойнер и создан,чтобы склеивать и запускать.Зачем нужна просто распаковка,без запуска?
Ну а если у тебя вирус/программа не только екзешник, с ней ещё идут конфиги, дллки и ненужная нагрузка, которую нужно спрятать от пользователя...

Зачем запускать конфиги, дллки и прочее, но если этого не будет, то программа/вирус не запуститься,как-то так !WinkSmile
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 068
Репутация
8 175
Хе сейчас потестил эту штуку, файл "Блондинка.exe", ничего опасного там нет, просто склеен специально подготовленный экзешник с картинкой png для теста, на выходе должны получить форму-шутку и блондинку !Dmeh-Smeh-Smeh!!!

Ну да-ладно сейчас не об этом !

Из 6-ти проверенных мной аверов:Нод,Каспер,Оутпост,Нортон,Авира,Битдефендер, детектят только два...

Авира определила компилятор Делфи у стаба и пишит потенциально опасное ПО Delphi-Dropper, хотя вредоносного ничего там нет...

Бит тоже среагировал на стаб, написал дроппер по мойму !

Каспер, запустил какой-то мега-крутой анализ во время запуска, но вроде всё проглатил, т.е. всё получилось распаковать и запустить...

Этот метод на самом деле так-себе, если только для того чтобы понять суть и принцип действия, это я тоже для того что-бы поучится сделал !

Теперь задачу немного усложню для себя как время будет:

1)Пререпишу стаб на асме, размер стаба по моим подсчётам должен уменьшится с 17 до 5 Кб., примерно так...

2)Функционал будет тот-же + добавлю возможность крипта файла XOR-ом, т.е. шифровать и паковать будет, а потом расшифровывать и запускать из темпа ...

3)Конструктор всё-же напишу на Си, т.к. этот язык мне ближе, хотя в целом без разницы здесь на чём делать, если си-билдер будет глючить, попробую написать на QT, на QT даже интересней такое сделать...

В общем потом отпишу о результатах !WinkSmile
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 068
Репутация
8 175
А можете объяснить по подробней, что это за джойнер для чего он и его конечная цель? Не въехал!!!
Джойнер - Это склейщик файлов, цель его из нескольких файлов получить один exe-файл, при запуске которого склеенные файлы распаковываются и запускаются...

Для чего-же нужен Джойнер ?

Всё очень просто, у такого типа программ две стороны применения:

1)Тёмная сторона, хакеры используют Джойнер для маскировки вирусов, пример даёте жертве склеенную с вирусом какую-нить игру, жертва запускает игру вместе с вирусом автоматически, причём вирус запускается в скрытом режиме и жертва ничего не понимает, играя в игру !

2)Вторая сторона, такие программы, так-же как и доунлодеры (Про них может позже статью напишу) используют вполне легальные программы, для скрытия ненужной для пользователя нагрузки...

Пример у Вас есть программа, написанная например на QT, к сожалению для работы таких программ, кроме EXE-файла нужно куча DLL-библиотек, так вот эти библиотеки можно скрыть в джойнер и давать один EXE-файл пользователю, не боясь что он что-то удалит или потеряет, а так область применения таких программ достаточно широка, нежели просто склеевать с вирусом !WinkSmile
 

Антоха

Уважаемый пользователь
Форумчанин
Регистрация
26.12.2012
Сообщения
2 780
Репутация
4 652
Олег,а можно сделать без этого вбивания вручную имён?Например,прописать в коде,чтобы всякие ddlки и конфиги не запускались по умолчанию,а остальные все запускались?Или,например,чебоксики напротив файлов с галочками напротив запускаемых?Можешь показать пример реализации на делфи?
Хе сейчас потестил эту штуку, файл "Блондинка.exe", ничего опасного там нет, просто склеен специально подготовленный экзешник с картинкой png для теста, на выходе должны получить форму-шутку и блондинку !
А я вчера эту блондинку отволок на виртуалку,запустил сниффер,процессы открыл...думаю счас поймаю коварную Олеговскую хрень!А хрени то оказывается и не было:)
 
Верх Низ