вот когда-то писал, мож пригодится Код (Text): .486 .model flat, stdcall option casemap: none include windows.inc include kernel32.inc includelib kernel32.lib .data? buf db 256 dup (?) buf2 db 1024 dup (?) .data alphabet db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ALPHABET_LEN equ $-alphabet pad db '=' sBase64 db 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0',\ 'aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1',\ 'c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0',\ 'aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdl',\ 'LCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=' .code base64encode proto szSource:DWORD,szOut:DWORD, sAphabet:DWORD ;ret eax = size Out base64encode proc uses esi edi ebx, szSource:DWORD, szOut:DWORD, sAlphabet:DWORD ;szOut > szSource на 30% + 1b LOCAL pMem: DWORD LOCAL nMem: DWORD invoke lstrlen, szSource mov ebx, eax xor edx, edx mov ecx, 3 div ecx .if edx != 0 push ebx or ebx, 3 mov nMem, ebx pop ebx invoke VirtualAlloc, 0, nMem, MEM_COMMIT, PAGE_READWRITE mov pMem, eax invoke lstrcpy, pMem, szSource mov edi, pMem add edi, ebx mov ecx, nMem sub ecx, ebx cld mov al, 0 rep stosb mov esi, pMem .elseif mov esi, szSource .endif mov edi, szOut mov ebx, sAlphabet xor edx,edx .repeat lodsb .if al==0 .break .endif mov ah, al and ah, 11b and al, 011111100b shr al, 2 mov dl, al mov al, [ebx+edx] stosb lodsb and al, 011110000b shr al, 4 shl ah, 4 or al,ah mov dl, al mov al, [ebx+edx] stosb mov ah,[esi-1] and ah, 01111b lodsb and al, 011000000b shr al, 6 shl ah, 2 or al, ah mov dl, al mov al, [ebx+edx] stosb mov dl, [esi-1] and dl, 0111111b mov al, [ebx+edx] stosb .until FALSE mov al, '=' stosb .if pMem != 0 invoke VirtualFree, pMem, 0, MEM_RELEASE .endif mov eax, szOut sub edi, eax mov eax, edi ret base64encode endp ;in: al = alphabet char ;out: al = alphabet char's index base64getindex proto sAlphabet:DWORD base64getindex proc uses edi ecx, sAlphabet:DWORD mov edi, sAlphabet mov ecx, ALPHABET_LEN+1 repne scasb .if ecx==0 invoke ExitProcess,0 .endif mov eax, ALPHABET_LEN+1 sub eax, ecx dec eax ret base64getindex endp base64decode proto szSource:DWORD, szOut:DWORD, sAlphabet:DWORD base64decode proc uses esi edi ebx, szSource:DWORD, szOut:DWORD, sAlphabet:DWORD mov esi, szSource mov edi, szOut mov edx, sAlphabet cld xor eax, eax .repeat lodsb .if al=='=' .break .endif invoke base64getindex, edx mov bh, al shl bh, 2 lodsb invoke base64getindex, edx mov bl, al and al, 110000b shr al, 4 or al, bh and bl, 01111b shl bl, 4 mov bh, bl stosb lodsb invoke base64getindex, edx mov bl, al and al, 111100b shr al, 2 or al, bh and bl, 11b shl bl, 6 mov bh, bl stosb lodsb invoke base64getindex, edx or al, bh stosb .until FALSE mov al, 0 stosb invoke lstrlen, szOut ret base64decode endp start: invoke base64decode, offset sBase64, offset buf2, offset alphabet ret end start вроде работает, хотя koderr показывал более элегантный код
Интересный код. Спасибо! Однако, не внедряясь в самые дебри хотелось бы (давно уже хотелось бы ) уточнить: этот код кодирует данные, размер которых кратен 3-м. Ведь так? А что делать, если, скажем, длина данных 8 байт, а не 9? В этом случае надо представить, 2 символа - по "6 бит", и один - "4 бита"? Или я не прав?
ой, я вспомнил тот код что был малость бажный, я после того его обновлял, обновил предидущий пост. MSoft прав, недостающие биты принимаются равными 0 вот "тута" проверяется входной буфер на кратность 3 и принимаются и добавляются нужные нулевые биты. Код (Text): invoke lstrlen, szSource mov ebx, eax xor edx, edx mov ecx, 3 div ecx .if edx != 0 ... кстати если это применять в своём софте в должности тривиальной шифровки и изменить порядок буков в алфавите можно заставить почесать репу тем кто это отснифает
rain, во-первых, хочу сказать спасибо зо то, что вернул меня к этому коду - давно хотел сесть, но никак руки не доходили Во-вторых, я сделал немного не так. Может это и не соответствует норме, но, тем не менее, мой код обрабатывает данные любой длины: [deleted] код был удален, т.к. делал все наоборот Щас чуточку подправлю и выложу Я просто разбиваю все данные на блоки по 6 бит. Т.е. получается, если данных было на 4 байта, то в блоках это будет выглядеть так: 5 блоков по 6 бит, а последний блок будет состоять из 2-х бит. Вот этот самый последний блок я обрабатываю как полноценный блок, т.е. тоже ищу ему соответствие в "алфавите" P.S.: вместо знака "/" я использую знак "-". Функцию раскодирования напишу позже, если убдут заявки А щас мультик начинается
не, так не интересно Надо самому помучиться Вобщем, дописал код, исправил ошибки. Вроде бы работаить правильно: Код (Text): ;##################################################### ;##################################################### Base64EncodeA proc lpSrc,lpDst:DWORD push edi mov edi,lpSrc xor eax,eax @@: scasb jnz @B dec edi sub edi,lpSrc push edi push lpDst push lpSrc call Base64Encode pop edi ret Base64EncodeA endp Base64Encode proc lpSrc,lpDst,dwSize:DWORD pushad xor eax,eax mov esi,lpSrc mov edi,lpDst mov ecx,dwSize jecxz _end _next_dword: lodsb mov dl,al shr al,2 ;al = первые 6 бит данных and dl,11b ;ah = оставшиеся 2 бита данных call _convert_byte ;конвертировать и сохранить первый байт dec ecx jz @F lodsb @@: mov ah,al shr al,4 shl dl,4 or al,dl and ah,1111b call _convert_byte jecxz _end_data dec ecx jz @F lodsb @@: mov dl,ah mov ah,al shr al,6 shl dl,2 or al,dl and ah,111111b call _convert_byte jecxz _end_data mov al,ah call _convert_byte dec ecx jnz _next_dword _end_data: mov ecx,edi sub ecx,lpDst and ecx,11b ;остаток от деления на 4 jecxz @F sub ecx,4 neg ecx @@: mov al,'=' rep stosb xor al,al stosb dec edi sub edi,lpDst mov eax,edi _end: mov [esp+7*4],eax popad ret _convert_byte: mov bh,'A' cmp al,25 jbe @F mov bh,'a'-26 cmp al,51 jbe @F mov bh,'0'-52 cmp al,61 jbe @F mov bh,'+'-62 cmp al,62 jz @F ;inc bh ;для символа "-" mov bh,'/'-63 ;для символа "/" @@: add al,bh stosb xor al,al retn Base64Encode endp ;##################################################### ;##################################################### Base64Decode proc lpSrc,lpDst:DWORD pushad mov esi,lpSrc mov edi,lpDst _next_dword: lodsb or al,al jz _end cmp al,'=' jz _end call _convert_byte mov ah,al lodsb or al,al jz _end ;если хоть один 2-х первых из байт блока "неполноценный", тогда дальше не раскодировать cmp al,'=' jz _end call _convert_byte ;здесь ah - первый раскодированный байт, al - второй xchg ah,al mov dl,ah shr dl,4 shl al,2 or al,dl shl ah,4 stosb ;сохранить первый раскодированный байт lodsb or al,al jz _end cmp al,'=' jz _end call _convert_byte xchg ah,al mov dl,ah shr dl,2 or al,dl shl ah,6 stosb ;сохранить второй раскодированный байт lodsb or al,al jz _end cmp al,'=' jz _end call _convert_byte or al,ah stosb ;сохранить третий раскодированный байт jmp _next_dword _end: sub edi,lpDst mov [esp+7*4],edi popad ret _convert_byte: mov bh,'+'-62 cmp al,'+' jz @F ; inc bh ;для символа "-" mov bh,'/'-63 ;для символа "/" cmp al,'/' jz @F mov bh,'0'-52 cmp al,'9' jbe @F mov bh,'A' cmp al,'Z' jbe @F mov bh,'a'-26 @@: sub al,bh retn Base64Decode endp Если кто найдет ошибки, буду крайне признателен
исправлено кстати, справедливости ради стоит заметить, что код Quantum'а действительно меньше моего. Причем намного меньше: функция кодирования у него занимает на 16, а раскодирования - аж на 26 байт меньше. Однако позволю себе сделать такое замечание: я попробовал закодировать строку "hello, i am a virus!". В результате и у квантума и у себя получил "aGVsbG8sIGkgYW0gYSB2aXJ1cyE=". Однако при расшивровке, если убрать последний символ, т.е. знак "=", то функция квантума обрезает последние 2 байта, т.е. получается "hello, i am a viru". У меня такого не происходит. Возможно, это как-то связано с диалогом или нулевым символом в конце, но тем не менее такое печальное событие имеет место быть у него
Насколько я знаю base64, обрезать "=" в конце просто некорректно, получится недопустимая с точки зрения декодера строка...
diamond, ты прав. Но я рассматриваю вариант, когда строка может быть повреждена. Тотже знак "=" в моем примере по сути не играет абсолютно никакой роли, но функция quantum'а это не учитвает. В целом, это конечно же мелочь.
Насколько понял я, знак "=" используется только для выравнивания текста по 4 байта. И все, никакой нагрузки он не несет. В правильном коде он конечно же обязан быть, но, т.к. нагрузки он не несет, я счел нужным обработать вариант, когда этого символа в силу определенных причин нет.
rain И где же утверждается противоположное? Строки "c3VyZQ==" и "c3Vy" правильные, а "c3VyZQ=" и "c3VyZQ" - нет. MSoft Если выравнивающих символов "=" в конце нет, то с ненулевой вероятностью строка повреждена и только нехваткой дело не ограничивается. Впрочем, что именно возвращать на выходе в случае некорректного входа - вопрос, не имеющий особого смысла (главное, не падать )