NT是怎么载入NTLDR的 NT引导研究 ( MBR->DBR->NTLDR )

[转载]NT是怎么载入NTLDR的 NT引导研究1

http://forum.eviloctal.com/thread-17505-1-1.html

 

信息来源: www.hackart.org
文章作者:风般的男人

操作系统的引导过程是这样的:
1 BIOS读入MBR 到0000:7C00,交执行权给MBR
2 MBR识别分区,读入有引导权限的DBR0000:7c00
3 DBR找到NTLDR,把NTLDR读入内存2000:0000,NTLDR进32位,加载内核 ,以下是上述过程的第3步的代码分析,要了解前面步骤请看我的 <<数据安全与编程 技术 >>(广告)。需要说明的是以下过程是FAT32文件系统中的代码,其实 NTFS 这一过程也是类似的,目的一样,都是分析文件系统将NTLDR读入内存,并交执行权限,过程不同而已。废话一句,NTFS和FAT32中的引导代码风格很相识,估计是一个人写的。MS的引导代码都像一个人写的。

;以下是DBR中引导记录的代码,其目的就是将0C扇区读入内存并交执行权


//********************** Start of Code in Segment: 1 **************

:0001.0000 33C9             xor cx, cx     ;CX= 0
:0001.0002 8ED1             mov ss, cx    ;SS = 0
:0001.0004 BCF47B            mov sp, 7BF4  ;SP = 7BF4
:0001.0007 8EC1             mov es, cx    ;ES = 0
:0001.0009 8ED9             mov ds, cx    ;DS = 0
:0001.000B BD007C            mov bp, 7C00  ;BP = 7C00
:0001.000E 884E02            mov [bp+02], cl  ;7C02 = 0 (1字节)
:0001.0011 8A5640            mov dl, [bp+40]  ;dl = 80h 驱动 器号
:0001.0014 B408             mov ah, 08     ;ah = 8  读驱动器参数
:0001.0016 CD13             int 13        
:0001.0018 7305             jnb 001F;cf = 0转(成功转)
:0001.001A B9FFFF            mov cx, FFFF  ;cx = ffff
:0001.001D 8AF1             mov dh, cl    ;dh = ff

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0018(C)
|
:0001.001F 660FB6C6          movzx eax, dh  ;最大磁头dh扩展到exa
:0001.0023 40              inc ax       ;AX=AX+1,AX为最大磁头数+1, 从0开始算,所以AX为磁头数
:0001.0024 660FB6D1          movzx edx, cl   ;读取驱动器参数成功则cl中B7 B6为可用柱面号的最大值高2位, B5~B0为扇区最大值
;读不成功则CL = FF,EDX = 0FF;
:0001.0028 80E23F            and dl, 3F      ;高2位为0,DL = 最大扇区数
:0001.002B F7E2             mul dx       ; AX = 磁头数 * 扇区数
:0001.002D 86CD             xchg ch, cl    ;CH = 可用柱面号的最大值(低8位),CL中B7 B6为可用柱面号的最大值高2位,B5~B0为
  ;可用扇区的最大值,交换后则反
