Sunteți pe pagina 1din 6

MS-Windows DOS Stub Program

1 de 6

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

Sponsoring website: Emergency Boot CD

A Guide to DEBUG
The Microsoft Windows .EXE

Program
Copyright2004,2013 by Daniel B. Sedory
This page may be freely copied for PERSONAL use ONLY !
( It may NOT be used for ANY other purpose unless you have
first contacted and received permission from the author ! )
Why is the DOS Stub in Windows Programs?
All the Details of the DOS Stub Program
Debugging (stepping through) the DOS Stub

Why is there a DOS Stub Program


in a Windows Executable?
In the early days of Microsoft Windows, The Windows1.x, 2.x and 3.xx OS not
only existed in the same volumes as Microsoft DOS, but also ran on top of an
MS-DOS OS. It was not only possible, but very probable that a user might attempt
to run some of the Windows programs under DOS. Therefore, Microsoft
programmers made sure all Windows programs would have a simple 16-bit DOS
program placed at the front of each Windows executable that would alert the user if
they were attempting to run a Windows program under DOS. This is all the DOS
"Stub" program does.

All the Details of the DOS "Stub" Program


One of the simplest .EXE programs you can run under DEBUG is the so-called
DOS "Stub" found inside hundreds of Windows executables. The "Stub" program
itself has not changed in many years, and we'll examine it in detail in a
Step-by-Step DEBUG session below. There are some ...

26/08/2014 11:45

MS-Windows DOS Stub Program

2 de 6

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

If you open a copy of NOTEPAD.EXE inside a Hex editor (such as HxD), it will
appear similar to this:

( The beginning of NOTEPAD.EXE from Windows XP Pro SP-3; April 14, 2008, 4:00:00 AM, 69,120 bytes.)
Figure 1.

Note the first two bytes, "4d 5a" or their ASCII equivalent: "MZ". Whenever the
DOS EXEC function is called to examine a file (anytime you load an .EXE or .COM
program into DEBUG 2.0+ for example) and it finds "MZ" as the first two bytes, that
file will always be considered an .EXE executable! So, what happens if you enter:
debug notepad.exe at the prompt in a DOS-box? Well, the first bytes you'll see
when you do a dump command are:

You may ask: "Hey, I thought DEBUG always loaded files from the command-line at
offset 0100?" Well, if this were a .COM program, or any other kind of file, that did
not have "MZ" as its first two bytes, it would. But, in the case of .EXE files, that isn't
true. The EXEC function will examine an .EXE file's Header area, which among
other things, determines the location of its first instruction (CS:IP) and also that of
the Stack Pointer (SS:SP). In this case, the DOS header told EXEC to set the IP
register to zero and load its code at offset zero.
Before proceeding with DEBUG, we should mention Windows executables can be
very complex when compared to the .COM and even 16-bit .EXE programs you'd
26/08/2014 11:45

MS-Windows DOS Stub Program

3 de 6

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

normally study with DEBUG. When we load NOTEPAD.EXE into DEBUG, its length
is given as 68,608 bytes (BX:CX = 10C00 hex). We already told you that its actual
size is 69,120 bytes. From Figure 1 above, which shows the actual beginning of
the program, we see the first 64 bytes (40h) weren't loaded into DEBUG; these are
NOTEPAD's DOS Header. But, 68,608 plus 64 equals only 68,672 bytes,
appearing to leave 448 bytes unaccounted for. The reason is because the DOS
Header contains different information about this file than its Windows PE
Header! We warned you this file's structure was complex. This particular program's
PE (Portable Executable) Header according to a particular 'file scanner' we used,
says the file has the following pieces:
Stub: 224 bytes, Header: 800 bytes, Image: 68,096 bytes, Overlay: 0. Those add
up to our file size of 69,120 bytes. Yet the DOS Header information shows only a
Header of 28 bytes (obviously not the whole DOS Header area!), Relocations: 0,
Empty: 36 bytes, Image: 1104 bytes, Overlay: 67,952; which adds up to the same
total. At some time in the future, we might create a few pages dealing with all this
header information and how to interpret it.
Offset

000000
000010
000020
000030
000040
000050
000060
000070
000080
000090
0000A0
0000B0
0000C0
0000D0
0000E0
0000F0

4D
B8
00
00
0E
69
74
6D
EC
6B
6B
6B
6B
00
50
00

5A
00
00
00
1F
73
20
6F
85
EB
EB
EB
EB
00
45
00

90
00
00
00
BA
20
62
64
5B
3A
68
6B
6F
00
00
00

00
00
00
00
0E
70
65
65
A1
F2
F2
F2
F2
00
00
00

03
00
00
00
00
72
20
2E
A8
A9
BB
A9
A9
00
4C
E0

00
00
00
00
B4
6F
72
0D
E4
E4
E4
E4
E4
00
01
00

00
00
00
00
09
67
75
0D
35
35
35
35
35
00
03
0F

00
00
00
00
CD
72
6E
0A
F2
F2
F2
F2
F2
00
00
01

04
40
00
00
21
61
20
24
A8
6B
A8
6B
52
00
87
0B

00
00
00
00
B8
6D
69
00
E4
EB
E4
EB
69
00
52
01

00
00
00
00
01
20
6E
00
35
55
34
6A
63
00
02
07

00
00
00
00
4C
63
20
00
F2
F2
F2
F2
68
00
48
0A

FF
00
00
E0
CD
61
44
00
A8
A9
63
BF
A8
00
00
00

FF
00
00
00
21
6E
4F
00
E4
E4
E4
E4
E4
00
00
78

00
00
00
00
54
6E
53
00
35
35
35
35
35
00
00
00

00
00
00
00
68
6F
20
00
F2
F2
F2
F2
F2
00
00
00

