PBRは何をしてるか

MBRは何をしているかの続きです。
MBRが起動パーティションのPBRを読み込んだ後の動作になります。
ターゲットはWin8.1でフォーマットしたHDD。
ダンプしてみるとこんな感じです。



0000〜0002はエントリポイント。
0003〜000AはNTFSシグネチャ。
000B〜0053はBPB。
0054〜01fdはブートコード。
01fe〜01ffはマジックナンバー(55,aa)。


まず条件として、PBRが読み込まれるのは、
・CPUモード:8086互換モード(16bit)
・MBRが読み込まれるアドレス:0000:7c00
・DLレジスタ:起動ドライブ番号(80〜)
です。

でもって、重要なのはその中身。
逆アセンブル+コメントを作ったのでのせてみる。
結局のところ、
・パーティションテーブルの先頭15セクタを07E0:0000から読み込んむ
・(実装されていれば)TCGのハッシュチェックをする
・読み込んだブートローダー(2段階目)分岐する(07C0:0319)
だけです。

以下逆アセンブル結果。
7C00 EB52                   jmp 7C54
7C02 90                     nop
;signature----------------------
7C03 db  "NTFS    "
;BPB----------------------
7C0B dw  200h ;セクタサイズ
7C0D db  8    ;クラスタサイズ
7C0E dw  0    ;予約セクタ
7C10 db  0,0,0;
7C13 dw  0    ;
7C15 db  0f8h ;メディアディスクリプタ
7C16 dw  0
7C18 dw  3fh  ;Sectors Per Track
7C1A dw  0ffh ;Number Of Heads
7C1C dd  3fh  ;パーティション開始物理セクタ
7C20 dd  0
7C24 dd  80008h
7C28 dq  0aefffh ;Total Sectors
7C30 dq  74aah ;$MFTのあるクラスタ
7C38 dq  2     ;$MFTMirrのあるクラスタ
7C40 db  0f6h  ;ファイルレコードあたりのバイト数。0f6h=-10
               ; 正の場合:セクタ数単位
               ; 負の場合:2の累乗。つまり2^10=1024バイト
7C41 db  0,0,0
7C44 db  1     ;Clusters Per Index Block
7C45 db  0,0,0
7C48 dq  0f44ed0614ed01de4h ;Volume Serial Number
7C50 dd  0;


;ここから
7C54 FA                     cli
7C55 33C0                   xor ax, ax
7C57 8ED0                   mov ss, ax
7C59 BC007C                 mov sp, 7C00
7C5C FB                     sti
7C5D 68C007                 push 07C0
7C60 1F                     pop ds
7C61 1E                     push ds
7C62 686600                 push 0066
7C65 CB                     retf          ;07c0:0066にfar jmp


0066 88160E00               mov [000E], dl;ドライブ番号退避
006A 66813E03004E544653     cmp dword ptr [0003], 5346544E;NTFS
0073 7515                   jne 008A ;シグネチャ無い→リードエラー表示
0075 B441                   mov ah, 41
0077 BBAA55                 mov bx, 55AA
007A CD13                   int 13   ;AH=41h: Check Extensions Present
007C 720C                   jb 008A  ;拡張int13使用不可→リードエラー表示
007E 81FB55AA               cmp bx, AA55
0082 7506                   jne 008A ;拡張int13使用不可→リードエラー表示
0084 F7C10100               test cx, 0001
0088 7503                   jne 008D ;拡張int13使用可
008A E9DD00                 jmp 016A

;拡張int13使用可
008D 1E                     push ds
008E 83EC18                 sub sp, 0018
0091 681A00                 push 001A
0094 B448                   mov ah, 48
0096 8A160E00               mov dl, [000E];ドライブ番号
009A 8BF4                   mov si, sp
009C 16                     push ss
009D 1F                     pop ds
009E CD13                   int 13   ;AH=48h: Extended Read Drive Parameters
00A0 9F                     lahf
00A1 83C418                 add sp, 0018
00A4 9E                     sahf
00A5 58                     pop ax
00A6 1F                     pop ds
00A7 72E1                   jb 008A  ;エラー→リードエラー表示
00A9 3B060B00               cmp ax, [000B]
00AD 75DB                   jne 008A ;セクタサイズ異常→リードエラー表示
00AF A30F00                 mov word ptr [000F], ax;セクタサイズ
00B2 C12E0F0004             shr word ptr [000F], 04;セクタサイズ÷16
                                                   ;※セクタサイズをセグメントに換算
00B7 1E                     push ds
00B8 5A                     pop dx   ;dx=7c0
00B9 33DB                   xor bx, bx
00BB B90020                 mov cx, 2000
00BE 2BC8                   sub cx, ax       ;cx=2000-200=1e00
00C0 66FF061100             inc word ptr [0011];元々0

00C5 03160F00               add dx, [000F];dx=07e0
00C9 8EC2                   mov es, dx
00CB FF061600               inc word ptr [0016];元々0
00CF E84B00                 call 011D        ;1セクタ読み込み

