Blog. Just Blog

Запись в архивы SAR, PRS и CAR без помощи архиватора

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
В предыдущих трех частях цикла статей о записи информации в архивы различных форматов без помощи архиваторов были рассмотрены как популярные форматы, так и более редкие. Настало время совсем экзотических архиваторов, результатов работы которых вы вообще нигде не встретите. Поэтому разбор их внутренних форматов можно рассматривать исключительно как разминку для ума, никакой практической пользы от этих исследований ждать не надо. Тем более, что документации по некоторым архиваторам нет, все данные пришлось получать на основании готовых архивов.

Первый и самый простой из виденных архивов - SAR, сокращенное название от "Streamline Arching Utility" производства компании Streamline Design. Единственная существующая версия датируется 1993 годом. Файлы в архиве предваряются небольшим заголовком, общего заголовка архива нет, признак завершения архива - нулевой байт вместо следующего заголовка.
  1. ;---------------------------------------------
  2. ; SAR Header
  3. ;---------------------------------------------
  4. shlen   db      ?         ; Header length
  5. shcrc   db      ?         ; CRC of header
  6. smeth   rb      5         ; Compression method (' LH0 ' = store)
  7. sosize  dd      ?         ; Original file size
  8. scsize  dd      ?         ; Compressed file size
  9.         db      ?         ; unknown
  10.         db      ?         ; unknown
  11.         db      ?         ; unknown
  12.         db      ?         ; unknown
  13. sunkn1  db      ?         ; File attribute? (20h)
  14. sunkn2  db      ?         ; unknown (01h)
  15. slen    db      ?         ; Filename size
  16. sfname  rb      (?)       ; Filename (ASCII)
  17. sfcrc   dw      ?         ; 16-bit CRC
  18. sunkn3  db      ?         ; unknown (20h)
  19.         db      ?         ; unknown
  20. shend   db      ?         ; unknown
Мнемокода "(?)" в FASM нет, просто таким образом я обозначил текстовую строку для записи имени файла неопределенной длины. В реальном проекте будет достаточно MAX_PATH или вообще фиксированного размера.
  1. ; Признак окончания архива - нулевой байт
  2. tail    db      0
  3. tail_length   = $-tail 
Некоторые поля мне не удалось идентифицировать, в заголовке они отмечены комментарием "unknown", они должны быть заполнены нулевыми значениями, если не указано другого.

Записываемый файл предварительно надо загрузить в память, после этого заполняем поля заголовка архива:
  • shlen = длина заголовка архива от поля smeth до shend включительно;
  • shcrc = контрольная сумма заголовка;
  • smeth = строка " LH0 ";
  • sosize = размер оригинального файла;
  • scsize = размер сжатого файла (равен оригинальному);
  • sunkn1 = 20h (неизвестное поле);
  • sunkn2 = 01h (неизвестное поле);
  • slen = длина имени файла;
  • sfname = имя файла;
  • sfcrc = CRC16 оригинального файла;
  • sunkn3 = 20h (неизвестное поле);
Первым делом заполняется имя файла и поле slen, куда записывается длина имени файла. Строка имени файла не должна заканчиваться нулевым символом. Затем заполняется длина заголовка shlen с учетом длины имени файла, ее значение равно длине всего заголовка минус 2 байта. Неизвестные поля, обозначенные как sunkn1 и sunkn3, по своим значениям очень похожи на атрибуты файла, но по факту они всегда равны 20h (атрибут "архивный"), даже при упаковке файлов с другими атрибутами ничего не меняется. Дата и время создания оригинального файла вообще нигде не учитывается. Контрольная сумма заголовка считается после заполнения всех остальных полей, она равна обычной арифметической сумме всех символов заголовка от поля smeth до shend включительно, но используется только младший байт от этого значения. Контрольная сумма оригинального файла - стандартная CRC16 без каких-либо модификаций.

После заполнения всех полей заголовка устанавливаем указатель на один байт от конца архивного файла, чтобы затереть существующий "хвост". Записываем сформированный заголовок, после него записываем наш файл и признак завершения архива в виде одного нулевого байта. Все, с внедрением в файлы .SAR разобрались.