:0001.002F C0ED06            shr ch, 06     ;CH逻辑右移6位 CH=柱面号最大值的高位(这样CX = 最大柱面号)
:0001.0032 41              inc cx        ;CX+1(柱面号是从0开始的,最大柱面号+1后就为柱面数)
:0001.0033 660FB7C9          movzx ecx, word ptr cx  ;CX扩展到ECX
:0001.0037 66F7E1            mul ecx            ;EAX=柱面数*EAX=柱面数*磁头数*扇区数,结果是这个 磁盘 的扇区数,
;不过是8G以内的,大于8G的就当8G处理
:0001.003A 668946F8          mov [bp-08], eax      ;把这个结果(3D方式下的扇区数)保存到BP-08的位置上,也就是7C00-8=7BF8
:0001.003E 837E1600          cmp word ptr [bp+16], 0000 ;是否30M以下的小硬盘(16为小硬盘下的每FAT扇区数)
:0001.0042 7538             jne 007C              ;是小硬盘转
:0001.0044 837E2A00          cmp word ptr [bp+2A], 0000  ;版本是否为0 (2A为小硬盘下的磁盘扇区总数)
:0001.0048 7732             ja 007C              ;高于0则转
:0001.004A 668B461C          mov eax, [bp+1C]    ;eax = 隐含扇区数
:0001.004E 6683C00C          add eax, 0000000C        ;隐含扇区数+0c
:0001.0052 BB0080            mov bx, 8000           ;bx=8000
:0001.0055 B90100            mov cx, 0001           ;cx=1
:0001.0058 E82B00            call 0086
:0001.005B E94803            jmp 03A6              ;03a6??????



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0106(C)
|
:0001.005E A0FA7D            mov al, [7DFA]     ;以下代码显示错误信息

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.007A(U), :0001.007F(U)
|
:0001.0061 B47D             mov ah, 7D
:0001.0063 8BF0             mov si, ax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0075(U)
|
:0001.0065 AC              lodsb
:0001.0066 84C0             test al , al
:0001.0068 7417             je 0081
:0001.006A 3CFF             cmp al, FF
:0001.006C 7409             je 0077
:0001.006E B40E             mov ah, 0E
:0001.0070 BB0700            mov bx, 0007
:0001.0073 CD10             int 10          ;显示Press any key to restart
:0001.0075 EBEE             jmp 0065



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.006C(C)
|
:0001.0077 A0FB7D            mov al, [7DFB]
:0001.007A EBE5             jmp 0061



* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0042(C), :0001.0048(C)
|
:0001.007C A0F97D            mov al, [7DF9]
:0001.007F EBE0             jmp 0061



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0068(C)
|
:0001.0081 98              cbw      
:0001.0082 CD16             int 16
:0001.0084 CD19             int 19      ;重启

* Referenced by a CALL at Address:
|:0001.0058
|

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0111(C)
|
:0001.0086 6660             pushad          ;所有寄存器进栈
:0001.0088 663B46F8          cmp eax, [bp-08]    ;隐含扇区数+0c 与 3D方式下的扇区数比较,
:0001.008C 0F824A00          jb 00DA          ;小于则转(小于可能要用非扩展INT13中断来读扇区)
:0001.0090 666A00            push 00000000      ;00000000入栈  像在构建一个DAP
:0001.0093 6650             push eax         ;eax入栈 (隐含扇区数+0c)
:0001.0095 06              push es          ;es入栈 es = 0
:0001.0096 53              push bx          ;bx入栈 bx = 8000
:0001.0097 666810000100        push 00010010      ;构建dap数据包的前8个字节,dap长度为0010H,读1个扇区(0001)
:0001.009D 807E0200          cmp byte ptr [bp+02], 00 ;比较偏移02处是否为0,一般为90
:0001.00A1 0F852000          jne 00C5            ;不是转C5
:0001.00A5 B441             mov ah, 41           ;扩展功能ah = 41,检验扩展功能是否存在
:0001.00A7 BBAA55            mov bx, 55AA          ;入口参数bx = 55aa
:0001.00AA 8A5640            mov dl, [bp+40]        ;Dl = 80
:0001.00AD CD13             int 13
:0001.00AF 0F821C00          jb 00CF             ;cf = 1,主板不支持扩展int13转
:0001.00B3 81FB55AA          cmp bx, AA55          ;
:0001.00B7 0F851400          jne 00CF            ;bx不等于55aa,扩展int13不可用转
:0001.00BB F6C101            test cl, 01           ;测试扩展读盘访问是否被支持
:0001.00BE 0F840D00          je 00CF            ;不支持转
:0001.00C2 FE4602            inc byte ptr [bp+02]    ;[7c02]处+1 = 1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.00A1(C)
|
:0001.00C5 B442             mov ah, 42
:0001.00C7 8A5640            mov dl, [bp+40]
:0001.00CA 8BF4             mov si, sp          ;si = sp 指向DAP数据包
:0001.00CC CD13             int 13            ;读相对逻辑扇区0c扇到 0:8000
:0001.00CE B0F9             mov al, F9          ;al = F9
:0001.00D0 6658             pop eax            
:0001.00D2 6658             pop eax
:0001.00D4 6658             pop eax
:0001.00D6 6658             pop eax           ;清堆栈 eax = 0
:0001.00D8 EB2A             jmp 0104



* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.008C(C)
|;不需要用扩展int13读,就用传统的int13
:0001.00DA 6633D2            xor edx, edx  ;edx = 0
:0001.00DD 660FB74E18         movzx ecx, word ptr [bp+18]  ;ecx = 63 扇区号
:0001.00E2 66F7F1            div ecx               ;该指令完成后eax为磁头数 ,edx为扇区数             ;
:0001.00E5 FEC2             inc dl              ;Dl = dl+1,扇区数+1
:0001.00E7 8ACA             mov cl , dl          ;cl = 扇区数
:0001.00E9 668BD0            mov edx, eax          ;edx = 磁头数
:0001.00EC 66C1EA10          shr edx, 10           ;edx右移16位,结果为EDX高位送低16位
:0001.00F0 F7761A            div word ptr [bp+1A]     ;每
:0001.00F3 86D6             xchg dh, dl
:0001.00F5 8A5640            mov dl, [bp+40]
:0001.00F8 8AE8             mov ch, al
:0001.00FA C0E406            shl ah, 06
:0001.00FD 0ACC             or cl , ah
:0001.00FF B80102            mov ax, 0201
:0001.0102 CD13             int 13              ;读到8000处

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.00D8(U)
|
:0001.0104 6661             popad             ;所有寄存器出栈
:0001.0106 0F8254FF          jb 005E            ;
:0001.010A 81C30002          add bx, 0200        ;bx=8000 + 200
:0001.010E 6640             inc eax            ;eax =  0 + 1
:0001.0110 49              dec cx            ;cx = 1 - 1 =0
:0001.0111 0F8571FF          jne 0086
:0001.0115 C3              ret               ;回到58处


:0001.0116 4E              dec si
:0001.0117 54              push sp
:0001.0118 4C              dec sp
:0001.0119 44              inc sp
:0001.011A 52              push dx
:0001.011B 2020             and [bx+si], ah
:0001.011D 2020             and [bx+si], ah
:0001.011F 2020             and [bx+si], ah
:0001.0121 00000000000000000000  BYTE 10 DUP(0)
:0001.012B 00000000000000000000  BYTE 10 DUP(0)
:0001.0135 00000000000000000000  BYTE 10 DUP(0)
:0001.013F 00000000000000000000  BYTE 10 DUP(0)
:0001.0149 000000000000000000    BYTE  9 DUP(0)


:0001.0152 0D0A4E            or ax, 4E0A
:0001.0155 54              push sp
:0001.0156 4C              dec sp
:0001.0157 44              inc sp
:0001.0158 52              push dx
:0001.0159 206973            and [bx+di+73], ch
:0001.015C 206D69            and [di+69], ch
:0001.015F 7373             jnb 01D4
:0001.0161 696E67FF0D         imul bp, [bp+67], 0DFF
:0001.0166 0A4469            or al , [si+69]
:0001.0169 736B             jnb 01D6
:0001.016B 206572            and [di+72], ah
:0001.016E 726F             jb 01DF
:0001.0170 72FF             jb 0171
:0001.0172 0D0A50            or ax, 500A
:0001.0175 7265             jb 01DC
:0001.0177 7373             jnb 01EC
:0001.0179 20616E            and [bx+di+6E], ah
:0001.017C 7920             jns 019E
:0001.017E 6B657920          imul sp, [di+79], 0020
:0001.0182 746F             je 01F3
:0001.0184 207265            and [bp+si+65], dh
:0001.0187 7374             jnb 01FD
:0001.0189 61              popa
:0001.018A 7274             jb 0200
:0001.018C 0D0A00            or ax, 000A
:0001.018F 00000000000000000000  BYTE 10 DUP(0)
:0001.0199 000000000000        BYTE  6 DUP(0)


:0001.019F AC              lodsb
:0001.01A0 BFCC00            mov di, 00CC
:0001.01A3 0055AA            add [di-56], dl

;以下是FAT32分区中第12扇区的内容,其目的是分析根目录找到NTLDR的位置,将其读入到2000:0000并交执行权


//********************** Start of Code in Segment: 1 **************

:0001.0000 660FB64610         movzx eax, [bp+10]  ;偏移10为FAT的个数
:0001.0005 668B4E24          mov ecx, [bp+24]    ;偏移24为每FAT扇区数
:0001.0009 66F7E1            mul ecx          ;fat个数*FAT扇区数 = FAT总共占有的扇区数 放入EAX中
:0001.000C 6603461C          add eax, [bp+1C]    ;加隐藏扇区数
:0001.0010 660FB7560E         movzx edx, word ptr [bp+0E]  ;保留扇区数放入edx
:0001.0015 6603C2            add eax, edx          ;eax = 数据区的起始扇区
:0001.0018 668946FC          mov [bp-04], eax        ;放入7c00 - 4处
:0001.001C 66C746F4FFFFFFFF     mov dword ptr [bp-0C], FFFFFFFF  ;7c00 - 0c处 = FFFFFFFF
:0001.0024 668B462C          mov eax, [bp+2C]            ;根目录的第一个簇号放入eax
:0001.0028 6683F802          cmp eax, 00000002           ;第一簇是否是2
:0001.002C 0F82A6FC          jb FCD6                  ;小于2转上面的偏移0d6处(好像是进个死循环)
:0001.0030 663DF8FFFF0F        cmp eax, 0FFFFFF8           ;比较第一簇是否是0FFFFFF8
:0001.0036 0F839CFC          jnb FCD6                 ;大于等于转(这两个跳转一般情况都不会转,除非磁盘破坏)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0079(C)
|
:0001.003A 6650             push eax                ;根目录的第一个簇号入栈
:0001.003C 6683E802          sub eax, 00000002          ;eax - 2
:0001.0040 660FB65E0D         movzx ebx, [bp+0D]          ;每簇扇区数送ebx
:0001.0045 8BF3             mov si, bx               ;每簇扇区数送si
:0001.0047 66F7E3            mul ebx                 ;eax = 每簇扇区数 * (根目录簇数 - 2)
:0001.004A 660346FC          add eax, [bp-04]           ;eax + 加上数据区的起始扇区 = 根目录的起始扇区数

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0072(C)
|
:0001.004E BB0082            mov bx, 8200              ;bx = 8200
:0001.0051 8BFB             mov di, bx               ;di = 8200
:0001.0053 B90100            mov cx, 0001              ;cx = 1
:0001.0056 E887FC            call FCE0                ;这段代码可能是读根目录到8200

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.006F(C)
|
:0001.0059 382D             cmp [di], ch              ;如果根目录第一个为空,则说明根目录没有文件
:0001.005B 741E             je 007B
:0001.005D B10B             mov cl, 0B                ;比较0b次,
:0001.005F 56              push si                  ;si入栈
:0001.0060 BE707D            mov si, 7D70              ;7d70为NTLDR字符串
:0001.0063 F3              repz                    ;比较
:0001.0064 A6              cmpsb
:0001.0065 5E              pop si                  ;si出栈
:0001.0066 741B             je 0083                  ;比较一样则跳到83处
:0001.0068 03F9             add di, cx               
:0001.006A 83C715            add di, 0015
:0001.006D 3BFB             cmp di, bx
:0001.006F 72E8             jb 0059                  ;指向下一个目录项继续比较
:0001.0071 4E              dec si                  
:0001.0072 75DA             jne 004E
:0001.0074 6658             pop eax
:0001.0076 E86500            call 00DE
:0001.0079 72BF             jb 003A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.005B(C)
|
:0001.007B 83C404            add sp, 0004
:0001.007E E955FC            jmp FCD6


:0001.0081 00              BYTE 0


;:0001.0082 2083C404          and [bp+di+04C4], al
:0001.0083 83C404            add sp, 0004  
:0001.0086 8B7509            mov si, [di+09]
:0001.0089 8B7D0F            mov di, [di+0F]
:0001.008C 8BC6             mov ax, si
:0001.008E 66C1E010          shl eax, 10
:0001.0092 8BC7             mov ax, di
:0001.0094 6683F802          cmp eax, 00000002
:0001.0098 0F823AFC          jb FCD6
:0001.009C 663DF8FFFF0F        cmp eax, 0FFFFFF8
:0001.00A2 0F8330FC          jnb FCD6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.00D4(C)
|
:0001.00A6 6650             push eax
:0001.00A8 6683E802          sub eax, 00000002
:0001.00AC 660FB64E0D         movzx ecx, [bp+0D]
:0001.00B1 66F7E1            mul ecx
:0001.00B4 660346FC          add eax, [bp-04]
:0001.00B8 BB0000            mov bx, 0000
:0001.00BB 06              push es
:0001.00BC 8E068180          mov es, [8081]
:0001.00C0 E81DFC            call FCE0
:0001.00C3 07              pop es
:0001.00C4 6658             pop eax
:0001.00C6 C1EB04            shr bx, 04
:0001.00C9 011E8180          add [8081], bx
:0001.00CD E80E00            call 00DE
:0001.00D0 0F830200          jnb 00D6
:0001.00D4 72D0             jb 00A6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.00D0(C)
|
:0001.00D6 8A5640            mov dl, [bp+40]
:0001.00D9 EA00000020         jmp 2000:0000                ;交执行权给NTLDR