00D2 2BC8                   sub cx, ax       ;1e00から毎回200ずつ減算してループ
00D4 77EF                   ja 00C5          ;つまり15セクタ読み込み

;ここまで来たら7C00〜にpartitionの先頭16セクタが読み込まれている
00D6 B800BB                 mov ax, BB00
00D9 CD1A                   int 1A           ;AX=bb00 TCG_StatusCheck
00DB 6623C0                 and eax, eax
00DE 752D                   jne 010D         ;TCG非対応ならジャンプ
00E0 6681FB54435041         cmp ebx, 41504354
00E7 7524                   jne 010D         ;TCG非対応ならジャンプ
00E9 81F90201               cmp cx, 0102
00ED 721E                   jb 010D          ;Ver1.2未満ならジャンプ
00EF 16                     push ss   ;eax(MSB)(dummy)
00F0 6807BB                 push BB07 ;eax(LSB)
00F3 16                     push ss   ;ecx(MSB)(0)
00F4 685211                 push 1152 ;ecx(LSB)(length)
00F7 16                     push ss   ;edx(MSB)(0)
00F8 680900                 push 0009 ;edx(LSB)(PCR index9=NTFS ブート ブロック)
00FB 6653                   push ebx  ;ebx=41504354
00FD 6653                   push ebx  ;esp(dummy)
00FF 6655                   push ebp  ;ebp(dummy)
0101 16                     push ss   ;esi(MSB)
0102 16                     push ss   ;esi(LSB)
0103 16                     push ss   ;edi(MSB)
0104 68B801                 push 01B8 ;edi(LSB)
0107 6661                   popad
0109 0E                     push cs
010A 07                     pop es
010B CD1A                   int 1A    ;TCG_CompactHashLogExtendEvent

010D 33C0                   xor ax, ax
010F BF0A13                 mov di, 130A
0112 B9F60C                 mov cx, 0CF6
0115 FC                     cld
0116 F3AA                   repz stosb   ;130A〜0CF6バイトを0クリア
0118 E9FE01                 jmp 0319


011B 90                     nop
011C 90                     nop


;[0011]+[001c(hidden sec=partiton#0の先頭)]セクタ〜を[0016]セクタを読み込む
;読み込み先 es:bx

011D 6660                   pushad
011F 1E                     push ds
0120 06                     push es

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|0163(C)
|
0121 66A11100               mov eax, dword ptr [0011]
0125 6603061C00             add eax, [001C]
012A 1E                     push ds
012B 666800000000           push 00000000
0131 6650                   push eax  ;セクタ番号
0133 06                     push es   ;読み込み先セグメント
0134 53                     push bx   ;読み込み先アドレス
0135 680100                 push 0001 ;読み込みセクタ数
0138 681000                 push 0010
013B B442                   mov ah, 42
013D 8A160E00               mov dl, [000E];ドライブ番号
0141 16                     push ss
0142 1F                     pop ds
0143 8BF4                   mov si, sp
0145 CD13                   int 13 ;AH=42h: Extended Read Sectors From Drive
0147 6659                   pop ecx ;捨てる
0149 5B                     pop bx  ;読み込み先アドレス
014A 5A                     pop dx  ;読み込み先セグメント
014B 6659                   pop ecx ;捨てる?
014D 6659                   pop ecx ;捨てる?
014F 1F                     pop ds  ;ds
0150 0F821600               jb 016A;読み込みエラー発生
0154 66FF061100             inc word ptr [0011]
0159 03160F00               add dx, [000F]
015D 8EC2                   mov es, dx
015F FF0E1600               dec word ptr [0016]
0163 75BC                   jne 0121
0165 07                     pop es
0166 1F                     pop ds
0167 6661                   popad
0169 C3                     ret


;エラーメッセージ表示
;A disk read error occurred
;ress Ctrl+Alt+Del to restart
016A A1F601                 mov ax, word ptr [01F6]
016D E80900                 call 0179
0170 A1FA01                 mov ax, word ptr [01FA]
0173 E80300                 call 0179
0176 F4                     hlt
0177 EBFD                   jmp 0176


;文字列表示
0179 8BF0                   mov si, ax
017B AC                     lodsb
017C 3C00                   cmp al, 00
017E 7409                   je 0189
0180 B40E                   mov ah, 0E
0182 BB0700                 mov bx, 0007
0185 CD10                   int 10
0187 EBF2                   jmp 017B
0189 C3                     ret

018A db 0dh,0ah
     db "A disk read error occurred",0

01A7 db 0dh,0ah
     db "BOOTMGR is compressed",0

01BF db 0dh,0ah
     db "Press Ctrl+Alt+Del to restart",0dh,0ah,0


01F6 dw                     018Ah
01F8 dw                     01A7h
01FA dw                     01BFh
01FC dw                     0
01FE dw                     0AA55h



感想、要望、バグ報告、その他何かありましたら、メールもしくは掲示板にてご連絡ください。
裕之  
ホームに戻る