1

My programm is supposed to encode binaries into base 64. Everything works fine until the EOF. I have troubles to add '=' at the end of my output string.

This should happen only when the last piece of bytes is being read. It should fill the empty space. Here is my code to dectect whenever I have to add one or two '='.

Read:
        mov eax,3               ; Specify sys_read call
        mov ebx,0               ; Specify File Descriptor 0: Standard Input
        mov ecx,Bytes           ; Pass offset of the buffer to read to
        mov edx,BYTESLEN        ; Pass number of bytes to read at one pass
        int 80h                 ; Call sys_read to fill the buffer
        mov ebp,eax             ; Save # of bytes read from file for later
        cmp rax,1               ; If EAX=0, sys_read reached EOF on stdin
        je MissingTwoByte   ; Jump If Equal (to 1, from compare)
        cmp rax,2               ; If EAX=0, sys_read reached EOF on stdin
        je MissingOneByte   ; Jump If Equal (to 2, from compare)
        cmp eax,0               ; If EAX=0, sys_read reached EOF on stdin
        je Done         ; Jump If Equal (to 0, from compare)

So in my :MissingOneByte and :MissingTwoByte function, I should add to Bytes my '=', right ? How can I achieve that ?

  • It's unclear what your problem is. Surely you are not looking for `mov [Bytes+1], '='` and such? – Jester Dec 12 '17 at 19:10
  • Nope, I don't really know how to explain, my english ain't that good. –  Dec 12 '17 at 19:23
  • Is this 32 or 64 bit? – Shift_Left Dec 12 '17 at 19:23
  • It is on Linux 64 bit ! –  Dec 12 '17 at 19:54
  • 1
    Your code is using 32 bit `int 0x80`, so you may (and very likely *will*) run into problems, if you will keep building it as 64b binary: [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730/4271923) (for example your binary will certainly NOT work in Windows10 linux "sub-system", the packaged Ubuntu is strictly 64b only, without support for `int 0x80`, while a proper 64b binary using console stdin/stdout would work ok) – Ped7g Dec 12 '17 at 22:53

1 Answers1

2

In my previous answer.. that code was supposed to eat 3 bytes always, padded by zeroes, and to fix/patch the result afterwards!

I.e. for single input byte 0x44 the Bytes needs to be set to 44 00 00 (the first 44 is set by sys_read, other two need to be cleared by code). You will get the wrong conversion result RAAA, and then you need to patch it to the correct RA==.

I.e.

SECTION .bss
BYTESLEN    equ     3           ; 3 bytes of real buffer are needed
Bytes:      resb    BYTESLEN + 5; real buffer +5 padding (total 8B)
B64output:  resb    4+4         ; 4 bytes are real output buffer
                                ; +4 bytes are padding (total 8B)

SECTION .text

        ;...
Read:
        mov     eax,3           ; Specify sys_read call
        xor     ebx,ebx         ; Specify File Descriptor 0: Standard Input
        mov     ecx,Bytes       ; Pass offset of the buffer to read to
        mov     edx,BYTESLEN    ; Pass number of bytes to read at one pass
        int     80h             ; Call sys_read to fill the buffer
        test    eax,eax
        jl      ReadingError    ; OS has problem, system "errno" is set
        mov     ebp,eax         ; Save # of bytes read from file for later
        jz      Done            ; 0 bytes read, no more input
        ; eax = 1, 2, 3
        mov     [ecx + eax],ebx ; clear padding bytes
            ; ^^ this is a bit nasty EBX reuse, works only for STDIN (0)
            ; for any file handle use fixed zero: mov word [ecx+eax],0
        call    ConvertBytesToB64Output     ; convert to Base64 output
        ; overwrite last two/one/none characters based on how many input
        ; bytes were read (B64output+3+1 = B64output+4 => beyond 4 chars)
        mov     word [B64output + ebp + 1], '=='
        ;TODO store B64output where you wish
        cmp     ebp,3
        je      Read            ; if 3 bytes were read, loop again
        ; 1 or 2 bytes will continue with "Done:"
Done:
        ; ...

ReadingError:
        ; ...

ConvertBytesToB64Output:
        ; ...
        ret

Written again to be short and simple, not caring about performance much.

The trick to make instructions simple is to have enough padding at end of buffers, so you don't need to worry about overwriting memory beyond buffers, then you can write two '==' after each output, and just position it at desired place (either overwriting two last characters, or one last character, or writing it completely outside of output, into the padding area).

Without that probably lot of if (length == 1/2/3) {...} else {...} would creep into code, to guard the memory writes, and overwrite only the output buffer and nothing more.

So make sure you understand what I did and how it works, and add enough padding to your own buffers.

Also... !disclaimer!: I actually don't know how many = should be at end of base64 output, and when... that's up to OP to study the base64 definition. I'm just showing how to fix wrong output of 3B->4B conversion, which takes shorter input padded by zeroes. Hmm, according to online BASE64 generator it actually works as my code... (input%3) => 0 has no =, 1 has two =, and 2 has single =.

Ped7g
  • 16,236
  • 3
  • 26
  • 63