Функции base64 на Ассемблере
Алгоритм Base64 может использоваться в пользовательских почтовых приложениях, в качестве одного из уровней защиты шифрованием, для хранения двоичных данных и для решения многих других задачах. В большинстве языков высокого уровня используются штатные функции, в Ассемблере приходится все реализовывать самостоятельно.Алгоритм Base64 обратимый, то есть из закодированного текста можно в точности получить исходные данные. Начнем с функции кодирования.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------------------
- ; Функция кодирования Base64
- ;---------------------------------------------------------------
- ; Параметры:
- ; lpFrom - указатель на исходные данные
- ; lpTo - указатель на буфер для приема кодированных данных
- ; dSize - размер исходных данных
- ; Функция ничего не возвращает
- ;---------------------------------------------------------------
- proc base64_encode lpFrom:dword, lpTo:dword, dSize:dword
- pusha
- mov ebx,.base64
- mov esi,[lpFrom]
- mov edi,[lpTo]
- mov ecx,[dSize]
- or ecx,ecx
- jz .r3
- .encode_loop:
- lodsd
- mov edx,eax
- bswap edx
- xor eax,eax
- shld eax,edx,6
- shl edx,6
- xlatb
- stosb
- xor eax,eax
- shld eax,edx,6
- shl edx,6
- xlatb
- stosb
- dec ecx
- jz .r2
- xor eax,eax
- shld eax,edx,6
- shl edx,6
- xlatb
- stosb
- dec ecx
- jz .r1
- xor eax,eax
- shld eax,edx,6
- shl edx,6
- xlatb
- stosb
- dec esi
- dec ecx
- jnz .encode_loop
- jmp .r3
- .r2:
- mov al,'='
- stosb
- .r1:
- mov al,'='
- stosb
- .r3:
- xor eax,eax
- stosb
- popa
- ret
- .base64 db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- db 'abcdefghijklmnopqrstuvwxyz'
- db '0123456789+/'
- endp
Функция декодирования. Для удобства использования я поместил код для определения длины строки и таблицу для декодирования прямо в функцию.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------------------
- ; Функция декодирования Base64
- ;---------------------------------------------------------------
- ; Параметры:
- ; lpFrom - указатель на кодированные данные
- ; lpTo - указатель на буфер для приема декодированных данных
- ; dSize - размер кодированных данных, необязательный параметр
- ; На выходе:
- ; EAX - длина декодированных данных
- ;---------------------------------------------------------------
- proc base64_decode lpFrom:dword, lpTo:dword, dSize:dword
- pusha
- ; Если длина строки не указана, то рассчитать
- mov ecx,[dSize]
- or ecx,ecx
- jnz @f
- ; Штатную функцию API не используем
- mov edi,[lpFrom]
- xor ecx,ecx
- dec ecx
- xor eax,eax
- repne scasb
- not ecx
- dec ecx
- or ecx,ecx
- jnz @f
- ; Если длина нулевая, то вернуть пустую строку
- mov edi,[lpTo]
- xor eax,eax
- stosb
- jmp .loc_ret
- @@:
- mov esi,[lpFrom]
- mov edi,[lpTo]
- @@:
- lodsd
- mov edx,eax
- bswap edx
- movzx eax,dl
- mov al,[.base64+eax]
- shrd ebx,eax,6
- shr edx,8
- mov al,dl
- mov al,[.base64+eax]
- shrd ebx,eax,6
- shr edx,8
- mov al,dl
- mov al,[.base64+eax]
- shrd ebx,eax,6
- shr edx,8
- mov al,dl
- mov al,[.base64+eax]
- shrd ebx,eax,6
- bswap ebx
- mov [edi],ebx
- inc edi
- inc edi
- inc edi
- sub ecx,4
- js @f
- jnz @b
- @@:
- mov al,0
- stosb
- mov eax,edi
- sub eax,[lpTo]
- dec eax
- cmp byte[esi-1],'='
- jne @f
- dec eax
- @@:
- cmp byte[esi-2],'='
- jne .loc_ret
- dec eax
- .loc_ret:
- mov [esp+28],eax
- popa
- ret
- .base64 db 43 dup (0), 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x34
- db 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C
- db 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- db 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
- db 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
- db 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
- db 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- db 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21
- db 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29
- db 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31
- db 0x32, 0x33, 133 dup (0)
- endp
Пример использования обеих функций:
Code (Assembler) : Убрать нумерацию
- section '.data' data readable writeable
- ...
- str1 db 'ManHunter / PCL' ; Строка для кодирования
- str2 db 'SGF2ZSBhIE5pY2UgRGF5IQ==',0 ; Закодированная строка
- buffer rb 100h ; Буфер-приемник
- section '.code' code readable executable
- ...
- ; Закодировать строку. Длина строки обязательно указывается
- stdcall base64_encode,str1,buff,15
- ; Теперь buff содержит кодированную строку 'TWFuSHVudGVyIC8gUENM'
- ...
- ; Раскодировать строку. Длина рассчитается автоматически
- stdcall base64_decode,str2,buff,NULL
- ; buff содержит раскодированную строку 'Have a Nice Day!'
- ...
Code (Assembler) : Убрать нумерацию
- CRYPT_STRING_BASE64 = 0x00000001
- ; Максимальный размер буфера-приемника
- mov [output_len],500h
- ; Закодировать строку
- invoke CryptBinaryToString,data_source,data_len,\
- CRYPT_STRING_BASE64,output_buff,output_len
- ...
- ...
- ; Максимальный размер буфера-приемника
- mov [output_len],500h
- ; Раскодировать строку
- invoke CryptStringToBinary,data_encoded,0,\
- CRYPT_STRING_BASE64,output_buff,output_len,NULL,NULL
Просмотров: 5825 | Комментариев: 9
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(27.06.2022 в 15:47):
13 лет уже прошло, давно надо было это все переписать нафиг.
Petya
(27.06.2022 в 10:09):
Если это не я напорол при копировании, что возможно, то функция врёт относительно длины при передаче ей строки "roiBlKncON8x/8bEFVjbvElBFk2v2HnstcVelgNR14c=". Возвращает 33, хотя в строке ровно 32 байта закодировано.
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Мбайт.
Добавить комментарий
Заполните форму для добавления комментария