Hello,
I know how to encrypt files into Base64 encrypted form so I can send them as an attachment with email. Now, I want to know how do I decode an encrypted attachment.

If I got the code "xxxxx.................xxxx" which is encrypted into Base64, I want to get the original file.

Orig.exe - "xxxxxxxxxxxxxxxxxxx" (encrypted)
Orig.exe - "yyyyyyyyyyyyyyyyyyy" (not encrypted)

Here is the code for encoding (I didn't write it):

encodeBase64 Proc

xor esi,esi
call over_enc_table
db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
db "abcdefghijklmnopqrstuvwxyz"
db "0123456789+/"
over_enc_table:
pop edi
push ebp
xor ebp,ebp
baseLoop:
movzx ebx,byte ptr
shr bl,2
and bl,00111111b
mov bh,byte ptr
mov byte ptr ,bh
inc esi

mov bx,word ptr
xchg bl,bh
shr bx,4
mov bh,0
and bl,00111111b
mov bh,byte ptr
mov byte ptr ,bh
inc esi

inc eax
mov bx,word ptr
xchg bl,bh
shr bx,6
xor bh,bh
and bl,00111111b
mov bh,byte ptr
mov byte ptr ,bh
inc esi

inc eax
xor ebx,ebx
movzx ebx,byte ptr
and bl,00111111b
mov bh,byte ptr
mov byte ptr ,bh
inc esi
inc eax

inc ebp
cmp ebp,24
jna DontAddEndOfLine

xor ebp,ebp
mov word ptr ,0A0Dh
inc esi
inc esi
test al,00h
org $-1

DontAddEndOfLine:

inc ebp
sub ecx,3
or ecx,ecx
jne baseLoop

mov ecx,esi
add edx,esi
pop ebp
ret

encodeBase64 EndP


edx - Where to store encrypted data
eax - what to encrypt

Output:
ecx - size of encrypted data
Posted on 2002-03-12 14:17:27 by Cube
Hi,

be carefull using this proc. IMHO this implemetation is wrong because I can't see the padding required if the data to be encoded has a length which is not a multiple of 3 Bytes.

In order to decode base64 simple implement a translates the alphabet A..Z a..z + / in reverse order. Skip all other chars even line breaks. Other chars may be used for error detection.

check out RFC1521 for more Info ..

Bye Miracle
Posted on 2002-03-13 04:44:39 by miracle
What exactly do you mean by 'a translates the alphabet A..Z a..z + / in reverse order' ??

Is it ok if I won't check lines breaks and keep encoding the data into the original binary file ?
Posted on 2002-03-13 06:22:05 by Cube
Hi,

it could look like this (without table)




xxxLoop:
; -- test for end of stream here ..

xor eax, eax
mov al, [edi + ecx]
cmp al, 02Bh ; +
je xxxSpec1
cmp al, 02Fh ; /
je xxxSpec2

cmp al, 30h ; 0
jl xxxIllegal
cmp al, 39h ; 9
jle xxxNumber

cmp al, 41h ; A
jl xxxIllegal
cmp al, 5Ah ; Z
jle xxxCapital

cmp al, 61h ; a
jl xxxIllegal
cmp al, 7Ah ; z
jle xxxLetter

xxxIllegal:
; -- if not al == 0Ah || al == 0Dh transmission error

xxxNumber: add eax, 4
putbits lpBuffer, eax
jmp xxxMore

xxxCapital: sub eax, 65
putbits lpBuffer, eax
jmp xxxMore

xxxLetter: sub eax, 71
putbits lpBuffer, eax
jmp xxxMore

xxxSpec1: putbits lpBuffer, 62
jmp xxxMore

xxxSpec2: putbits lpBuffer, 63
jmp xxxMore

xxxMore: inc ecx
jmp xxxLoop



Bye Miracle
Posted on 2002-03-13 06:57:48 by miracle
Hi,

or use a table like this to get the 6 bit value from 8 bit encoded stream. Use the encoded byte as an offset in table, but consider that yuo'll need an error detection ..



lpTable: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63
db 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0
db 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
db 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0
db 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
db 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0



Bye Miracle
Posted on 2002-03-13 07:12:59 by miracle
Some stuff i wrote about one year ago, if not longer... It does padding and all that stuff too...



.data
alphabet db "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

.code
base64encode PROC source:DWORD, destination:DWORD, sourcelen:DWORD
push edi
push esi
push ebx
mov esi, source
mov edi, destination
@@base64loop:
xor eax, eax
.IF sourcelen == 1
lodsb ;source ptr + 1
mov ecx, 2 ;bytes to output = 2
mov edx, 03D3Dh ;padding = 2 byte
dec sourcelen ;length - 1
.ELSEIF sourcelen == 2
lodsw ;source ptr + 2
mov ecx, 3 ;bytes to output = 3
mov edx, 03Dh ;padding = 1 byte
sub sourcelen, 2 ;length - 2
.ELSE
lodsd
mov ecx, 4 ;bytes to output = 4
xor edx, edx ;padding = 0 byte
dec esi ;source ptr + 3 (+4-1)
sub sourcelen, 3 ;length - 3
.ENDIF

xchg al,ah ; flip eax completely
rol eax, 16 ; can this be done faster
xchg al,ah ; ??

@@:
push eax
and eax, 0FC000000h ;get the last 6 high bits
rol eax, 6 ;rotate them into al
mov al, byte ptr [offset alphabet+eax] ;get encode character
stosb ;write to destination
pop eax
shl eax, 6 ;shift left 6 bits
dec ecx
jnz @B ;loop

cmp sourcelen, 0
jnz @@base64loop ;main loop

mov eax, edx ;add padding and null terminate
stosd ; " " " " "

pop ebx
pop esi
pop edi
ret
base64encode ENDP




.data
; ASCII-43 -> BASE64 mapping table
base64table db 62,0,0,0,63,52,53,54,55,56,57,58,59,60,61,0
db 0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13
db 14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0
db 0,0,26,27,28,29,30,31,32,33,34,35,36,37,38
db 39,40,41,42,43,44,45,46,47,48,49,50,51

.code
base64decode PROC source:DWORD, destination:DWORD
push ebx
push esi
push edi
mov esi, source
mov edi, destination
invoke lstrlen, source
shr eax, 2
mov ecx, eax
push ecx
@@outer_loop:
xor ebx, ebx
mov ecx, 4
lodsd
@@inner_loop:
push eax
and eax, 0FFh
sub al, 43
or bl, [offset base64table+eax]
shl ebx, 6
pop eax
shr eax, 8
dec ecx
jnz @@inner_loop
mov eax, ebx
rol ax, 8
rol eax, 16
rol ax, 8
stosd
dec edi
pop ecx
dec ecx
jnz @@outer_loop
pop edi
pop esi
pop ebx
ret
base64encode ENDP


Same as the one above but with error detection...



; ASCII -> BASE64 mapping table
base64table db 43 dup (255)
db 62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255
db 255,255,0,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13
db 14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255
db 255,255,26,27,28,29,30,31,32,33,34,35,36,37,38
db 39,40,41,42,43,44,45,46,47,48,49,50,51
db 132 dup (255)

base64decode PROC source:DWORD, destination:DWORD, sourcelen:DWORD
push esi
push edi
push ebx

mov esi, source ; esi <- source
mov edi, destination ; edi <- destination
mov ecx, sourcelen
shr ecx, 2
cld

;-------------[decoding part]---------------

@@outer_loop:
push ecx
mov ecx, 4
xor ebx, ebx
lodsd
@@inner_loop:
push eax
and eax, 0ffh
mov al, byte ptr [offset base64table+eax]
cmp al, 255
je @@invalid_char
shl ebx, 6
or bl, al
pop eax
shr eax, 8
dec ecx
jnz @@inner_loop
mov eax, ebx
shl eax, 8
xchg ah, al
ror eax, 16
xchg ah, al
stosd
dec edi
pop ecx
dec ecx
jnz @@outer_loop
xor eax, eax
jmp @@decode_done

;-------------------------------------------

@@invalid_char:
mov eax, -1
@@decode_done:
pop ebx
pop edi
pop esi
ret
base64decode ENDP
Posted on 2002-03-15 07:02:19 by Zynaps
High-speed decoding action BASE64.

; From Internet network library by Stepan Polovnikov
; SMTP/BASE64 decoder

tblB64 db "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

label tblDecode dword
Fi dd 256 dup (?)
Se dd 256 dup (?)
Th dd 256 dup (?)
Fo dd 256 dup (?)

; 22333333 11112222 00000011
BuildTableDecoder:
lea edi,
mov ebx,edi
mov ecx,4*256
mov eax,01000000h
rep stosd
mov ecx,64
xor edi,edi
@@lp: lodsb
lea edx,
mov ,edx
mov edx,edi
mov dh,dl
shr dl,4
shl dh,4
mov ,edx
mov edx,edi
mov dh,dl
shr dl,2
shl dh,6
shl edx,8
mov ,edx
mov edx,edi
shl edx,16
mov ,edx
inc edi
dec ecx
jne @@lp
ret

Decoder:
; Input:
; esi - source buffer
; eax - source length
; ecx - destination buffer
; Output:
; eax<>0 OR ZF=0 - invalid chars
lea edi,
shr eax,2
@@lp: xor ebp,ebp
mov edx, ; get 4 chars
add esi,4
mov ebx,3 ; decode fouth char
shld ebx,edx,8
add ebp,
shld ebx,edx,16 ; decode third char
and ebx,0FFh
add ebp,
movzx ebx,dh ; decode second char
add ebp,
and edx,0FFh
add ebp, ; decode first char
test ebp,0FF000000h ; check invalid chars
jne @@err
mov ,ebp
add ecx,3
dec eax
jne @@lp
@@err: ret
Posted on 2002-03-24 13:46:05 by Nexo
Hi Nexo,



Decoder:
; Input:
; esi - source buffer
; eax - source length
; ecx - destination buffer
; Output:
; eax<>0 OR ZF=0 - invalid chars

lea edi, [tblDecode]
;shr eax, 2
@@lp: ;
;xor ebp, ebp
mov edx, [esi] ; get 4 chars
add esi, 4
mov ebx, 3 ; decode fouth char
shld ebx, edx, 8
mov ebp, [edi+4*ebx]
shld ebx, edx,16 ; decode third char
and ebx, 0FFh
add ebp, [edi+4*(ebx+200h)]
movzx ebx, dh ; decode second char
add ebp, [edi+4*(ebx+100h)]
and edx, 0FFh
add ebp, [edi+4*edx] ; decode first char
;test ebp, 0FF000000h ; check invalid chars
js @@err ; just change in table 1 with 0FFh or other neg value
;jne @@err
mov [ecx], ebp ; slow ->writing in unaligned buffer !!!
add ecx, 3
;dec eax ;
sub eax, 4
jg @@lp
;jne @@lp
ret ; and you should return number of written bytes in eax
@@err:
;Begin error managing proc -> CRLF and "=" are NOT invalid chars
;Example: if you received e-mail the attachment may be
; BASE64 encoded and it has CRLF after every 76 or less encoded characters
; this proc must skip CRLF and return to the loop...
; If the last 1 or 2 characters from the buffer are "="
; this proc must decrement number of written bytes....
; More info for this example in RFC 2045 - Internet Message Bodies
.......
.......
ret
Posted on 2002-03-27 03:59:42 by buliaNaza
I am Sorry, but it is the old draft code from joint design. I have no direct concept about BASE64. This code was a starting point for usage BASE64, UUE, XXE decoding actions. I have made some editing the code, that it was not absolutely correct in this case. :(
For watching CRLF and '=' it is possible to use addition:
mov edx, ; get 4 chars
cmp dl, 0Dh
je CRLF
cmp dl, 0Ah
je CRLF
cmp dl, '='
je end_msg
...
CRLF:
inc esi
dec eax
jne @@ lp
ret

mov , ebp - here works buffering and the postponed writing. In result it works most more effectively, than decoding action of separate entry characters.
I only have tried to display a procedure of operation with tables at packing groups bit and no more.
Posted on 2002-03-27 10:53:53 by Nexo