assemblyx86reverse-engineeringbootloadermbr

Interpreting the boot sector assembly code


I am going through os-dev by Nick Blundell. There he has taken through the hex data inside a bin file after compiling the boot sector assembly code using NASM. Is there a way to interpret all the 512 bytes manually, just by looking at the code. Say, for example, following is the code

mov ah,0x0E

;First attempt
mov al,the_secret
int 10h

;Second attempt
mov al,[the_secret]
int 10h

;Third attempt
mov bx,the_secret
add bx,0x7c00
mov al,[bx]
int 10h

;Fourth attempt
mov al,[0x7c1e]
int 0x10

jmp $

the_secret: db "X"

times 510 - ($ - $$) db 0

dw 0xaa55

The above code generates a 512 byte bin file after compiling. Is it possible to determine all the 512 bytes just by looking at the code? I think it should be possible, Otherwise he wouldn't know that the_secret is present at 0x7c1e. If it's possible, please direct me to relevant articles explaining this part. Thank you


Solution

  • Have you tried using ndisasm foo.bin? You'll find mov bx, 0x1d with the address of the secret, and another mov al,[0x7c1e]. Then you'd look at the disassembly at that address (the 0x7c00 load address), and see the byte. Also, it's the first byte after the infinite-loop jump, which makes it also in a pretty obvious place.

    $ nasm foo.asm
    $ ndisasm foo
    00000000  B40E              mov ah,0xe
    00000002  B01D              mov al,0x1d        ; use the address as an ASCII code...
    00000004  CD10              int 0x10
    00000006  A01D00            mov al,[0x1d]
    00000009  CD10              int 0x10
    0000000B  BB1D00            mov bx,0x1d
    0000000E  81C3007C          add bx,0x7c00
    00000012  8A07              mov al,[bx]
    00000014  CD10              int 0x10
    00000016  A01E7C            mov al,[0x7c1e]
    00000019  CD10              int 0x10
    0000001B  EBFE              jmp short 0x1b
    0000001D  58                pop ax               ;;; This 0x58 is actually the ASCII code
    0000001E  0000              add [bx+si],al
    00000020  0000              add [bx+si],al
    ...
    000001FE  55                push bp
    000001FF  AA                stosb
    

    It looks like this bootloader assumes that DS = 0 when it starts up, but doesn't bother to actually set DS itself to match the implicit default org 0. The earlier mov al,[0x1d] will work for the other perhaps-likely case of DS=0x07C0. (It's common for bootloaders to start with CS:IP = 07C0:0000 or 0000:7C00, but I'm not sure if DS is normally set to anything relevant. Best to assume not.)

    Also, from the source you posted, the secret is at a 0x1d offset into the binary file, not 0x1e. So mov al,[0x7c1e] is wrong. mov al, [0x7c00 + the_secret] would have made sense and adjusted to fit wherever the label ended up.