231 lines
12 KiB
Plaintext
231 lines
12 KiB
Plaintext
;*************************************************************************************
|
|
; MODULE: DECODE64.ASM DATE: JANUARY 27,1997
|
|
; AUTHOR: SEAN M. KESSLER
|
|
; TARGET: 32 BIT FLAT MODEL
|
|
; FUNCTION : BASE64 DECODER
|
|
;*************************************************************************************
|
|
.386
|
|
.MODEL FLAT
|
|
INCLUDE devioctl.inc
|
|
INCLUDE string.inc
|
|
INCLUDE openfile.inc
|
|
.DATA
|
|
inputFile FileInfo <>
|
|
outputFile FileInfo <>
|
|
lineData DB 400h DUP(0)
|
|
szDefaultOutputPathFileName DB 'IMAGE.JPG',00h
|
|
szOutputPathFileName DB 0FFh DUP(0)
|
|
szFileNameLiteral DB 'filename=',00h
|
|
szOutBytes DB 04h DUP(0)
|
|
szInputPathFileName DD ?
|
|
szBase64ID DB '/9j/',00h
|
|
szExtension DB '.JPG',00H
|
|
szBase64Vector DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',00h
|
|
szBase64End DB '---',00h
|
|
num DD ?
|
|
lineLength DD ?
|
|
itemIndex DD ?
|
|
itemCount DD ?
|
|
numIndex DD ?
|
|
valueItem DD ?
|
|
.CODE
|
|
_decodeBase64 proc near ; WORD decodeBase64(const char *szPathFileName)
|
|
push ebp ; save stack frame
|
|
mov ebp,esp ; create new frame
|
|
push esi ; save source index register
|
|
push edi ; save destination index register
|
|
mov itemCount,0000h ; initialize decoded counter to zero
|
|
push dword ptr[ebp+8] ; save pathFileName
|
|
pop szInputPathFileName ; restore into inputPathFileName
|
|
cmp szInputPathFileName,0000h ; is the file na null
|
|
je @@error ; if so then we've got an error
|
|
FOPEN szInputPathFileName,inputFile,GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL
|
|
cmp inputFile.FileInfo@@mhFileHandle,INVALID_HANDLE ; do we have a valid handle ?
|
|
je @@error ; if the handle is invalid then we've got an error
|
|
call _outputName ; get output file name
|
|
@@search: ; search sync address
|
|
FGETS inputFile,lineData ; get input line
|
|
cmp eax,0000h ; did we read anything
|
|
je @@end ; if not we're done
|
|
STRSTR lineData,szFileNameLiteral ; look for "filename=" literal
|
|
cmp eax,0000h ; did we find it
|
|
jne @@nameFile ; if so then extract the filename
|
|
STRNCMP szBase64ID,lineData ; compare line to base64 identifier
|
|
cmp eax,0001h ; if we've got it then we start decoding
|
|
je @@beginDecode ; jump to decode handler
|
|
jmp @@search ; keep going
|
|
@@nameFile: ; nameFile sync address
|
|
push eax ; save address of filename literal
|
|
push offset szOutputPathFileName ; save address of filename buffer
|
|
call _nameFile ; extract the file name
|
|
add esp,08h ; reset stack frame
|
|
jmp @@search ; keep going
|
|
@@beginDecode: ; begin decode sync address
|
|
mov esi,offset szOutputPathFileName
|
|
FOPEN esi,outputFile,GENERIC_WRITE,FILE_SHARE_READ,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL
|
|
; FOPEN szOutputPathFileName,outputFile,GENERIC_WRITE,FILE_SHARE_READ,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL
|
|
@@continueDecode: ; continue decode sync address
|
|
STRLEN lineData ; get length of lineData
|
|
dec eax ; decrement line length
|
|
mov lineLength,eax ; move line length into lineLength
|
|
mov itemIndex,0000h ; set itemIndex to zero
|
|
@@itemLoop: ; itemLoop sync address
|
|
mov valueItem,0000h ; set valueItem to zero
|
|
mov esi,offset lineData ; move ptr lineData to esi register
|
|
add esi,itemIndex ; add itemIndex to address
|
|
cmp byte ptr[esi+02h],'=' ; is pChar[2] equal to '='?
|
|
je @@assignOne ; if so then num=1
|
|
cmp byte ptr[esi+03h],'=' ; else if pChar[3]='='
|
|
je @@assignTwo ; then num=2
|
|
mov num,0003h ; otherwise num=3
|
|
jmp @@assignContinue ; continue
|
|
@@assignOne: ; assignment sync address
|
|
mov num,0001h ; assign 1 to num
|
|
jmp @@assignContinue ; continue
|
|
@@assignTwo: ; assignment sync address
|
|
mov num,0002h ; assign two to num
|
|
jmp @@assignContinue ; continue
|
|
@@assignContinue: ; end assignment sync address
|
|
mov numIndex,0000h ; set numIndex to zero
|
|
@@numLoop: ; numIndex loop sync address
|
|
xor eax,eax ; clear out eax
|
|
mov edi,numIndex ; move numIndex into destination index
|
|
mov al,byte ptr[esi+edi] ; get the byte at pChar[numIndex]
|
|
STRCHR szBase64Vector,eax ; ::strchar(szBase64Vector,pChar[numIndex])
|
|
cmp eax,0000h ; did we find the token
|
|
je @@end ; if not then we've got an error
|
|
mov edi,eax ; move address of found token to edi (pTok)
|
|
sub edi,offset szBase64Vector ; perform (pTok-szBase64Vector) result to edi
|
|
mov eax,0003h ; move 3 into eax
|
|
sub eax,numIndex ; perform (3-numIndex) result to eax
|
|
mov edx,0006h ; move 6 into edx
|
|
imul eax,edx ; perform (3-numIndex)*6 result to eax
|
|
mov cl,al ; move shift value into cl register
|
|
shl edi,cl ; perform (pTok-smszVec)<<((3-numIndex)*6) result to edi
|
|
add valueItem,edi ; valueItem+=(pTok-smszVec)<<((3-numIndex)*6)
|
|
inc numIndex ; increment numIndex
|
|
mov eax,numIndex ; move numIndex into eax register
|
|
cmp eax,num ; compare numIndex to num
|
|
jle @@numLoop ; loop through <= operation
|
|
mov numIndex,0002h ; set numIndex to 2
|
|
@@nextNumLoop: ; next numLoop sync address
|
|
mov esi,offset szOutBytes ; move szOutBytes address into esi
|
|
mov edi,numIndex ; move numIndex into edi
|
|
mov eax,valueItem ; move valueItem into eax register
|
|
and eax,000000FFh ; apply bit mask
|
|
mov byte ptr[esi+edi],al ; set byte in szOutBytes
|
|
shr valueItem,08h ; shift valueItem right 8 bytes
|
|
dec numIndex ; decrement numIndex
|
|
cmp numIndex,0000h ; compare numIndex to zero
|
|
jge @@nextNumLoop ; if >=0 keep going
|
|
mov esi,offset szOutBytes ; move szOutBytes to esi
|
|
xor edi,edi ; clear edi
|
|
@@writeLoop: ; writeLoop sync address
|
|
FWRITE outputFile,byte ptr[esi+edi] ; write out the byte
|
|
inc edi ; increment edi
|
|
cmp edi,num ; compare edi to num
|
|
jl @@writeLoop ; if it's less then keep going
|
|
add itemIndex,0004h ; increment itemIndex by four
|
|
mov eax,itemIndex ; move itemIndex to eax
|
|
cmp eax,lineLength ; compare itemIndex to lineLength
|
|
jl @@itemLoop ; if it's less that keep going
|
|
FGETS inputFile,lineData ; get another line
|
|
cmp eax,0000h ; did we get a line?
|
|
je @@end ; if not then we're done
|
|
STRNCMP lineData,szBase64End ; look for trailer signature
|
|
cmp eax,0001h ; if we found it then another image may follow
|
|
je @@prepNewImage ; flush and close current output file
|
|
jmp @@continueDecode ; otherwise keep going
|
|
@@prepNewImage: ; prepNewImage sync address
|
|
inc itemCount ; increment decoded counter
|
|
FFLUSH outputFile ; flush output file
|
|
CLOSEHANDLE outputFile.FileInfo@@mhFileHandle ; close output file
|
|
mov outputFile.FileInfo@@mhFileHandle,INVALID_HANDLE ; invalidate the handle
|
|
jmp @@search ; try to decode another image
|
|
@@end: ; end sync address
|
|
cmp outputFile.FileInfo@@mhFileHandle,INVALID_HANDLE ; is this a valid handle
|
|
je @@closePrimary ; is handle is invalid, just close the input file
|
|
FFLUSH outputFile ; flush the output file
|
|
CLOSEHANDLE outputFile.FileInfo@@mhFileHandle ; close output file
|
|
@@closePrimary: ; close primary sync address
|
|
CLOSEHANDLE inputFile.FileInfo@@mhFileHandle ; close input file
|
|
@@error: ; error sync address
|
|
mov eax,itemCount ; move decoded count to eax register
|
|
pop edi ; restore destination index register
|
|
pop esi ; restore source index register
|
|
pop ebp ; restore prior stack frame
|
|
retn ; return near to caller
|
|
_decodeBase64 endp
|
|
_nameFile proc near
|
|
push ebp ; save stack frame
|
|
mov ebp,esp ; create new frame
|
|
push esi ; save source index register
|
|
push edi ; save destination index register
|
|
mov edi,[ebp+8] ; move dest string to destination index register
|
|
mov esi,[ebp+0Ch] ; move source string to source index register
|
|
@@NAMEFILEquoteLoop: ; first quote loop control
|
|
mov al,byte ptr[esi] ; move byte into al
|
|
cmp al,00h ; is it null?
|
|
je @@NAMEFILEerror ; if it's null then we've got an error
|
|
cmp al,'"' ; is it the first quote ?
|
|
je @@NAMEFILEreadFile ; if so then get the filename
|
|
inc esi ; increment along esi
|
|
jmp @@NAMEFILEquoteLoop ; keep going
|
|
@@NAMEFILEreadFile: ; read file name sync address
|
|
inc esi ; skip past the first quote
|
|
mov al,byte ptr[esi] ; read from file name
|
|
cmp al,'"' ; is the byte the closing quote?
|
|
je @@NAMEFILEreadEnd ; if so then we're done
|
|
cmp al,00h ; is the byte a null byte?
|
|
je @@NAMEFILEreadEnd ; if so then we're done
|
|
mov byte ptr[edi],al ; store the byte in destination
|
|
inc edi ; increment along destination
|
|
jmp @@NAMEFILEreadFile ; keep going
|
|
@@NAMEFILEreadEnd: ; read end sync address
|
|
mov byte ptr[edi],00h ; null terminate the string
|
|
mov eax,0001h ; set return code
|
|
jmp @@NAMEFILEend ; we're done
|
|
@@NAMEFILEerror: ; error sync address
|
|
xor eax,eax ; set error return
|
|
@@NAMEFILEend: ; end proc sync address
|
|
pop edi ; restore destination index register
|
|
pop esi ; restore source index register
|
|
pop ebp ; restore prior stack frame
|
|
retn ; return near to caller
|
|
_nameFile endp
|
|
_outputName proc near
|
|
push ebp ; save stack frame
|
|
mov ebp,esp ; create new frame
|
|
push esi ; save source index register
|
|
push edi ; save destination index register
|
|
mov esi,szInputPathFileName ; set esi to input name address
|
|
mov edi,offset szOutputPathFileName ; set edi to output name address
|
|
xor ecx,ecx ; clear ecx for indexing
|
|
@@copyLoop: ; copy loop sync address
|
|
mov al,[esi+ecx] ; get byte from source to al
|
|
cmp al,00h ; is this a null byte
|
|
je @@copyDone ; if so then we're done copying
|
|
mov byte ptr[edi],al ; store the byte into destination
|
|
inc edi ; increment destination
|
|
inc ecx ; increment source index
|
|
jmp @@copyLoop ; loop through the string
|
|
@@copyDone: ; copy done sync address
|
|
mov byte ptr[edi],00h ; set null terminator
|
|
STRCHR szOutputPathFileName,'.' ; look for extension marker
|
|
cmp eax,0000h ; did we find it?
|
|
je @@nameError ; if not then we set output name to default
|
|
mov byte ptr[eax],0000h ; otherwise terminate the string
|
|
STRCAT szOutputPathFileName,szExtension ; cat the string with ".jpg"
|
|
jmp @@outputDone ; we're done
|
|
@@nameError: ; nameError sync address
|
|
STRLEN szDefaultOutputPathFileName ; get the length of the default file name
|
|
MEMCPY szOutputPathFileName,szDefaultOutputPathFileName,eax ; set output file name to default
|
|
@@outputDone: ; outputDone sync address
|
|
pop edi ; restore destination index
|
|
pop esi ; restore source index
|
|
pop ebp ; restore previous stack frame
|
|
retn ; return near to caller
|
|
_outputName endp
|
|
public _decodeBase64
|
|
END
|