* Referenced by a CALL at Addresses:
|:0001.0076, :0001.00CD
|
:0001.00DE 66C1E002          shl eax, 02
:0001.00E2 E81100            call 00F6
:0001.00E5 26668B01          mov eax, es:[bx+di]
:0001.00E9 6625FFFFFF0F        and eax, 0FFFFFFF
:0001.00EF 663DF8FFFF0F        cmp eax, 0FFFFFF8
:0001.00F5 C3              ret



* Referenced by a CALL at Address:
|:0001.00E2
|
:0001.00F6 BF007E            mov di, 7E00
:0001.00F9 660FB74E0B         movzx ecx, word ptr [bp+0B]
:0001.00FE 6633D2            xor edx, edx
:0001.0101 66F7F1            div ecx
:0001.0104 663B46F4          cmp eax, [bp-0C]
:0001.0108 743A             je 0144
:0001.010A 668946F4          mov [bp-0C], eax
:0001.010E 6603461C          add eax, [bp+1C]
:0001.0112 660FB74E0E         movzx ecx, word ptr [bp+0E]
:0001.0117 6603C1            add eax, ecx
:0001.011A 660FB75E28         movzx ebx, word ptr [bp+28]
:0001.011F 83E30F            and bx, 000F
:0001.0122 7416             je 013A
:0001.0124 3A5E10            cmp bl , [bp+10]
:0001.0127 0F83ABFB          jnb FCD6
:0001.012B 52              push dx
:0001.012C 668BC8            mov ecx, eax
:0001.012F 668B4624          mov eax, [bp+24]
:0001.0133 66F7E3            mul ebx
:0001.0136 6603C1            add eax, ecx
:0001.0139 5A              pop dx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0122(C)
|
:0001.013A 52              push dx
:0001.013B 8BDF             mov bx, di
:0001.013D B90100            mov cx, 0001
:0001.0140 E89DFB            call FCE0
:0001.0143 5A              pop dx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0108(C)
|
:0001.0144 8BDA             mov bx, dx
:0001.0146 C3              ret


:0001.0147 00000000000000000000  BYTE 10 DUP(0)
:0001.0151 00000000000000000000  BYTE 10 DUP(0)
:0001.015B 00000000000000000000  BYTE 10 DUP(0)
:0001.0165 00000000000000000000  BYTE 10 DUP(0)
:0001.016F 00000000000000000000  BYTE 10 DUP(0)
:0001.0179 00000000000000000000  BYTE 10 DUP(0)
:0001.0183 00000000000000000000  BYTE 10 DUP(0)
:0001.018D 00000000000000000000  BYTE 10 DUP(0)
:0001.0197 00000000000000000000  BYTE 10 DUP(0)
:0001.01A1 00000000000000000000  BYTE 10 DUP(0)
:0001.01AB 00000000000000000000  BYTE 10 DUP(0)
:0001.01B5 00000000000000000000  BYTE 10 DUP(0)
:0001.01BF 00000000000000000000  BYTE 10 DUP(0)
:0001.01C9 00000000000000000000  BYTE 10 DUP(0)
:0001.01D3 00000000000000000000  BYTE 10 DUP(0)
:0001.01DD 00000000000000000000  BYTE 10 DUP(0)
:0001.01E7 00000000000000000000  BYTE 10 DUP(0)
:0001.01F1 00000000000000000000  BYTE 10 DUP(0)
:0001.01FB 000000            BYTE  3 DUP(0)


:0001.01FE 55              push bp
:0001.01FF AA              stosb

你可能感兴趣的:(c,扩展,div,byte,代码分析,磁盘)