Blog. Just Blog

Функции base64 на Ассемблере

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

Алгоритм Base64 использует две функции - кодирования данных и обратного декодирования. Для обеих функций кодирования и декодирования предварительно инициализируются следующие вспомогательные данные:
  1. section '.data' data readable writeable
  2. ...
  3. base64_table db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  4.              db "abcdefghijklmnopqrstuvwxyz"
  5.              db "0123456789+/"
  6.  
  7. decode_table rb 100h
  8. ...
А вот сами функции для работы с Base64:
  1. ;---------------------------------------------------------------
  2. ; Функция кодирования Base64
  3. ; Параметры:
  4. ; dFrom - указатель на исходные данные
  5. ; dTo   - указатель на буфер для приема кодированных данных
  6. ; dSize - размер исходных данных
  7. ; Функция ничего не возвращает
  8. ;---------------------------------------------------------------
  9. proc    base64_encode dFrom:dword, dTo:dword, dSize:dword
  10.         push    eax ecx edx esi edi
  11.  
  12.         mov     esi,[dFrom]
  13.         mov     edi,[dTo]
  14.         mov     ecx,[dSize]
  15.  
  16.         or      ecx,ecx
  17.         jz      .r3
  18. .encode_loop:
  19.         lodsd
  20.         mov     edx,eax
  21.         cmp     ecx,3
  22.         jae     .remainder_ok
  23.         and     edx,0ffffh
  24.         cmp     ecx,2
  25.         jae     .remainder_ok
  26.         and     edx,0ffh
  27. .remainder_ok:
  28.         bswap   edx
  29.  
  30.         mov     eax,edx
  31.         shr     eax,26
  32.         and     eax,00111111b
  33.         mov     al,[base64_table+eax]
  34.         stosb
  35.  
  36.         mov     eax,edx
  37.         shr     eax,20
  38.         and     eax,00111111b
  39.         mov     al,[base64_table+eax]
  40.         stosb
  41.         dec     ecx
  42.         jz      .r2
  43.  
  44.         mov     eax,edx
  45.         shr     eax,14
  46.         and     eax,00111111b
  47.         mov     al,[base64_table+eax]
  48.         stosb
  49.         dec     ecx
  50.         jz      .r1
  51.  
  52.         mov     eax,edx
  53.         shr     eax,8
  54.         and     eax,00111111b
  55.         mov     al,[base64_table+eax]
  56.         stosb
  57.  
  58.         dec     esi
  59.         dec     ecx
  60.         jnz     .encode_loop
  61.  
  62.         jmp     .r3
  63. .r2:
  64.         mov     al,'='
  65.         stosb
  66. .r1:
  67.         mov     al,'='
  68.         stosb
  69. .r3:
  70.         xor     eax,eax
  71.         stosb
  72.         pop     edi esi edx ecx eax
  73.         ret
  74. endp
