Blog. Just Blog

Упаковка и распаковка данных с помощью Runtime-функций

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

За последнее время тут было выложено немало распаковщиков для различных алгоритмов компрессии данных. Теперь расскажу о штатных функциях упаковки и распаковки, которые есть в Windows. Плюсы их использования в том, что не надо таскать за собой разные алгоритмы или библиотеки, все делается парой системных функций. Степень компрессии, конечно, получается где-то на уровне плинтуса, но этого вполне хватит, например, чтобы в половину утрамбовать логи вашей поняшки перед отправкой на сервер.

Начнем с упаковки данных. Тут используются две функции - RtlGetCompressionWorkSpaceSize и RtlCompressBuffer. С помощью первой определяется размер рабочего буфера для упаковки, а с помощью второй данные пакуются.
  1.         COMPRESSION_ENGINE_MAXIMUM = 0x0100
  2.         COMPRESSION_FORMAT_LZNT1 = 0x0002
  3.  
  4.         invoke  RtlGetCompressionWorkSpaceSize,\
  5.                 COMPRESSION_FORMAT_LZNT1+COMPRESSION_ENGINE_MAXIMUM,\
  6.                 cbwss,cfwss
  7.         invoke  GlobalAlloc,GMEM_MOVEABLE,[cfwss]
  8.         mov     [hMem],eax
  9.         invoke  GlobalLock,eax
  10.         mov     [workspace],eax
  11.  
  12.         ; Упаковать данные
  13.         invoke  RtlCompressBuffer,\
  14.                 COMPRESSION_FORMAT_LZNT1+COMPRESSION_ENGINE_MAXIMUM,\
  15.                 [original_data],[original_size],\
  16.                 [packed_data],[packed_size],4096,compressed_size,\
  17.                 [workspace]
  18.  
  19.         ; [packed_data] -> упакованные данные
  20.         ; [compressed_size] -> размер упакованных данных
Что интересно, в обеих функциях заявлены несколько алгоритмов сжатия, хотя по факту работает только один - LZ compression, все остальные варианты при попытке использования возвращают ошибку. Почему так? Идем на сайт MSDN и открываем описание функции распаковки RtlDecompressBuffer:


CompressionFormat
A bitmask that specifies the compression format of the compressed buffer. This parameter must be set to COMPRESSION_FORMAT_LZNT1.


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

А вот пример распаковки данных. Тут используется всего одна функция RtlDecompressBuffer, о ее причудах я написал чуть выше.
  1.         COMPRESSION_FORMAT_LZNT1 = 0x0002
  2.  
  3.         ; Распаковать данные
  4.         invoke  RtlDecompressBuffer,\
  5.                 COMPRESSION_FORMAT_LZNT1,[unpacked_data],[buffer_size],\
  6.                 [packed_data],[packed_size],unpacked_size
  7.  
  8.         ; [unpacked_data] -> распакованные данные
  9.         ; [unpacked_size] -> размер распакованных данных
В приложении примеры программ с исходными текстами. Это простейший упаковщик данных, работающий через командную строку, и программа, которая извлекает из памяти иконку с помощью штатных Runtime-функций, а затем выводит ее на форму.

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

Runtime.Library.Pack.Unpack.Demo.zip (6,370 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
Petya (07.04.2021 в 17:08):
Цитатафлаги не DWORD, а QWORD

x64 начал проникать всюду?
Цитатавы можете использовать любой формат сжатия данных, но только если это будет формат LZ

Вроде есть куда более адекватные и документированные (к сожалению, работают только с файлами) ф-ии из kernel32 LZ(Open,Read,Write,etc.)File, похоже - именно с описанными Rtl под капотом.
ManHunter (31.03.2021 в 17:37):
IDA здорово помогла, декомпилировал свою же программу :) Оказывается, тут структуры передаются не по референсу, а льются напрямую в стек, и флаги не DWORD, а QWORD. Звездец какой... Разобрался, будет статья. А жмет действительно классно, на больших файлах уделала даже aPLib.
DRON (31.03.2021 в 16:12):
Вот вроде какой-то пример:
https://github.com/bats3c/Ghos.../compess.cpp
DRON (31.03.2021 в 15:58):
Упаковка:
  Input.lpStart=<Указатель на исходные данные>
  Input.uSize:=<Размер данных>
  Input.Editable=0
  CreateDeltaB(DELTA_FILE_TYPE_SET_EXECUTABLES,0,0,EMPTY_INPUT,
    Input,EMPTY_INPUT,EMPTY_INPUT,EMPTY_INPUT,nil,32,Output)
  Output.lpStart - запакованные данные
  Output.uSize - и их размер
  DeltaFree(Output.lpStart)

Распаковка:
  Input.lpStart=<Указатель на запакованные данные>
  Input.uSize=<Их размер>
  Input.Editable=0
  ApplyDeltaB(DELTA_FLAG_NONE,EMPTY_INPUT,Input,Output)
  Output.lpStart - распакованные данные
  Output.uSize - и их размер
  DeltaFree(Output.lpStart)
ManHunter (30.03.2021 в 12:21):
Спасибо за наводку, обязательно посмотрю. Если разберусь, то будет статейка и по ним тоже. А то пока не могу найти ни одного нормального рабочего примера.
DRON (28.03.2021 в 19:04):
Из встроенного в винду есть ещё CreateDeltaB/ApplyDeltaB (MSDELTA.DLL). Сжимает на уровне LZMA особенно хорошо жмёт EXE-шники.

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

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

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