Back to the roots: we drive a computer directly from the MBR

Once again, I deployed a Linux-image to a USB-drive (for some reason it turned out to be Manjaro, but this is a completely different story), and strange thoughts crept into my head: the BIOS saw a USB flash drive, and then what? Well, yes, there is an MBR, most likely GRUB, and ... And once in MBR someone else's custom code was popped up, it means that a simple person from Adygea can program something on a "big" computer, but outside the operating system.


And since it’s too bold to do such things in high-level languages, and we don’t know assemblers, we’ll spar directly on the opcodes for 8086.



Introduction


Plan:


  1. Withdraw #
  2. Withdraw Hello, Habrauser!
  3. Display input characters (you can already entertain children).

Disclaimers and Disclaimers


In order not to bother with the roar of the flopper, we will train cats QEMU. , , dd x86- . .


MBR, - (?) (?) β€” , Enter. .


β€” , ( !) - . ( .) ! .


MBR


:


  • , Bootstrap Area .
  • , ( ) 0x7c00 ( Compaq).
  • , , ( , --). : 640KB, . ( , .)


, β€” , .


, , , , (sic!) . , ( - ), , .


, - «» 80- «-» 90-, : «» «». «», Lode Runner, «».


«» +


!



-, , , , , β€” errata.


, , , .


:


  • , MOV, INT, ADD, DIV β€” , , , . , , , .
  • , , , : imm8, r16, r/m32, rel8. , , (, ) , , DIV BL F6 F3 (DIV r/m8, , , β€” .) F6 β€” DIV, NEG, ( opcode extension β€” .)


, , dd, , , , , β€” , , -. -, … , POSIX , !


➜  $ echo "48 65 6c 6c 6f 2c 20 48 61 62 72 21" | xxd -r -p 
Hello, Habr!%    

:


➜  $ echo -e "# Comment\n48 65 6c 6c 6f 2c 20  # First line\n48 61 62 72 21        # Last line" | sed 's/#.*$//g' | xxd -r -p
Hello, Habr!%  

( sed-, xxd , hex-dump. ?)


, , .


, sh-
#!/bin/sh

IN="${1:-/dev/stdin}"
OUT="${2:-/dev/stdout}"

> $OUT

while read line
do
    echo "$line" | sed 's/#.*$//' | xxd -r -p >> $OUT
done < $IN


: LF (aka \n), . , , , , - , β€” .

β€” , !


➜  $ ./build loader.mbr loader.img && stat -f %z loader.img
512

512 β€” , . , .




, bin- 512B, . Β« dd /dev/zero, !Β» β€” . , c ( , ipython) !


,
# 0x0000:0x007F (0-127)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0080:0x00FF (128-255)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0100:0x017F (256-383)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0180:0x0200 (384-512)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00


, , , QEMU, Exception'.



, , ( ), MBR.


,
...

# 0x0180:0x0200 (384-445)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00

# Partition 1     0x01BE:0x01CD (446-461) 
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 2     0x01CE:0x01DD (462-477)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 3     0x01DE:0x01ED (478-493)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 4     0x01EE:0x01FD (494-509)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# MBR Signature   0x1FE:0x1FF (510-511)
00 00


, :


# MBR Signature   0x1FE:0x1FF (510-511)
55 AA


:


$ qemu-system-i386 -nic none loader.img

-nic none , PXE, β€” .


, BIOS , ! , !



, !


, . :


# 0x0000:0x007F (0-127)
B4 0E                      # Set a console output mode
B0 23                      # Set an octothorp sign
CD 10                      # Call a print function

00 00
00 00 00 00 00 00 00 00


( , 512).


, QEMU !



, , , , :


  • B4 0E β€” AH 0E ( mov ah, 0e), BIOS ( ), , .
  • B0 23 β€” : AL #. ? «»? β€” ASCII- man ascii!
  • CD 10 β€” : BIOS-, . , AL AH, , : .

, AL :


  • $ (B0 24)
  • % (B0 25)
  • Γ‘ (B0 A0, )


, , . .


- . β€” printf('Hell of word') .