PRS - формат архиватора PRESS отечественной разработки от Екатеринбургского СКБ "Контур". Единственная найденная в интернете версия датируется 1995 годом. Очень интересная разработка с неплохой степенью сжатия, возможностью создания многотомных архивов, обновлением файлов в архиве (например, для инкрементальных бэкапов) и многими другими полезными функциями. Хороший потенциал, но история распорядилась иначе. По всей видимости, этот архиватор так и остался для внутреннего использования в компании, не получив широкого распространения. Формат архивов на первый взгляд мне показался несложным, но потом пришлось провести несколько дней, медитируя на отладчик и дизассемблерный листинг, пока не удалось выяснить назначение и формат всех необходимых полей.
  1. ;---------------------------------------------
  2. ; PRS Header
  3. ;---------------------------------------------
  4. psign   dd      ?                       ; Signature ('GW',0,0)
  5. posize  dd      ?                       ; Original file size
  6.         db      ?                       ; unknown
  7. plen    db      ?                       ; Filename size
  8.         db      ?                       ; unknown
  9.         db      ?                       ; unknown
  10. pmeth   dw      ?                       ; Compression method (0 = store)
  11. pattr   db      ?                       ; File attribute
  12. pdtm    dd      ?                       ; Date/Time
  13. pcsize  dd      ?                       ; Compressed file size
  14. pfname  rb      (?)                     ; Filename (ASCII)
  15. pcrc1   dw      ?                       ; CRC of header
Заголовок файла в архиве поделен на две части - перед сжатыми данными и после них.
  1. pfcrc   dd      ?                       ; 32-bit CRC of file
  2. pcrc2   dw      ?                       ; CRC of header +8000h
Записываемый файл предварительно надо загрузить в память, после этого заполняем поля первого заголовка архива:
  • psign = сигнатура заголовка файла "GW" и два нулевых байта;
  • posize = размер оригинального файла;
  • plen = длина имени файла;
  • pmeth = метод сжатия (0 = store);
  • pattr = атрибуты файла;
  • pdtm = дата и время создания файла;
  • pcsize = размер сжатого файла (равен оригинальному);
  • pfname = имя файла;
  • pcrc1 = CRC заголовка;
и поля второго заголовка файла:
  • pfcrc = CRC32 оригинального файла;
  • pcrc2 = CRC заголовка и признак окончания архива
Сначала заполняется имя файла и поле plen, куда записывается длина имени файла. Строка имени файла не должна заканчиваться нулевым символом. Затем заполняются размер и атрибуты файла, дата и время создания, метод сжатия. Контрольная сумма оригинального файла - стандартный алгоритм CRC32 без каких-либо модификаций. А вот с контрольной суммой заголовка пришлось повозиться дольше всего. Ее значение равно арифметической сумме всех символов первого заголовка от поля psign до pfname включительно, размер сохраняемого значение 2 байта (WORD). Контрольная сумма заголовка записывается как в первый, так и во второй заголовок, но есть одна важная особенность. Если файл находится в середине архива, то оба значения в первом и втором заголовке равны. Если файл последний, то к значению контрольной суммы во втором заголовке прибавляется константа 8000h, значение в первом заголовке остается без изменений.

После заполнения всех полей заголовка устанавливаем указатель на один байт от конца архивного файла. В нем записан старший байт контрольной суммы заголовка предыдущего файла в архиве, и, чтобы не было ошибок целостности структуры, надо его откорректировать, уменьшив значение на 80h. После этого последний файл оригинального архива становится не последним, а последним будет наш файл. Далее в конец исправленного архива записываем первый сформированный заголовок, после него записываем наш файл и второй заголовок с признаком окончания архива. С внедрением в файлы формата .PRS тоже разобрались.

CAR, название которого происходит от двух слов "Compression/ARchive", - коммерческий архиватор, разработанный в 1996 году компанией MylesHi! Software. Как признаются сами разработчики, алгоритм архиватора повторяет алгоритм работы архиватора LHA, но часть служебных полей в заголовке архива изменены. Из-за этого программы, поддерживающие формат архивов LHA, почти успешно пытаются открыть архивы формата CAR, но просмотреть содержимое и извлечь файлы не могут. Зато в комплекте с архиватором идет подробная инструкция, в которой описан формат и значения всех полей заголовка архива. Было бы глупо не воспользоваться таким подарком.
  1. ;---------------------------------------------
  2. ; CAR Header
  3. ;---------------------------------------------
  4. csize   db      ?                       ; Header size
  5. chcrc   db      ?                       ; Header CRC
  6. cmeth   rb      5                       ; Packing method '-lh0-' = store
  7. ccsize  dd      ?                       ; Compressed file size
  8. cosize  dd      ?                       ; Original file size
  9. cnlen   db      ?                       ; Filename length
  10. cfname  rb      (?)                     ; Filename (ASCII)
  11. cfcrc   dw      ?                       ; File CRC16
  12. cflag   dw      ?                       ; File attribute
  13. cdtm    dd      ?                       ; Time/Date
  14. cres1   db      ?                       ; Reserved 1 (20h)
  15. cres2   dw      ?                       ; Reserved 2
Признаком окончания архива является нулевой байт вместо следующего заголовка файла.
  1. ; Признак окончания архива - нулевой байт
  2. tail    db      0
  3. tail_length   = $-tail 
