I was playing around with my BIOS today and managed to load the boot code. On x86 systems, the processor always starts execution at F000:FFF0 (linearly 0xFFFF0). I looked there and found this:
So far so good. I go to F000:E05B and I find this:Code:F000:FFF0 JMP F000:E05B
I know this is legit code because the last instruction is a jump to 0000:7C00, where the BIOS always loads the boot sector code for initialization. Now, if we look at the function in FC00:07FE...Code:F000:E05B CALL FC00:07FE F000:E060 STI F000:E061 MOV AL, 08H F000:E063 INT E6 F000:E065 CMP AL, 00H F000:E067 JZ E073 F000:E069 PUSH DS F000:E06A CALL FAR CS:[D000] F000:E06F POP DS F000:EO70 STI F000:E071 JMP E078 F000:E073 MOV AL, DS:[0049] F000:E076 INT 10 F000:E078 MOV AL, 09H F000:E07A INT E6 F000:E07C MOV AL, 05H F000:E07E INT E6 F000:E080 MOV DL, CS:[D009] F000:E085 JMP 0000:7C00
First thing that you should notice: Two HLT instructions in a row. What? So that's waiting for two hardware interrupts...All right, I guess that's legal. Here's where it gets weird:Code:FC00:07FE HLT FC00:07FF HLT FC00:0800 PUSH BX FC00:0801 POP AX FC00:0802 MOV AH, 62H FC00:0804 INT 21H FC00:0806 POP AX FC00:0807 HLT FC00:0808 POP BX FC00:0809 RETF FC00:080A... HLT
Why not this?Code:FC00:0800 PUSH BX FC00:0801 POP AX
All right, that's inefficient but it works. Then there's this:Code:MOV AX, BX
First of all - why did we move BX into AX if we're overwriting AH immediately afterward? Wouldn't a simple MOV AL, BL have done the trick instead of that push/pop nonsense?Code:FC00:0802 MOV AH, 62H FC00:0804 INT 21H
Second thing - if you look up the interrupt, it's a subprogram for retrieving the address of the PSP. The PSP does not exist when executing BIOS boot code. It's for COM programs only.
And now we get into illegal things:
If we look at our stack, we're now popping the return address' segment into AX, waiting for an interrupt...and popping the stack again, putting the return address' offset into BX. And then we return. But we destroyed our return address with the pops! So we're returning to...who knows where.Code:FC00:0806 POP AX FC00:0807 HLT FC00:0808 POP BX FC00:0809 RETF
And if that weren't enough, look at the interrupt calls made to E9h. They're assigning data to AL and then calling the interrupt. Functions numbers are indicated in AH...so we're calling a random subfunction. Who knows what that is.
Does anyone have any idea what's going on here?
sudo rm -rf /
well if u are looking at the first 60Byte of the Partition table and the Bios links to it,then u got into the place where the windows kernel loads the drive letters.
No, not exactly. Few things wrong with that:
I'm dual booting with Ubuntu, so this would load GRUB, not Windows. Even if it were, the first 60 bytes most likely won't load the drive letters; they'll load the kernel, if anything. It's the kernel's job to switch to protected mode and enumerate the drives, which certainly won't be in the boot sector of the partition table.
The BIOS loads the first 512 bytes of the first bootable drive (my hard drive in this case) into memory at location 7C00:0000. (At this point the processor is still in 8086 emulation mode.) I checked in memory, not on my hard drive, so this has little to do with loading the kernel. The BIOS just loads the first sector of boot code, which is not what I'm looking at.
sudo rm -rf /
There's code on your BIOS chip which is also the very first code your computer runs when it boots up. It's firmware which is why to update your bios you need to flash it. Although since the only thing as far as I know initiating it is a hardcoded reference to a memory address in the cpu I imagine you could technically write your own.
Since your bios is Intel you might be able to find a reference manual for it. AFAIK all the code should be doing is copying itself into ROM or an area of memory that becomes write-protected... and then runs the post tests for the boot-up sequence and the MBR ofcourse jumping to 0000:7C00. Ofcourse different manufacturers can do it differently (I think).
Unfortunately I haven't gotten into how the chips themselves work within a computer with the exception of a few CPUs. Most of my adventures have happened after theHave fun and document your adventure though, sounds interesting.Code:JMP 0000:7C00
"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.
Yes, you're correct. To further explain the process:
The low megabyte of memory is memory-mapped onto the BIOS. IBM-compatible computers always begin execution at F000:FFFF, where the BIOS has a hard-coded (but flashable) jump instruction to the actual (flashable) boot code.
There the BIOS performs its POST tests and searches for a bootable disk by enumerating all of the memory devices and reading the first 512 bytes from each, according to priorities stored in the CMOS settings. If the last two bytes of the first sector are 0x55 0xAA, then it's considered bootable.
If the BIOS finds one, it copies it from the disk to location 0000:7C00 and jumps there. If not, you get a nice black screen with the message "Operating system not found."
I would imagine that manufacturers of non-IBM-compatible machines probably do otherwise as you suggested. This seems like an outdated and inefficient way to me.
sudo rm -rf /
Sorry for bumping an old thread but has anybody found an explanation?
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks