Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Хранение нескольких различных файлов в одном исполняемом

Автор: Павел

Часть I. "Пакер"

Эта материал открывает цикл статей для юных программеров (и хакеров :)) интересующихся скрытием своей информации (а так же поиском интересной "чужой" :)). Не секрет что у тебя есть много того, что ты бы не хотел показывать ФСБ, друзьям, Васе Пупкину, и прочей "мировой общественности". Конечно можно использовать запароленные архивы и прочую лабуду (например твой сосед может не увидеть скрытый файл на расшареном диске :), но если задуматься, то станет ясно что, чем больше людей использует одинаковые системы защиты, тем быстрее улучшаются методы взлома этих систем (сорри за тавтологию).

У тебя ёще не появилось желание написать средство для защиты своей ценнейшей инфы (исходников, рефератов, фоток :) и т.д и т.п.) от посторонних глаз. Ведь если ты что-то написал сам, то только ТЫ знаешь, КАК ОНО ПРЯЧЕТСЯ И ДОСТАЁТСЯ. Наши первые программы будут полезны как программерам, так и хакерам. Это будут Пакер и Анпакер (Packer & Unpacker). В этой статье я опишу только пакер (темы анпакера будут затронуты в следующих статьях). Писать мы его будем на всенародно любимом Delphi (у меня шестая версия, но работать должно и на предыдущих). Суть пакера заключается в следующем: в конец некоего экзешника (.exe) дописываем размер файла который мы потом будем из него доставать, далее следует сам файл, потом размер второго файла, и, собственно, второй. Сразу скажу что под "неким экзешником" я подразумеваю анпакер.

Ну, что? Готов? Если да то запускай Делфи и создавай новый проект (File/New/Application). Первым делом назови как-нибудь форму (Caption) (пусть будет что-то типа "Super-Puper-Mega- Packer"). Далее размести на ней OpenDialog и SaveDialog (вкладка Dialogs). Давай сразу посмотрим на настройки OpenDialog'a. Для этого открой Options в Object Inspector'е и сделай поля ofPathMastExist и ofFileMastExist равными True. Всё это нужно для того, чтобы файлы которые мы будем прятать реально существовали. В SaveDialog'е желательно сделать поле ofPathMastExist равным True. Так же размести на форме кнопку (Button) с грозной надписью "GO!", 3 Edit'а (первым двум Edit'aм в поле ReadOnly надо поставить True) и 3 SpeedButton'а. У SpeedButton1 сделай поле Tag равным 1 (это понадобится в дальнейшем). Теперь можно занятся дизайном нашего пакера (это не должно вызвать особых проблем :)). Не забудь только загрузить рисунки в SpeedButton'ы. Отличные пикчурсы можно взять (если у тебя стоит полная версия Delphi) из \Program Files\Common Files\Borland Shared\Images\Buttons. Я нацепил на SpeedButton1 и SpeedButton2 Fileopen.bmp, а на SpeedButton3 - Filesave.bmp.

А теперь переходим к самому интересному - к кодингу. Для начала сделаем обработчик SpeedButton1'а OnClick и укажем его же в SpeedButton2. В нем напишем следующий код:

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    if (Sender as TSpeedButton).Tag = 1 then
      Edit1.Text := OpenDialog1.FileName
    else
      Edit2.Text := OpenDialog1.FileName;
end;

Если пользователь в OpenDialog'е что-то выбрал, то посмотрим какой из SpeedButton'ов он нажал и присвоим соответствующему Edit'у новое значение. Можно было бы сделать два OnClick'a (у каждого SpeedButton'а свой) и написать что-то типа:

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    Edit1.Text := OpenDialog1.FileName;
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    Edit2.Text := OpenDialog1.FileName;
end;

Но мне это кажется неспортивным. Да и откомпилированная прога будет жирнее на пару байт :). Далее обратим свой взор на SpeedButton3. Сделаем обработчик OnClick в котором:

procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
  if SaveDialog1.Execute then
    Edit3.Text := SaveDialog1.FileName;
end;

Ну а теперь перейдём к самой интересной кнопке - "GO!". В её OnClick'е будет сам упаковщик:

procedure TForm1.Button1Click(Sender: TObject);
var
  f, f2: file;
  buf: array[1..1024] of byte;
  done: integer;
begin
  if not ((FileExists(Edit1.Text)) or (FileExists(Edit2.Text))) then
  begin
    ShowMessage('Неправильно указан путь к файлу');
    Exit;
  end;
  if not FileExists(ExtractFilePath((Application.ExeName)) + 'Unpacker.exe')
    then
  begin
    ShowMessage('Не могу найти Unpacker.exe');
    Exit;
  end;
  AssignFile(f, ExtractFilePath((Application.ExeName)) + 'Unpacker.exe');
  AssignFile(f2, Edit3.Text);
  Reset(f, 1);
  Rewrite(f2, 1);
  while not eof(f) do
  begin
    blockread(f, buf, sizeof(buf), done);
    blockwrite(f2, buf, done);
  end;
  CloseFile(f);

  AssignFile(f, Edit1.Text);
  Reset(f, 1);
  done := FileSize(f);
  blockwrite(f2, done, 4);
  while not eof(f) do
  begin
    blockread(f, buf, sizeof(buf), done);
    blockwrite(f2, buf, done);
  end;
  CloseFile(f);

  AssignFile(f, Edit2.Text);
  Reset(f, 1);
  done := FileSize(f);
  blockwrite(f2, done, 4);
  while not eof(f) do
  begin
    blockread(f, buf, sizeof(buf), done);
    blockwrite(f2, buf, done);
  end;
  CloseFile(f);
end;

Тут всё совсем просто :). Для начала проверяем все ли необходимые для упаковки файлы присутствуют. Далее создаем файл указанный в Edit3.Text и записываем в него распаковщик, размер первого файла, файл, размер второго и второй соответственно (какой-то бутерброд получается :)). Вот и всё! В результате получается .exe который может достать из себя эти 2 файла. Но сейчас это работать не будет, так как нет Unpacker.exe. Его мы напишем в следующий раз. Хотя для любопытных я приведу листинг альфа версии Unpacker'а:

program Unpacker;

uses classes;

const
  c = 117248;

var
  mem: tmemorystream;
  i: integer;
  done: integer = 0;
  done1: integer;
  f: file;
  buf: array[1..2048] of byte;
begin
  mem := tmemorystream.Create;
  mem.LoadFromFile(paramstr(0));
  mem.Seek(c, soFromBeginning);
  mem.ReadBuffer(i, $4);
  assignfile(f, 'temp1');
  rewrite(f, 1);
  while i >= done + 2048 do
  begin
    done1 := mem.Read(buf, sizeof(buf));
    blockwrite(f, buf, done1);
    done := done + done1;
  end;
  if i > done then
  begin
    done1 := mem.Read(buf, i - done);
    blockwrite(f, buf, done1);
  end;
  closefile(f);

  done := 0;
  mem.ReadBuffer(i, 4);
  assignfile(f, 'temp2');
  rewrite(f, 1);
  while i > done + 2048 do
  begin
    done1 := mem.Read(buf, sizeof(buf));
    blockwrite(f, buf, done1);
    done := done + done1;
  end;
  if i > done then
  begin
    done1 := mem.Read(buf, i - done);
    blockwrite(f, buf, done1);
  end;
  closefile(f);

  mem.Free;
end.
Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay