Rebooting With JMP Instruction
While learning about x86 microprocessors, I realised that it is
possible to reboot a computer running MS-DOS or Windows 98 by
jumping to the memory address FFFF:0000. Here is an
example DEBUG.EXE
session from MS-DOS 6.22:
C:\>DEBUG G =FFFF:0000
In the above example, we start the DOS debugger and then enter
the G
(go) command to execute the program at FFFF:0000.
Just doing this simple operation should reboot the system
immediately.
When the computer boots, the x86 microprocessor starts in real mode and executes the instruction at FFFF:0000. This is an address in the BIOS ROM that contains a far jump instruction to go to another address, typically F000:E05B.
C:\>DEBUG -U FFFF:0000 4 FFFF:0000 EA5BE000F0 JMP F000:E05B
The address F000:E05B contains the BIOS start-up program which performs a power-on self-test (POST), initialises the peripheral devices, loads the boot sector code, and executes it. These operations complete the booting sequence.
The important point worth noting here is that the very first
instruction the microprocessor executes after booting is the
instruction at FFFF:0000. We can use this fact to create a tiny
executable program that can be used to reboot the computer. Of
course, we can always perform a soft reboot using the key
sequence ctrl+alt+del. However,
just for fun, let us create a program to reboot the computer with
a JMP FFFF:0000
instruction.
Reboot Program
Here is a complete DEBUG.EXE
session that shows how we
could write a simple reboot program:
C:\>DEBUG -A 1165:0100 JMP FFFF:0000 1165:0105 -N REBOOT.COM -R CX CX 0000 :5 -W Writing 00005 bytes -Q C:\>
Note that the N
(name) command specifies the name of
the file where we write the binary machine code to. Also, note that
the W
(write) command expects the registers BX and CX
to contain the number of bytes to be written to the file. When the
DOS debugger starts, it already initialises BX to 0 automatically,
so we only set the register CX to 5 with the R CX
command above.
Now we can execute this 5-byte program like this:
C:>REBOOT
Debugger Scripting
In the previous section, we saw how we can start
DEBUG.EXE
and type the debugger commands and the
assembly language instruction to jump to FFFF:0000. We can also keep
these debugger inputs in a separate text file and feed that to the
debugger. Here is how the content of such a text file would look:
A
JMP FFFF:0000
N REBOOT.COM
R CX
5
W
Q
If the above input is saved in a file, say, REBOOT.TXT
,
then we can run the DOS command DEBUG < REBOOT.TXT
to assemble the program and create the binary executable file. The
following DOS session example shows how this command behaves:
C:\>DEBUG < REBOOT.TXT -A 1165:0100 JMP FFFF:0000 1165:0105 -N REBOOT.COM -R CX CX 0000 :5 -W Writing 00005 bytes -Q C:>
Disassembly
Here is a quick demonstration of how we can disassemble the executable code:
C:\>DEBUG REBOOT.COM -U 100 104 117C:0100 EA0000FFFF JMP FFFF:0000
While we did not really need to disassemble this tiny program, the
above example shows how we can use the debugger
command U
(unassemble) to translate machine code to
assembly language mnemonics.