Blog. Just Blog

Работа с escape-последовательностями на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Работа с escape-последовательностями на Ассемблере
Работа с escape-последовательностями на Ассемблере

Escape-последовательности, также известные как экранированные последовательности или символьные объекты, представляют собой особый метод представления символов внутри строк. В зависимости от синтаксиса языка, ими могут кодироваться не только ASCII-символы, но и вся последовательность юникода UTF-16 и даже UTF-32. В процессе компиляции или при отображении на экране каждая escape-последовательность заменяется на соответствующий ей код символа. Кроме этого, такую запись символов очень часто используют в различных обфускаторах для скриптов PHP и JavaScript с целью затруднения визуального анализа текстовых строк или кодирования исходных текстов. Escape-последовательность обычно распознается по начальному символу обратного слеша и фиксированному количеству символов, следующих за ним.

Функция раскодирования escape-последовательностей принимает в качестве параметров три значения: указатель на исходную строку, длина исходной строки и указатель на буфер для раскодированной строки. В принципе, можно было бы модифицировать функцию, чтобы в ней же определялась длина исходной строки, но пока так.
  1. ;-----------------------------------------------------------------------
  2. ; Функция Escape-декодирования
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;-----------------------------------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ;       lpBuff - указатель на буфер-приемник
  10. ;-----------------------------------------------------------------------
  11. proc    esc_decode lpData:DWORD, dSize:DWORD, lpBuff:DWORD
  12.         push    eax ebx ecx edx edi esi
  13.  
  14.         mov     ecx,[dSize]
  15.         mov     esi,[lpData]
  16.         mov     edi,[lpBuff]
  17.  
  18.         or      ecx,ecx
  19.         jz      .loc_done
  20. .loc_decode:
  21.         xor     eax,eax
  22.         lodsb
  23.  
  24.         ; Возможно, это закодированный символ
  25.         cmp     al,'\'
  26.         jne     .loc_store
  27.  
  28.         ; Строка заканчивается?
  29.         cmp     ecx,4
  30.         jb      .loc_store
  31.  
  32.         ; Однобайтовые юникод-скаляры \xNN
  33.         cmp     byte [esi],'x'
  34.         jne     @f
  35.         jmp     .decode_ascii
  36. @@:
  37.         ; Двухбайтные юникод-скаляры \uNNNN (UTF-16)
  38.         cmp     byte [esi],'u'
  39.         jne     @f
  40.         ; Строка заканчивается?
  41.         cmp     ecx,6
  42.         jb      .loc_store
  43.         jmp     .decode_unicode16
  44. @@:
  45.         ; Четыребайтные юникод-скаляры \UNNNNNNNN (UTF-32)
  46.         cmp     byte [esi],'U'
  47.         jne     .loc_store
  48.         ; Строка заканчивается?
  49.         cmp     ecx,10
  50.         jb      .loc_store
  51.         jmp     .decode_unicode32
  52.  
  53. .decode_ascii:
  54.         ; Проверить следующие символы
  55.         push    eax
  56.         xor     ebx,ebx
  57.         xor     edx,edx
  58.         inc     edx
  59.         mov     ah,3
  60.         jmp     .decode_digit
  61.  
  62. .decode_unicode16:
  63.         ; Проверить следующие символы
  64.         push    eax
  65.         xor     ebx,ebx
  66.         xor     edx,edx
  67.         inc     edx
  68.         mov     ah,5
  69.         jmp     .decode_digit
  70.  
  71. .decode_unicode32:
  72.         ; Проверить следующие символы
  73.         push    eax
  74.         xor     ebx,ebx
  75.         xor     edx,edx
  76.         inc     edx
  77.         mov     ah,9
  78.  
  79. .decode_digit:
  80.         shl     ebx,4
  81.         mov     al,byte [esi+edx]
  82.         cmp     al,'0'
  83.         jb      .loc_skip
  84.         cmp     al,'9'
  85.         ja      @f
  86.         sub     al,'0'
  87.         jmp     .decode_digit_next
  88. @@:
  89.         ; Символ в нижний регистр
  90.         or      al,20h
  91.         cmp     al,'a'
  92.         jb      .loc_skip
  93.         cmp     al,'f'
  94.         ja      .loc_skip
  95.         sub     al,'a'-10
  96. .decode_digit_next:
  97.         add     bl,al
  98.         inc     edx
  99.         cmp     dl,ah
  100.         jb      .decode_digit
  101.  
  102.         xchg    eax,ebx
  103.         shr     ebx,8
  104.  
  105.         ; Пропустить следующие символы
  106.         sub     ecx,ebx
  107.         add     esi,ebx
  108.  
  109.         pop     ebx
  110.         jmp     .loc_store
  111. .loc_skip:
  112.         pop     eax
  113.  
  114. .loc_store:
  115.         cmp     eax,0FFh
  116.         jbe     .loc_store_byte
  117.         cmp     eax,0FFFFh
  118.         jbe     .loc_store_word
  119. .loc_store_dword:
  120.         ; Записать раскодированный юникодный символ в строку
  121.         stosd
  122.         jmp     @f
  123. .loc_store_word:
  124.         ; Записать раскодированный юникодный символ в строку
  125.         stosw
  126.         jmp     @f
  127. .loc_store_byte:
  128.         ; Записать раскодированный символ в строку
  129.         stosb
  130. @@:
  131.         dec     ecx
  132.         or      ecx,ecx
  133.         jnz    .loc_decode
  134. .loc_done:
  135.         ; Символ конца строки
  136.         mov     al,0
  137.         stosb
  138.  
  139.         pop     esi edi edx ecx ebx eax
  140.         ret
  141. endp
