
Распаковка данных в формате aPLib на Ассемблере

Распаковка данных в формате aPLib на Ассемблере
Вот мы и добрались до одной из самых популярных библиотек для компрессии данных aPLib. Ее разработал Joergen Ibsen в 1998 году, но исходники по какой-то причине до сих пор не раскрыты, хотя сама библиотека бесплатная. За счет превосходных показателей сжатия и легкой интеграции, aPLib используется в некоторых упаковщиках исполняемых файлов. В 2019 году Emmanuel Marty сделал, казалось бы, невозможное. Ему удалось не только отреверсить алгоритм упаковки aPLib, но и улучшить на 5-7% степень сжатия, полностью сохранив при этом совместимость с оригинальным кодом для распаковки. Таким образом, алгоритм aPLib теперь можно считать открытым.
Утилита appack от Joergen Ibsen перед упакованными данными записывает 24-байтный заголовок, в котором находится "магический" маркер (первые два DWORD), размер исходных данных (5-й DWORD), размер упакованных данных (3-й DWORD) и контрольные суммы для проверки целостности (4-й и 6-й DWORD). Упаковщик apultra от Emmanuel Marty выдает просто упакованные данные, поэтому при его использовании размер первоначальных данных для резервирования памяти надо будет получать самостоятельно.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------
- ; Получение размера распакованных данных
- ;---------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; На выходе:
- ; EAX = размер распакованных данных
- ;---------------------------------------------------
- proc aplib_size lpCompressed:DWORD
- pusha
- mov esi,[lpCompressed]
- xor edi,edi
- mov al,080h
- xor edx,edx
- .literal:
- inc esi
- inc edi
- .next_command_after_literal:
- mov ebx,03h
- .next_command:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jnc .literal
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .other
- stdcall .get_gamma2
- sub ecx,ebx
- jae .not_repmatch
- stdcall .get_gamma2
- jmp .got_len
- .not_repmatch:
- mov edx,ecx
- shl edx, 8
- mov dl,[esi]
- inc esi
- stdcall .get_gamma2
- cmp edx,07D00h
- jae .increase_len_by2
- cmp edx,0500h
- jae .increase_len_by1
- cmp edx,0080h
- jae .got_len
- .increase_len_by2:
- inc ecx
- .increase_len_by1:
- inc ecx
- .got_len:
- add edi,ecx
- xor ecx,ecx
- mov bl,02h
- jmp .next_command
- .get_gamma2:
- xor ecx,ecx
- inc ecx
- .gamma2_loop:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .gamma2_loop
- retn
- .other:
- xor ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .short_literal
- movzx edx,byte[esi]
- inc esi
- inc ecx
- shr dl,1
- je .done
- adc ecx,ecx
- jmp .got_len
- .short_literal:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- .write_zero:
- inc edi
- jmp .next_command_after_literal
- .done:
- ; EAX = размер распакованных данных
- mov [esp+28], edi
- popa
- ret
- endp
Поскольку apultra дает максимальное сжатие, я буду использовать именно ее. В интернетах выложена только 64-битная версия упаковщика, 32-битный вариант мне пришлось собирать самостоятельно из авторских исходников. Оба варианта есть в прилагаемом архиве. Как и в случае с LZSA, код Emmanuel Marty в оптимизации не нуждается, он идеален. От меня потребовалось только подкорректировать некоторые синтаксические конструкции для адаптации исходника к диалекту FASM.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Распаковка данных в формате aPLib
- ; Copyright (C) 2019 Emmanuel Marty
- ;------------------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; lpOut - указатель на буфер для распакованных данных
- ; На выходе:
- ; EAX = размер распакованных данных
- ;------------------------------------------------------------
- proc aplib_unpack lpCompressed:DWORD, lpOut:DWORD
- pusha
- mov esi,[lpCompressed]
- mov edi,[lpOut]
- mov al,080h
- xor edx,edx
- .literal:
- movsb
- .next_command_after_literal:
- mov ebx,03h
- .next_command:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jnc .literal
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .other
- stdcall .get_gamma2
- sub ecx,ebx
- jae .not_repmatch
- stdcall .get_gamma2
- jmp .got_len
- .not_repmatch:
- mov edx,ecx
- shl edx, 8
- mov dl,[esi]
- inc esi
- stdcall .get_gamma2
- cmp edx,07D00h
- jae .increase_len_by2
- cmp edx,0500h
- jae .increase_len_by1
- cmp edx,0080h
- jae .got_len
- .increase_len_by2:
- inc ecx
- .increase_len_by1:
- inc ecx
- .got_len:
- push esi
- mov esi,edi
- sub esi,edx
- rep movsb
- pop esi
- mov bl,02h
- jmp .next_command
- .get_gamma2:
- xor ecx,ecx
- inc ecx
- .gamma2_loop:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .gamma2_loop
- retn
- .other:
- xor ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- jc .short_literal
- movzx edx,byte[esi]
- inc esi
- inc ecx
- shr dl,1
- je .done
- adc ecx,ecx
- jmp .got_len
- .short_literal:
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- add al,al
- jnz @f
- lodsb
- adc al,al
- @@:
- adc ecx,ecx
- xchg eax,ecx
- jz .write_zero
- mov ebx,edi
- sub ebx,eax
- mov al,[ebx]
- .write_zero:
- stosb
- mov eax,ecx
- jmp .next_command_after_literal
- .done:
- sub edi,[lpOut]
- mov [esp+28],edi
- popa
- ret
- endp
В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму aPLib, и выводит ее на форму. Там же в архиве утилита для упаковки и распаковки данных от Emmanuel Marty.
Просмотров: 1272 | Комментариев: 2
Метки: Assembler, распаковка

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(19.03.2021 в 07:48):
Ну вот, а тут все сразу и со всеми исходниками.

user
(18.03.2021 в 23:21):
Когда-то году в 2000-м реверснул распаковщик aPLib,
распаковывал PECO. Заинтересовался тогда этой библиотекой,
начал было ковырять её, но так и забросил, за отсутствием острой надобности.
распаковывал PECO. Заинтересовался тогда этой библиотекой,
начал было ковырять её, но так и забросил, за отсутствием острой надобности.

Добавить комментарий
Заполните форму для добавления комментария