, , :


,
# 0x0000:0x007F (0-127)
B4 0E    # Set a console output mode

B0 0A    # LF
CD 10

B0 48    # H
CD 10    # print 

B0 65    # e
CD 10

B0 6C    # l
CD 10

B0 6C
CD 10

B0 6F    # o
CD 10

B0 2C    # ,
CD 10

B0 20    # SPC
CD 10

B0 48    # H
CD 10

B0 61    # a
CD 10

B0 62    # b
CD 10

B0 72    # r
CD 10

B0 61    # a
CD 10

B0 75    # u
CD 10

B0 73    # s
CD 10

B0 65    # e
CD 10

B0 72    # r
CD 10

B0 21    # !
CD 10

00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

,


, , :



:


  • ,
  • , ,
  • , BIOS' β€” - , Booting from Hard Disk....

, :


# 0x0000:0x007F (0-127)
B8 00 06          # Clear screen
CD 10

B4 0E             # Set a console output mode
BE 80 7C          # Place 0x0080 + 0x7c00 = 0x7c80 into SI
AC                # Load a byte at address SI into AL, increment SI
3C 00             # AL == 00?
74 06             # If yes, go to +6 bytes (to zeroes)
CD 10             # Print a char in AL
EB F7             # Go to -7 bytes (to AC opcode)

00 00 00 00 00
00 00 00 00 00 00 00 00

...

# 0x0080:0x00FF (128-255)
48 65 6C 6C 6F 2C 20 48   # Hello, H
61 62 72 61 75 73 65 72   # abrauser
21                        # !

00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

:


  • : , 0x7c00, . ? data- ( ), ( !), SI β€” .
  • SI AC ( LODS). , SI AL, SI! , !
  • . , . , , ?
  • AL, , β€” ( , 6 ), 00 .
  • AL - , BIOS-...
  • … 7 β€” LODS!

, . , .


, - . : BIOS- . … . β€” ( , β€” ).


, . printer.mbr typewriter.mbr.

, :


# 0x0000:0x007F (0-127)
B4 07   # Clear screen
B0 00   #
CD 10   #

B4 00   # Set Get keystroke mode
CD 16   # Read a char -> AL

3C 0D   # AL == 0D? (CR, Return pressed)
75 06   # If no, go to +6 bytes

B4 0E   # Print CR
CD 10   #
B0 0A   # Then print NL

B4 0E   # Print a char
CD 10   # 

EB EC   # Go to -20 bytes

1


:


  • ( QEMU) .
  • AH = 00h 16h, , , AL.
  • , : OD (aka CR aka ), Return/Enter, , ( -), .
  • CR CR, LF, , Enter.
  • AL OD, , .
  • : -- , ! 20 .

, :



, :


  • , «» ,
  • , ,
  • «»: Backspace , .

. emacs- .



, .



, - :



, . , :


# 0x0000:0x007F (0-127)
B8 12 00          # Set VGA mode 640x480x16
CD 10

B4 0E             # Set a console output mode
B3 00             # Set FG color to black
FE C3             # Color++

BE 80 7C          # Place 0x0080 + 0x7c00 = 0x7c80 into SI
AC                # Load a byte at address SI into AL, increment SI
3C 00             # AL == 00?
74 F6             # If yes, go to -10 bytes (to FE C3)

CD 10             # Print a char in AL
EB F7             # Go to -9 bytes (to AC)

00
00 00 00 00 00 00 00 00

...

# 0x0080:0x00FF (128-255)
48 65 6C 6C 6F 2C 20 48   # Hello, H
61 62 72 61 68 61 62 72   # abrahabr
21 20                     # ! 

00 00 00 00 00 00
00 00 00 00 00 00 00 00

color-printer.mbr


  • (? ? BIOS?) , ,
  • BL (. , .)
  • FE BL
  • : , , , .

.



, .






, :
β€” !
β€” .
, Sublime Text :
β€” --, ! !
.


- .




UPD: eisaev, Andrew_Pinkerton, MrSmith33, Anthony1025 , , .


All Articles