В этой функции все параметры обязательные. Размер буфера-приемника должен быть примерно в 1,5 раза больше исходных данных, это обусловлено особенностями алгоритма кодирования.
  1. ;---------------------------------------------------------------
  2. ; Функция декодирования Base64
  3. ; Параметры:
  4. ; dFrom - указатель на кодированные данные
  5. ; dTo   - указатель на буфер для приема декодированных данных
  6. ; dSize - размер кодированных данных, необязательный параметр
  7. ; На выходе:
  8. ; EAX - длина декодированных данных
  9. ;---------------------------------------------------------------
  10. proc    base64_decode dFrom:dword, dTo:dword, dSize:dword
  11.         ; Если длина строки не указана, то рассчитать
  12.         cmp     [dSize],0
  13.         jnz     .len_not_zero
  14.         ; Штатную функцию API не используем
  15.         stdcall _lstrlen,[dFrom]
  16.         mov     [dSize],eax
  17.         cmp     eax,0
  18.         jnz     .len_not_zero
  19.         ; Если длина нулевая, то вернуть пустую строку
  20.         mov     byte [dTo],0
  21.         xor     eax,eax
  22.         ret
  23. .len_not_zero:
  24.         push    ebx ecx edx esi edi
  25.  
  26.         mov     ecx,[dSize]
  27.         mov     esi,[dFrom]
  28.         mov     edi,[dTo]
  29.  
  30.         xor     eax,eax
  31.         mov     ebx,63
  32. .make_table:
  33.         mov     al,[base64_table+ebx]
  34.         mov     [decode_table+eax],bl
  35.         dec     ebx
  36.         jns     .make_table
  37.         mov     [decode_table+'='],0
  38.         xor     ebx,ebx
  39. .load_dword:
  40.         mov     edx,[esi]
  41.         bswap   edx
  42.         add     esi,4
  43.         mov     al,dl
  44.         mov     al,byte[decode_table+eax]
  45.         shrd    ebx,eax,6
  46.         shr     edx,8
  47.         mov     al,dl
  48.         mov     al,byte[decode_table+eax]
  49.         shrd    ebx,eax,6
  50.         shr     edx,8
  51.         mov     al,dl
  52.         mov     al,byte[decode_table+eax]
  53.         shrd    ebx,eax,6
  54.         shr     edx,8
  55.         mov     al,dl
  56.         mov     al,byte[decode_table+eax]
  57.         shrd    ebx,eax,6
  58.         bswap   ebx
  59.         mov     [edi],ebx
  60.         add     edi,3
  61.         sub     ecx,4
  62.         js      .exit_loop
  63.         jnz     .load_dword
  64. .exit_loop:
  65.         mov     byte[edi],0
  66.         inc     edi
  67.         mov     eax,[dTo]
  68.         sub     edi,eax
  69.         mov     eax,edi
  70.         dec     eax
  71.         pop     edi esi edx ecx ebx
  72.         ret
  73. endp
  74.  
  75. ;---------------------------------------------------------------
  76. ; Вспомогательная функция для расчета длины строки
  77. ; Параметры:
  78. ; lpBuff - указатель на строку в формате ASCIIZ
  79. ; На выходе:
  80. ; EAX - длина строки
  81. ;---------------------------------------------------------------
  82. proc    _lstrlen lpBuff:dword
  83.         push    edi ecx
  84.         mov     edi,[lpBuff]
  85.         xor     ecx,ecx
  86.         dec     ecx
  87.         xor     eax,eax
  88.         repne   scasb
  89.         not     ecx
  90.         dec     ecx
  91.         mov     eax,ecx
  92.         pop     ecx edi
  93.         ret
  94. endp
Поскольку данные, закодированные по алгоритму Base64 могут содержать только печатные символы, то в функции декодирования можно не указывать их длину, она будет посчитана автоматически. Но для этого кодированные данные обязательно должны быть записаны в формате ASCIIZ.

Пример использования обеих функций:
  1. section '.data' data readable writeable
  2. ...
  3. base64_table db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  4.              db "abcdefghijklmnopqrstuvwxyz"
  5.              db "0123456789+/"
  6.  
  7. decode_table rb 100h
  8.  
  9. str1         db 'ManHunter / PCL'             ; Строка для кодирования
  10. str2         db 'SGF2ZSBhIE5pY2UgRGF5IQ==',0  ; Закодированная строка
  11. buffer       rb 100h                          ; Буфер-приемник
  12.  
  13. section '.code' code readable executable
  14.         ...
  15.         ; Закодировать строку. Длина строки обязательно указывается
  16.         stdcall base64_encode,str1,buff,15
  17.         ; Теперь buff содержит кодированную строку 'TWFuSHVudGVyIC8gUENM'
  18.         ...
  19.         ; Раскодировать строку. Длина рассчитается автоматически
  20.         stdcall base64_decode,str2,buff,NULL
  21.         ; buff содержит раскодированную строку 'Have a Nice Day!'
  22.         ...


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 4467 | Комментариев: 7

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

Комментарии

Отзывы посетителей сайта о статье
Grey (24.06.2013 в 13:43):
Все, допер. Расширение поменял туда и обратно. В любом случае спасибо за статью!
ManHunter (24.06.2013 в 13:23):
А какая для ассемблера разница, что кодировать? WMF для него такие же двоичные данные, как JPEG, как этот текст и вообще как все остальное. На входе набор байтов, на выходе набор байтов.
Grey (24.06.2013 в 13:06):
Изображение твоим енкодером в base64. В интернете в основном он-лайновые кодировщики конвертят наиболее распространенные форматы, я хочу в base64 перевести изображение wmf.
ManHunter (24.06.2013 в 12:55):
Для каких целей кодировать? Куда заталкивать?
Grey (24.06.2013 в 12:53):
Чтобы закодировать изображение его нужно без заголовка заталкивать?
ManHunter (13.06.2011 в 01:48):
Нафига тебе 100 метров в base64 переводить??? Решил фильм по почте отправить?
Vladimir (11.06.2011 в 15:57):
Какова скорость работы алгоритма кодирования? Например, для блока памяти размером 100Мбайт.

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

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

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