[转载]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