gzuncompress и gzinflate: Assembler vs PHP
При разработке проекта Massacre возникла необходимость реализовать функции распаковки PHP-кода на Ассемблере. В этой статье я распишу все выкладки по этому вопросу. Кому-нибудь пригодится - хорошо, не пригодится - оставлю для себя, чтобы не забыть. Как всегда, начнем с теории. Функции gzuncompress и gzinflate обратны к функциям gzcompress и gzdeflate, соответственно. Все они используют алгоритм сжатия LZW, который также используется в бесплатной библиотеке zlib. Сперва скачаем эту библиотеку и воспользуемся Ассемблером, чтобы сжать какую-нибудь эталонную строку.Code (Assembler) : Убрать нумерацию
- format PE GUI 4.0
- entry start
- include 'win32a.inc'
- section '.data' data readable writeable
- strr db 'ManHunter' ; Строка для компрессии
- lend = $-strr
- bsize = 1000
- blen dd bsize
- tmp rb bsize
- tmp2 rb bsize
- tmp3 rb bsize
- mask db '%.2X ',0
- ;----------------------------------------------------------
- section '.code' code readable executable
- start:
- invoke compress,tmp,blen,strr,dword lend
- mov ecx,[blen]
- mov esi,tmp
- @@:
- push ecx
- movzx eax,byte [esi]
- invoke wsprintf,tmp2,mask,eax
- add esp,12
- invoke lstrcat,tmp3,tmp2
- inc esi
- pop ecx
- loop @b
- invoke MessageBox,HWND_DESKTOP,tmp3,NULL,MB_OK
- invoke ExitProcess,0
- ;----------------------------------------------------------
- section '.idata' import data readable writeable
- library kernel32,"kernel32.dll",\
- user32,"user32.dll",\
- zlib,"zlib1.dll"
- include "apia\kernel32.inc"
- include "apia\user32.inc"
- import zlib,\
- compress,'compress'
78 9C F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
Часть строки я специально выделил красным цветом, дальше будет понятно зачем это сделано.
А теперь проделаем то же самое, но на PHP. Простенький скрипт покажет результаты работы обеих функций с разными параметрами сжатия. Строка, естественно, та же самая.
Code (PHP) : Убрать нумерацию
- <?
- $str="ManHunter";
- for ($cl=0; $cl<=10; $cl++) {
- if ($cl==10) {
- echo "DFLT - ";
- $tmp=gzdeflate($str);
- }
- else {
- echo "CL=".$cl." - ";
- $tmp=gzdeflate($str,$cl);
- }
- for ($i=0; $i<strlen($tmp); $i++) {
- printf("%02X ",ord(substr($tmp,$i,1)));
- }
- echo "<br>";
- }
- echo "<br>";
- for ($cl=0; $cl<=10; $cl++) {
- if ($cl==10) {
- echo "DFLT - ";
- $tmp=gzcompress($str);
- }
- else {
- echo "CL=".$cl." - ";
- $tmp=gzcompress($str,$cl);
- }
- for ($i=0; $i<strlen($tmp); $i++) {
- printf("%02X ",ord(substr($tmp,$i,1)));
- }
- echo "<br>";
- }
- ?>
CL=0 - 01 09 00 F6 FF 4D 61 6E 48 75 6E 74 65 72
CL=1 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=2 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=3 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=4 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=5 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=6 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=7 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=8 - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=9 - F3 4D CC F3 28 CD 2B 49 2D 02 00
DFLT - F3 4D CC F3 28 CD 2B 49 2D 02 00
CL=0 - 78 01 01 09 00 F6 FF 4D 61 6E 48 75 6E 74 65 72 11 11 03 93
CL=1 - 78 01 F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=2 - 78 5E F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=3 - 78 5E F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=4 - 78 5E F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=5 - 78 5E F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=6 - 78 9C F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=7 - 78 DA F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=8 - 78 DA F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
CL=9 - 78 DA F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
DFLT - 78 9C F3 4D CC F3 28 CD 2B 49 2D 02 00 11 11 03 93
Здесь тоже выделены некоторые строки. Они частично совпадают в случае использования gzdeflate и gzcompress, а в случае gzcompress с дефолтной степенью сжатия строка вообще полностью идентична результатам вызова функции compress библиотеки zlib. Можно сделать первые выводы: результат работы gzdeflate - только упакованные данные, а gzcompress - заголовок + упакованные данные + служебные данные. Возможно, служебные данные - это контрольная сумма или что-то около того, потому что при ее изменении распаковка вылетает с ошибкой. Но упакованные данные, выделенные красным цветом, во всех трех случаях одинаковые. Отсюда следует, что строка, сжатая командой gzcompress, распаковывается функцией uncompress библиотеки zlib без каких-либо изменений, и если в коде PHP-скрипта встречается функция gzuncompress, то ее аргументы можно смело распаковывать штатными средствами. А как быть с gzinflate, если у ее аргументов отсутствуют служебные данные? Попробуем просто дописать их и распаковать полученную строку.
Code (Assembler) : Убрать нумерацию
- format PE GUI 4.0
- entry start
- include 'win32a.inc'
- section '.data' data readable writeable
- strr db 078h,09Ch ; Заголовок
- db 0F3h,04Dh,0CCh,0F3h,028h,0CDh,02Bh,049h,02Dh,002h,000
- db 0,0,0,0 ; Служебные данные неизвестны, просто заменим их нулями
- lend = $-strr
- bsize = 1000
- blen dd bsize
- tmp rb bsize
- ;----------------------------------------------------------
- section '.code' code readable executable
- start:
- invoke uncompress,tmp,blen,strr,dword lend
- invoke MessageBox,HWND_DESKTOP,tmp,NULL,MB_OK
- invoke ExitProcess,0
- ;----------------------------------------------------------
- section '.idata' import data readable writeable
- library kernel32,"kernel32.dll",\
- user32,"user32.dll",\
- zlib,"zlib1.dll"
- include "apia\kernel32.inc"
- include "apia\user32.inc"
- import zlib,\
- uncompress,'uncompress'
В приложении скрипт на PHP и примеры программ на Ассемблере, использованные в статье. Исходники без комментариев, все параметры вызова функций zlib можно посмотреть на офсайте или в прилагаемой к дистрибутиву документации.
Просмотров: 6273 | Комментариев: 6
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
zlib
(29.06.2015 в 20:08):
спасибо работает
Redee
(08.01.2014 в 01:14):
Интересно!
JokerBaD
(16.05.2012 в 05:00):
Спасибо)Интересная статья.
shomeax
(13.11.2011 в 07:41):
хех. ну там как бы не просто "служебная информация", а паддинг. если этот код исполнялся бы на уровне ядра, то мог бы иногда падать из-за выхода за границы страницы. а в случае приложения - ок, там сегмент данных ещё приличный сзади =)
Zummenix
(10.08.2009 в 16:22):
Обязательно пригодится :)
Добавить комментарий
Заполните форму для добавления комментария
ссылка http://www.zlib.net/zlib123-dll.zip недоступна
на 29/08/2017 актуальная ссылка www.winimage.com/zLibDll/zlib123dll.zip