MZ..............
........@.......
................
................
........!..L.!Th
is program canno
t be run in DOS
mode....$.......
..[...5...5...5.
k.:...5.k.U...5.
k.h...5...4.c.5.
k.k...5.k.j...5.
k.o...5.Rich..5.
................
PE..L....R.H....
.............x..

( Beginning of NOTEPAD.EXE; Windows XP Pro SP-3; April 14, 2008, 4:00:00 AM, 69,120 bytes.)
Figure 3.

Stepping Through a DOS Stub with DEBUG


The following illustrations show exactly what happens when you use DEBUG to
step through almost any Windows (not just NOTEPAD) program using the following
DEBUG commands (Note: The Segment values on your computer will most likely
vary from those shown here):
C:\WINDOWS>debug notepad.exe
-r
First we enter the R command, to bring up the Registers display!
AX=0000

BX=0000

CX=C510

DX=0000

SP=00B8

BP=0000

SI=0000

DI=0000

26/08/2014 11:45

MS-Windows DOS Stub Program

4 de 6

DS=0B5C ES=0B5C
0B6C:0000 0E

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

SS=0B6C CS=0B6C
PUSH
CS

IP=0000

NV UP EI PL NZ NA PO NC

Note the CX Register above. This tells us the executable portion of NOTEPAD has
a length of C510h (or 50,448) bytes; at least that's how EXEC interpreted the DOS
header. But this value cannot be trusted for a complete picture of Windows
executables. The Data Segment (DS Register) is 0B5C, Code Segment (CS) is
0B6C and the Instruction Pointer (IP) is at 0000. Each time an instruction is
executed, the IP value will change. This first instruction will push the value of the
CS Register onto the Stack. After entering the Trace (-t) command, you should
see the following:
AX=0000 BX=0000
DS=0B5C ES=0B5C
0B6C:0001 1F

CX=C510 DX=0000
SS=0B6C CS=0B6C
POP
DS

SP=00B6
IP=0001

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

Before continuing, let's take a quick look at the Stack. You can see above that the
Stack Pointer (SP) changed from 00B8 to 00B6. Stacks always fill-up (push) and
get depleted (pop) in much the same manner as a spring-loaded tray rack at a
cafeteria. Once a memory location has been assigned to the first byte in a Stack,
every byte added to the Stack will subtract one from the Stack Pointer (SP). In this
case, a Word (of two bytes) was added to our Stack. Since the Stack Segment
(SS) is set to 0B6C, but our Data Segment is still at 0B5C, we'll do a Dump of
b6c:00b6 to b8 here:
-d b6c:00b6 b8
0B6C:00B0

6C 0B-00

l..

Note that values which contain more than one byte, such as this Word 0B6Ch, are
always stored in Memory with the Least Significant Byte first! Let's carry out
another Trace:
AX=0000 BX=0000
DS=0B6C ES=0B5C
0B6C:0002 BA0E00

CX=C510 DX=0000 SP=00B8


SS=0B6C CS=0B6C IP=0002
MOV
DX,000E

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

The POP instruction moved 0B6C from the Stack to the DS Register, and changed
the SP Register back to 00B8. And now that the Data Segment has been changed
to the same value as the Code Segment, we can do a Dump of Offset 000Eh (and
following) to see why the program wants to load that value into the DX (Data)
Register. Enter the command "d 0e 38" and you should see:
-d 0e 38
0B6C:0000
0B6C:0010
0B6C:0020
0B6C:0030

54 68
69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F
74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20
6D 6F 64 65 2E 0D 0D 0A-24

Th
is program canno
t be run in DOS
mode....$

We already knew that the string data would end with a "$" sign, so went ahead and

26/08/2014 11:45

MS-Windows DOS Stub Program

5 de 6

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

used offset 38h as the last location for the Dump command. These are the ASCII
bytes and the characters they represent (shown on the right-side of the display).
Although many non-displayable bytes are shown as 'dots' in the ASCII part of
DEBUG's Dump display, a "2Eh" byte (shown in light blue above) is the real ASCII
value for a period (punctuation character). The yellow 'dots' show the
non-displayable characters, 0Dh and 0Ah, which are a Line Feed and Carriage
Return, repectively. We'll comment on the 24h byte below. Yet another Trace (-t)
command gives us:
AX=0000 BX=0000
DS=0B6C ES=0B5C
0B6C:0005 B409

CX=C510 DX=000E SP=00B8


SS=0B6C CS=0B6C IP=0005
MOV
AH,09

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

-t

Before you carry out the next instruction, you need some information: INT 21h
executes DOS Interrupts; in this case, Function 09h (because AH=09). You should
never use the Trace command on Interrupts! (Unless you really do want to attempt
stepping through all of the MS-DOS code that comprises one.) Basically, Function
09 of INT 21, will print out a string of characters (at an offset pointed to by the
DS:DX registers), until it encounters a 24h ("$") byte. After entering the Proceed
command, you should see the string displayed on your screen as follows:
AX=0900 BX=0000 CX=C510 DX=000E SP=00B8
DS=0B6C ES=0B5C SS=0B6C CS=0B6C IP=0007
INT
21
0B6C:0007 CD21
-p
This program cannot be run in DOS mode.

AX=0924 BX=0000
DS=0B6C ES=0B5C
0B6C:0009 B8014C

CX=C510 DX=000E SP=00B8


SS=0B6C CS=0B6C IP=0009
MOV
AX,4C01

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

This is yet another DOS Interrupt (INT 21h) in the making... Function 4Ch (AH=4C)
is the standard "Exit" (Terminate) code with Return (AL=return value; 01 in this
case). By now, you should see that it's very important to obtain a list of all the
Interrupts! Look for the link to Ralf Brown's (Free) Interrupt Listing on our Assembly
page.
-t
AX=4C01 BX=0000
DS=0B6C ES=0B5C
0B6C:000C CD21
-p

CX=C510 DX=000E
SS=0B6C CS=0B6C
INT
21

SP=00B8
IP=000C

BP=0000 SI=0000 DI=0000


NV UP EI PL NZ NA PO NC

Program terminated normally


-q

As you can see, the "Program terminated normally" and we Quit the DEBUG
session.
There are variations of the "DOS Stub" program in existence. Basically they depend
upon which software company made the compiler that was used to create a

26/08/2014 11:45

MS-Windows DOS Stub Program

6 de 6

http://thestarman.pcministry.com/asm/debug/DOSstub.htm

Windows program. For example, the string displayed by a program which used
Borland's tlink32 compiler, should state: "This program must be run under
Win32." when run under a real 16-bit DOS or in DEBUG.

Last Update: October 12, 2004. (12.10.2004)

A Guide to DEBUG
The Starman's Realm Assembly Page

26/08/2014 11:45

S-ar putea să vă placă și