Однако с каждым годом появляются все новые и новые независимые разработчики, которые разбирают защиты программных продуктов любой сложности, и в связи с этим собственники терпят большие убытки на рынке информационных технологий.
В данной статье показан процесс разбора одного из современных алгоритмов защиты - файлового архива с расширением RAW с прилагающейся к нему таблицей, которая имеет расширение SDT. Для этой цели была выбрана среда программирования Delphi, т.к. Delphi - оптимальный инструмент для создания приложений любой сложности. Оптимальный, т.к. поддерживает технологию визуальной разработки, которая позволяет существенно сократить время разработки (снизить стоимость, соответственно) при сохранении хорошего качества и надежности программного продукта.
Преимущества среды программирования:
низкие требования разработанного приложения к ресурсам компьютера;
наращиваемость за счет встраивания новых компонентов и инструментов в среду Delphi;
удачная проработка иерархии объектов;
высокая производительность разработанного приложения.
Была поставлена следующая задача:
написать приложение для распаковки файлового архива на примере файлов с расширением RAW и SDT, где SDT – файловая таблица, в которой хранятся сведения о файлах, расположение которых в основном файле RAW. Обеспечить извлечение файлов из архива путём средств среды программирования Delphi. Присвоить извлечённым файлам имена,задействовав функцию инкремента, а также дать возможность пользователю выбрать директорию для сохранения файлов.
Приложение представляет собой форму, на которой присутствуют 2 кнопки “Выбрать” (первая для RAW – файла, а вторая для SDT соответственно), кнопка “Распаковать”, которая приводит в действие процедуру распаковки из модуля (Рис.1).
Рис.1. Главное окно приложения.
Для начала пользователь должен указать пути к обоим файлам средствами файлового диалога Windows (Рис.2):
Рис.2. Файловый диалог.
Если выбран один файл из двух, или оба файла не выбраны вообще, то появляется ошибка, которая представлена на Рис.3.:
Рис.3. Сообщение об ошибке.
Если RAW и SDT выбраны, то при нажатии на кнопку “Распаковать” происходит извлечение файлов из архива.Появляется диалог выбора каталогов, в котором пользователь может выбрать нужную ему директорию для сохранения файлов(Рис.4):
Рис.4.Выбор директории для сохранения.
Известно, что SDT – это таблица, которая содержит в себе информацию о файле RAW. Рассмотрим таблицу с помощью HEX-редактора эту таблицу.Структура таблицы представлена на Рис.5.
Рис.5.Структура файловой таблицы.
Изучив таблицу с помощью калькулятора, можно прийти к выводу, что информация о каждом файле равна 12 байтам и представляет собой следующую структуру: смещение – 4 байта, размер – 4 байта, частота – 4байта. Файлы в архиве – звуки ADPCM с заголовком VAGp. Итак, в программе необходимо объявить переменные. Если в файле используется структура данных, то справедливо будет объединить переменные в структуру:
sdtstruc: record
startpos: integer;
length: integer;
samplerate: integer;
end;
Далее объявляем остальные переменные, необходимые в процедуре.
Для начала, получив 2 файла от пользователя, мы начинаем считывать информацию из файла-таблицы. Создадим цикл:
while not eof(sdt) do begin… * Пока файл не достигнет конца – продолжать.
BlockRead(sdt, sdtstruc, 12); *Читаем все данные из таблицы размером в 12 байт и записываем их в переменные ранее созданной структуры.
Далее нужно позаботиться об именах файлов, так как они не указаны в файловой таблице, создадим их, используя инкремент. Дадим переменной n начальное значение 0.
Далее будем использовать следующую конструкцию внутри цикла:
s := inttostr(n) + '.vag';
inc(n);
Переменной типа String будет присваиваться число, которое впоследствии выполнения цикла будет увеличиваться на 1, так как переменная имеет тип Integer, то переведём её в тип String, задействовав IntTostr, а на конце добавим расширение выходному файлу *.VAG.
По считанной информации из таблицы мы обращаемся к архиву и начинаем считывать из него байты, в буфер, согласуясь с таблицей:
GetMem(buf, sdtstruc.length);*Готовим место в буфере для файла по считанному из таблицы размеру.
Seek(raw, sdtstruc.startpos); *Переходим на позицию, с которой начинается файл
BlockRead(raw, buf^, sdtstruc.length);*Читаем в буфер байты, количество которых равно размеру.
BlockWrite(wav, buf^, sdtstruc.length);*Записываем считанные байты из буфера в новый файл.
FreeMem(buf, sdtstruc.length);* Очистка буфера
Далее нам нужно закрыть, только что создавшийся файл:
CloseFile(wav);
Весь цикл будет выглядеть следующим образом:
while not eof(sdt) do
begin
BlockRead(sdt, sdtstruc, 12);
s := inttostr(n) + '.vag';
AssignFile(wav, Save.SelectedPathName+'/'+s);
Rewrite(wav, 1);
GetMem(buf, sdtstruc.length);
Seek(raw, sdtstruc.startpos);
BlockRead(raw, buf^, sdtstruc.length);
BlockWrite(wav, buf^, sdtstruc.length);
FreeMem(buf, sdtstruc.length);
CloseFile(wav);
inc(n)
end;
После завершения цикла необходимо закрыть файл архива и таблицу и сообщить пользователю, что файлы извлечены:
CloseFile(raw);
CloseFile(sdt);
Showmessage('Файлыуспешноизвлечены');
Как можно заметить, файлы были успешно извлечены и прекрасно проигрываются в плеере для VAG – формата.