Записываемый файл также предварительно надо загрузить в память, после этого заполняем поля заголовка.
  • csize = размер заголовка от cmeth до cres2 включительно;
  • cmeth = строка "-lh0-" - метод компрессии Store;
  • cosize = размер оригинального файла;
  • ccsize = размер сжатого файла (равен оригинальному);
  • cdtm = дата и время создания файла;
  • clflag = 20h - атрибуты файла;
  • cnlen = длина имени файла с расширением;
  • cfname = имя файла;
  • cfcrc = CRC16 оригинального файла;
  • cres1 = 20h - какое-то служебное поле;
После заполнения заголовка надо посчитать его контрольную сумму. Тут используется уже известный алгоритм - считается арифметическая сумма символов от cmeth до cres2 включительно и берется от нее младший байт. Полученное значение записывается в поле chcrc. Имя файла может иметь длину до 255 символов и не заканчивается нулевым символом, но при извлечении оно все равно будет обрезано до формата 8:3. Контрольная сумма оригинального файла - стандартная CRC16 без каких-либо модификаций.

После заполнения заголовка надо переместить указатель на 1 байт от конца файла, чтобы удалить существующий "хвост" архива. После этого записываем сформированный заголовок, за ним внедряемый файл и "хвост" архива, состоящий из нулевого символа. Как видите, работа с архивами .CAR мало чем отличается от внедрения в архивы .LZH и его аналогов.

В приложении примеры программ с исходными текстами, демонстрирующие все три описанных способа записи в архивы. При каждом запуске программа дописывает себя к архиву "example" соответствующего формата, выбирая случайное имя исполняемого файла.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Store.to.SAR.without.Archiver.Demo.zip (21,211 bytes)

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Store.to.PRS.without.Archiver.Demo.zip (30,312 bytes)

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Store.to.CAR.without.Archiver.Demo.zip (62,932 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 5098 | Комментариев: 12

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Yellow (17.04.2015 в 23:28):
Я так понимаю, речь всё-таки идёт о "rb (?)" а не просто о "(?)", что в fasm преспокойно существует. А то, что именно Вы этим обозначили, в данном случае не имеет значения. Ничего личного, просто попытался уточнить.
ManHunter (17.04.2015 в 08:44):
ЦитатаМнемокода "(?)" в FASM нет, просто таким образом я обозначил ТЕКСТОВУЮ СТРОКУ для записи имени файла НЕОПРЕДЕЛЕННОЙ ДЛИНЫ.
Yellow (16.04.2015 в 23:38):
А что значит "Мнемокода (?) в FASM нет"? Т.е. нельзя написать, к примеру:
db  12 dup (?)
? Да запросто можно, FASM без проблем "съест". Или Вы о чём-то другом?
brute (11.02.2015 в 12:38):
Намек понял! Полезная вещь!!!
ManHunter (11.02.2015 в 10:40):
В первой части все подробно расписано, что это такое и для чего нужно.
brute (11.02.2015 в 09:26):
я правильно понял, что "программа дописывает себя к архиву "example"" без сжатия? То есть, имеется возможность просто записать в УЖЕ существующий архив? И, при необходимости, "извлечь" только наш неупакованный файл из архива. А самих алгоритмов сжатия\разжатия здесь нет.
п.с. просто думаю, где это можно использовать..
ЖК (11.02.2015 в 05:10):
Годная статья, хороший пример разбора заголовков различных форматов.

Зато прочитав про PRESS, подумалось, что в 90-х очень уж в России любили заниматься архиваторостроением =) А ведь до PRESS уже был RAR, а до RAR - BSA (1991 год), а до BSA - ChArc (1990 год). И все наши, отечественные.
Doxtur (10.02.2015 в 18:40):
ЦитатаЯ считаю, что эти архивы SAR, PRS и CAR не принадлежат к управлению информацией, а вдруг они опасны, тогда можно и с компьютером попрощаться, поэтому прошу удалить этот пост, спасибо.

Ну вот и весна пришла)))
ManHunter (10.02.2015 в 18:15):
Наверное человек увидел незнакомые слова, испугался.
Vladimir (10.02.2015 в 17:30):
Откуда в комментариях к узкоспециальным статьям берутся идиоты...
Спасибо, ManHunter, за любопытные статьи.
ManHunter (10.02.2015 в 13:52):
Не пиши больше ничего, не надо.
flawiimark (10.02.2015 в 12:56):
Я считаю, что эти архивы SAR, PRS и CAR не принадлежат к управлению информацией, а вдруг они опасны, тогда можно и с компьютером попрощаться, поэтому прошу удалить этот пост, спасибо.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.21 сек. / MySQL: 2 (0.0088 сек.) / Память: 4.5 Mb
Наверх