Функция универсальная, обрабатывает как однобайтовые скаляры вида \xNN, двухбайтные юникод-скаляры вида \uNNNN для строк в формате UTF-16 и даже четырехбайтные скаляры вида \UNNNNNNNN, которые используются при кодировании строк в формате UTF-32. Исходная строка может содержать как обычные символы, так и все перечисленные виды скаляров в любом сочетании, все будет корректно раскодировано. Исключение могут составить только суррогатные пары UTF-16, и предусмотренные синтаксисом некоторые языков скаляры вида \NNN в восьмеричной системе счисления. Но на практике при решении своих задач я с ними не сталкивался, поэтому никакой дополнительной обработки таких ситуаций не предусмотрено, если понадобится, то можете доработать функцию самостоятельно. Размер буфера-приемника не проверяется, поэтому он должен быть не менее длины исходной строки с учетом завершающего нулевого символа (признак окончания строки).

Функция преобразования строки в escape-последовательность принимает три параметра: указатель на исходную строку, длина исходной строки и указатель на буфер для закодированной строки.
  1. ;-----------------------------------------------------------------------
  2. ; Функция Escape-кодирования
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;-----------------------------------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ;       lpBuff - указатель на буфер-приемник
  10. ;-----------------------------------------------------------------------
  11. proc    esc_encode lpData:DWORD, dSize:DWORD, lpBuff:DWORD
  12.         push    eax ecx edi esi
  13.  
  14.         mov     ecx,[dSize]
  15.         mov     esi,[lpData]
  16.         mov     edi,[lpBuff]
  17.  
  18.         or      ecx,ecx
  19.         jz      .loc_done
  20.  
  21. .loc_encode:
  22.         ; Префикс однобайтового скаляра
  23.         mov     ax,'\x'
  24.         stosw
  25.  
  26.         ; Загрузить символ из строки
  27.         lodsb
  28.  
  29.         ; Перевести байт в HEX-строку
  30.         movzx   eax,al
  31.         ror     eax,4
  32.         and     al,0Fh
  33.         daa
  34.         add     al,0F0h
  35.         adc     al,40h
  36.         stosb
  37.  
  38.         shr     eax,28
  39.         and     al,0Fh
  40.         daa
  41.         add     al,0F0h
  42.         adc     al,40h
  43.         stosb
  44.  
  45.         loop    .loc_encode
  46. .loc_done:
  47.         ; Символ конца строки
  48.         mov     al,0
  49.         stosb
  50.  
  51.         pop     esi edi ecx eax
  52.         ret
  53. endp
При кодировании не делается различий между символами юникода и ASCII, все символы преобразуются в однобайтовые скаляры. Размер буфера для приема кодированной строки не проверяется и должен заранее определяться с тем расчетом, что каждый символ исходной строки преобразуется в четыре закодированных символа плюс нулевой символ окончания строки.

В приложении примеры двух программ с исходными текстами, демонстрирующие функции escape-кодирования и декодирования текстовых строк.

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

Escape.Sequences.Demo.zip (5,526 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
Игорь (12.07.2015 в 08:38):
Спасибо

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

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

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