电脑磁盘碎片整理-red hat linux 下载

ntldr is missing
2023年3月31日发(作者:haier电脑)成功转7C8A

0085 B9FFFF mov cx, FFFFtt;读参数失败,则取CHS读盘最大值:柱面数=1024,磁头数=256,扇区数=63

0088 8AF1 mov dh, cl

008A 660FB6C6 movzx eax, dhtt;读参数成功,则dh=磁头数

008E 40 inc ax

008F 660FB6D1 movzx edx, cltt;CH=柱面数的低8位;CL(7-6)=柱面数的高2位,CL(5-0)=扇区数

0093 80E23F and dl, 3Fttt;dx=扇区数

0096 F7E2 mul dxttt;ax=扇区数x磁头数

0098 86CD xchg ch, cl

009A C0ED06 shr ch, 06

009D 41 inc cxttt;cx=柱面数

009E 660FB7C9 movzx ecx, word ptr cx

00A2 66F7E1 mul ecxttt;eax=扇区数x磁头数x柱面数=磁盘的总扇区数

00A5 66A32000 mov dword ptr [0020], eaxt;[0020]=CHS读盘方式能读的最大扇区号

00A9 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;检验扩展int13h功能是否存在

00AA B441 mov ah, 41ttt;检验扩展int13h功能是否存在

00AC BBAA55 mov bx, 55AA

00AF 8A162400 mov dl, [0024]tt;DL=[0024]=驱动器号

00B3 CD13 int 13

00B5 720F jb 00C6ttt;cf=1则此驱动器不支持扩展功能,转出错

00B7 81FB55AA cmp bx, AA55tt;如果进位标志为0,同时 BX = AA55h,则存在扩展功能

00BB 7509 jne 00C6ttt;不相等直接退出t

00BD F6C101 test cl, 01ttt;测试是否支持扩展功能第一个子集

00C0 7404 je 00C6ttt;不支持直接退出

00C2 FE061400 inc byte ptr [0014]tt;支持扩展int13h功能,则[0014]=1

00C6 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读盘子程序

;入口参数: [0010]=要读的扇区偏移 [000E]=要读的扇区数 es:bx=读盘缓冲地址

;出口参数: es:bx=要读的数据

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

00C7 6660 pushad

00C9 1E push ds

00CA 06 push es

00CB 66A11000 mov eax, dword ptr [0010]t;[0010]=要读的相对扇区偏移

00CF 6603061C00 add eax, [001C]tt;[001C]=隐藏扇区数

00D4 663B062000 cmp eax, [0020]tt;[0020]=CHS读盘方式能读的最大扇区号t

00D9 0F823A00 jb 0117ttt;小于则用常规int13h读盘

00DD 1E push ds

00DE 666A00 push 00000000tt;扩展 Int13H 构造磁盘地址数据包

00E1 6650 push eaxttt;磁盘起始绝对块地址,和分区无关 占8字节(以扇区为单位)

00E3 06 push esttt;读盘缓冲地址(ES=segment

器参数,返回: ds:[0020]=(CHS读盘方式)磁盘的总扇区数

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;计算每个记录所占扇区数

0278 660FB7060B00 movzx eax, word ptr [000B]t;[000B]=每扇区字节数

027E 660FB61E0D00 movzx ebx, byte ptr [000D]t;[000D]=每簇扇区数

0284 66F7E3 mul ebx

0287 66A34E02 mov dword ptr [024E], eaxt;ds:[024E]=每簇字节数

028B 668B0E4000 mov ecx, [0040]tt;[0040]==每个记录占簇

0290 80F900 cmp cl, 00

0293 0F8F0E00 jg 02A5ttt;大于转02A5

0297 F6D9 neg clttt;为负求补 cl=0-F6=0A

0299 66B801000000 mov eax, 00000001

029F 66D3E0 shl eax, cl tt;移位后 eax=每个记录所占字节数=1024

02A2 EB08 jmp 02AC

02A4 90 nop

02A5 66A14E02 mov eax, dword ptr [024E]t;ds:[024E]=每簇字节数

02A9 66F7E1 mul ecxttt;eax=每个记录占簇x每簇字节数=每个记录所占字节数

02AC 66A35202 mov dword ptr [0252], eaxt;[0252]=每个记录所占字节数

02B0 660FB71E0B00 movzx ebx, word ptr [000B]t;[000B]=每扇区字节数

02B6 6633D2 xor edx, edx

02B9 66F7F3 div ebxttt;eax=每个记录所占字节数/每扇区字节数=每个记录所占扇区数

02BC 66A35602 mov dword ptr [0256], eaxt;[0256]=每个记录所占扇区数=2

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读$MFT记录,搜索属性列表属性,分析数据属性内容

02C0 E80D04 call 06D0

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;设置解析根目录的缓冲区

02C3 668B0E4A02 mov ecx, [024A]tt;[024A]=R

02C8 66890E2202 mov [0222], ecxtt;[0222]=R

02CD 66030E5202 add ecx, [0252]tt;[0252]=每个记录所占字节数

02D2 66890E2602 mov [0226], ecxtt;[0226]=400+R

02D7 66030E5202 add ecx, [0252]

02DC 66890E2A02 mov [022A], ecxtt;[022A]=800+R

02E1 66030E5202 add ecx, [0252]

02E6 66890E3A02 mov [023A], ecxtt;[023A]=C00+R

02EB 66030E5202 add ecx, [0252]

02F0 66890E4202 mov [0242], ecxtt;[0242]=1000+R

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取根目录各属性首址

02F5 66B890000000 mov eax, 00000090tt;eax=索引根目录属性

02FB 668B0E2202 mov ecx, [0222]tt;ecx=R

0300 E8EC08 call 0BEFttt;读根目录,搜索索引根目录属性t

0303 660BC0 or eax, eaxttt;eax=索引根目录属性首址

0306 0F8457FE je 0161

030A 66A32E02 mov dword pt

r [022E], eaxt;[022E]=索引根目录属性首址

030E 66B8A0000000 mov eax, 000000A0tt;eax=索引分配表属性

0314 668B0E2602 mov ecx, [0226]tt;ecx=[0226]=400+R

0319 E8D308 call 0BEFttt;读根目录,搜索索引分配表属性

031C 66A33202 mov dword ptr [0232], eaxt;[0232]=索引分配表属性首址

0320 66B8B0000000 mov eax, 000000B0tt;eax=索引位图属性

0326 668B0E2A02 mov ecx, [022A]tt;ecx=[022A]=800+R

032B E8C108 call 0BEFttt;读根目录,搜索索引位图属性首址

032E 66A33602 mov dword ptr [0236], eaxt;[0236]=索引位图属性首址

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;计算每个索引记录扇区数,检查目录属性地址是否为空

0332 66A12E02 mov eax, dword ptr [022E]tt;eax=[022E]=索引根目录属性首址

0336 660BC0 or eax, eax

0339 0F8424FE je 0161tttt;为0 转出错

033D 6780780800 cmp byte ptr [eax+08], 00tt;(00:常驻属性;01:非常驻属性)

0342 0F851BFE jne 0161tttt;不为常驻属性转出错

0346 67668D5010 lea edx, dword ptr [eax+10]tt;edx=索引根目录属性首址+10

034B 67034204 add ax, word ptr [edx+04]tt;eax=索引根目录属性数据起始字节(相当于属性头起始地址)

034F 67660FB6480C movzx ecx, byte ptr [eax+0C]

0355 66890E6202 mov [0262], ecxttt;[0262]=ecx=每个簇可以记录的索引记录个数

035A 67668B4808 mov ecx, dword ptr [eax+08]

035F 66890E5E02 mov [025E], ecxttt;[025E]=ecx=索引记录大小

0364 66A15E02 mov eax, dword ptr [025E]

0368 660FB70E0B00 movzx ecx, word ptr [000B]

036E 6633D2 xor edx, edx

0371 66F7F1 div ecxtttt;eax=索引记录大小/每扇区字节数=每个索引记录扇区数

0374 66A36602 mov dword ptr [0266], eaxtt;[0266]=每个索引记录所占扇区数

0378 66A14202 mov eax, dword ptr [0242]tt;eax=[0242]=1000+R

037C 6603065E02 add eax, [025E]

0381 66A34602 mov dword ptr [0246], eaxtt;[0246]=1000+R + 索引记录大小

0385 66833E320200 cmp dword ptr [0232], 00000000

038B 0F841900 je 03A8tttt;索引分配表属性首址为0 转出错

038F 66833E360200 cmp dword ptr [0236], 00000000

0395 0F84C8FD je 0161tttt;索引位图属性首址为0转出错

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取NTLDR文件的MFT记录号

0399 668B1E3602 mov ebx, [0236]ttt;ebx=索引位图属性首址

039E 1E push ds

039F 07 pop es

03A0 668B3E4602 mov edi, [0246]ttt;es:edi=缓冲区首址=[0246]=1000+R + 索引记录大小

0

3A5 E89201 call 053Atttt;读取索引位图属性数据

03A8 660FB70E0002 movzx ecx, word ptr [0200]tt;[0200]=NTLDR文件长度

03AE 66B802020000 mov eax, 00000202ttt;eax=文件名首址(NTLDR)

03B4 E89607 call 0B4Dtttt;检查索引记录头,取指定文件索引项首址

03B7 660BC0 or eax, eaxtttt;eax=索引项首址

03BA 0F840A09 je 0CC8tttt;eax=0 转出错(NTLDR is missing)

03BE 67668B00 mov eax, dword ptr [eax]tt;eax=NTLDR文件的MFT记录号

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读NTLDR文件的MFT记录,取NTLDR文件的数据属性首址

03C2 1E push ds

03C3 07 pop es

03C4 668B3E3A02 mov edi, [023A]ttt;edi=[023A]=C00+R eax=NTLDR文件的MFT记录号

03C9 E8CE05 call 099Atttt;读NTLDR文件的MFT记录

03CC 66A13A02 mov eax, dword ptr [023A]tt;eax=NTLDR文件的MFT记录首址

03D0 66BB80000000 mov ebx, 00000080

03D6 66B900000000 mov ecx, 00000000

03DC 66BA00000000 mov edx, 00000000

03E2 E8AC00 call 0491tttt;查找NTLDR文件的数据属性

03E5 660BC0 or eax, eax

03E8 0F853E00 jne 042Atttt;找到数据属性转042A

;在属性列表中查找数据属性,取NTLDR文件的数据属性首址

03EC 66B980000000 mov ecx, 00000080ttt;没找到数据属性,则查找属性列表属性

03F2 66A13A02 mov eax, dword ptr [023A]

03F6 E85908 call 0C52tttt;在属性列表中搜索数据属性

03F9 660BC0 or eax, eaxtttt;eax=NTLDR文件数据属性的MFT记录号

03FC 0F84C808 je 0CC8tttt;eax=0 转出错(NTLDR is missing)ttt

0400 1E push ds

0401 07 pop es

0402 668B3E3A02 mov edi, [023A]ttt;edi=[023A]=C00+R

0407 E89005 call 099Atttt;读NTLDR文件数据属性的MFT记录

040A 66A13A02 mov eax, dword ptr [023A]tt;eax=数据属性的MFT记录首址

040E 66BB80000000 mov ebx, 00000080

0414 66B900000000 mov ecx, 00000000

041A 66BA00000000 mov edx, 00000000

0420 E86E00 call 0491tttt;查找NTLDR文件的数据属性

0423 660BC0 or eax, eax

0426 0F849E08 je 0CC8tttt;eax=0 转出错(NTLDR is missing)

;检查数据是否被压缩

042A 67660FB7580C movzx ebx, word ptr [eax+0C]t;[eax+0C]属性值是否压缩,0表示没压缩,1表示压缩

0430 6681E3FF000000 and ebx, 000000FF

0437 0F859308 jne 0CCEtttt;如果数据被压缩,转出错(NTLDR is compressed)

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读取NTLDR文件内容,并跳转到NTLDR文件偏移0000处执行

043B 668B

D8 mov ebx, eaxtt;ebx=数据属性首址tt

043E 680020 push 2000ttt;读盘缓冲区es:edi(2000:0000)

0441 07 pop es

0442 662BFF sub edi, edi

0445 E8F200 call 053Attt;读取NTLDR文件内容

0448 8A162400 mov dl, [0024]tt;dl=驱动器号=80

044C B8E803 mov ax, 03E8

044F 8EC0 mov es, axttt;es=03E8

0451 8D360B00 lea si, [000B]tt;si=000B

0455 2BC0 sub ax, ax

0457 680020 push 2000

045A 50 push ax

045B CB retfttt;跳转到2000:0000处执行(到此引导程序完成任务)

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;按簇读数据

;入口参数:eax=起始簇号;edx=要读的簇数;es:edi=读盘缓冲地址

;出口参数: es:edi=要读的数据

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

045C 06 push es

045D 1E push ds

045E 6660 pushad

0460 668BDA mov ebx, edxtt;ebx=要读的簇数

0463 660FB60E0D00 movzx ecx, [000D]tt;ecx=每簇扇区数,eax=要读数据的起始簇号

0469 66F7E1 mul ecx

046C 66A31000 mov dword ptr [0010], eaxt;[0010]=要读的数据相对分区开始的扇区数

0470 668BC3 mov eax, ebx

0473 66F7E1 mul ecx

0476 A30E00 mov word ptr [000E], axt;[000E]=要读的扇区数

0479 8BDF mov bx, di

047B 83E30F and bx, 000Ftt;bx=edi低4位

047E 8CC0 mov ax, es

0480 66C1EF04 shr edi, 04

0484 03C7 add ax, dittt;edi高位加到es

0486 50 push ax

0487 07 pop esttt;es:bx读盘缓冲地址

0488 E83CFC call 00C7ttt;调用读盘子程序

048B 6661 popad

048D 90 nop

048E 1F pop ds

048F 07 pop es

0490 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;查找指定属性

;入口参数:eax=包含属性MFT记录首址 ebx=要检查的属性 ecx=属性名长度 edx=属性名地址

;出口参数:成功:eax=属性首址;失败:eax=0

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

0491 67034014 add ax, word ptr [eax+14]tt;eax=第一个属性的首址

0495 67668338FF cmp dword ptr [eax], FFFFFFFFt;[eax]=属性类型

049A 0F844C00 je 04EAtttt;属性类型等于FFFFFFFF(结尾),则转04EA(返回失败)

049E 67663918 cmp dword ptr [eax], ebx

04A2 0F853300 jne 0

4D9tttt;属性类型不等于ebx,则转04D9

04A6 660BC9 or ecx, ecx

04A9 0F850A00 jne 04B7tttt;ecx不为零,则转04B7

04AD 6780780900 cmp byte ptr [eax+09], 00tt;[eax+09]=属性名长度

04B2 0F852300 jne 04D9tttt;属性名长度不为零,则转04D9

04B6 C3 retttttt;找到属性,eax=属性首址



04B7 673A4809 cmp cl, byte ptr [eax+09]tt;比较属性名长度

04BB 0F851A00 jne 04D9tttt;不相等则转04D9

04BF 668BF0 mov esi, eaxttt;esi=属性头首址

04C2 6703700A add si, word ptr [eax+0A]tt;esi=属性名首址

04C6 E85906 call 0B22tttt;检查属性名,并将小写字母转大写字母

04C9 6651 push ecx

04CB 1E push ds

04CC 07 pop es

04CD 668BFA mov edi, edx

04D0 F3 repz

04D1 A7 cmpswtttt;比较属性名

04D2 6659 pop ecx

04D4 0F850100 jne 04D9tttt;不相等转04D9

04D8 C3 retttttt;找到属性,eax=属性首址



04D9 676683780400 cmp dword ptr [eax+04], 00000000t;属性总长度

04DF 0F840700 je 04EAtttt;属性总长度为零,则转04EA(返回失败)

04E3 6766034004 add eax, dword ptr [eax+04]tt;eax+属性长度=下一属性开始地址

04E8 EBAB jmp 0495tttt;检查下一属性



04EA 662BC0 sub eax, eaxttt;返回失败

04ED C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;搜索索引记录头,查找指定文件

;入口参数: eax=索引项的偏移地址 ebx==文件名首址 ecx=文件名长度

;出口参数: eax=指定文件索引项首址

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

04EE 668BF3 mov esi, ebxttt;esi=文件名首址 ecx=文件名长度

04F1 E82E06 call 0B22tttt;检查文件名,并将小写字母转大写字母

04F4 67660300 add eax, dword ptr [eax]tt;eax=索引项首址



04F8 67F7400C0200 test word ptr [eax+0C], 0002t;[eax+0C]=索引标志

04FE 0F853400 jne 0536tttt;ZF=0 转0536



0502 67668D5010 lea edx, dword ptr [eax+10]t

0507 673A4A40 cmp cl, byte ptr [edx+40]tt;比较文件名长度

050B 0F851800 jne 0527

050F 67668D7242 lea esi, dword ptr [edx+42]tt;[edx+42]=文件名首址

0514 E80B06 call 0B22tttt;检查宽位字符,并将小写字母转大写字母

0517 6651 push ecx

0519 1E push ds

051A 07 pop es

051B 668BFB mov edi, ebx

051E F3 repz

051F A7 cmpswtttt;比较文件名

0520 6

659 pop ecx

0522 0F850100 jne 0527

0526 C3 retttttt;找到文件,eax=文件索引项首址



0527 6783780800 cmp word ptr [eax+08], 0000tt;[eax+08]=索引项大小

052C 0F840600 je 0536

0530 ******** add ax, word ptr [eax+08]tt;ax=ax+索引项大小

0534 EBC2 jmp 04F8tttt;转到下一个索引项



0536 6633C0 xor eax, eaxttt;没找到文件,eax=0

0539 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读取属性数据

;入口参数:ebx=属性头开始地址tes:edi=属性数据缓冲区

;出口参数: es:edi=属性数据内容tt

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

053A 67807B0800 cmp byte ptr [ebx+08], 00tt;(00:常驻属性;01:非常驻属性)

053F 0F851C00 jne 055F

;常驻属性处理

0543 06 push es

0544 1E push ds

0545 6660 pushad

0547 67668D5310 lea edx, dword ptr [ebx+10]tt;[ebx+10]=常驻属性数据长度

054C 67668B0A mov ecx, dword ptr [edx]tt;ecx=常驻属性数据长度

0550 668BF3 mov esi, ebxttt;esi=常驻属性开始地址

0553 ******** add si, word ptr [edx+04]tt;[edx+4]=属性数据起始字节(相当于属性头起始地址)

0557 F3 repz

0558 A4 movsbtttt;把属性数据复制到es:di缓冲区

0559 6661 popad

055B 90 nop

055C 1F pop ds

055D 07 pop es

055E C3 ret

;非常驻属性处理

055F 67668D5310 lea edx, dword ptr [ebx+10]tt;[ebx+10]=属性内容开始VCN

0564 67668B4A08 mov ecx, dword ptr [edx+08]tt;ecx=属性内容结束VCN

0569 6641 inc ecxtttt;ecx=属性内容所占簇数

056B 662BC0 sub eax, eaxttt;eax存放已读簇数

056E E80100 call 0572tttt;检查是否为非常驻属性

0571 C3 ret

;检查是否为非常驻属性,属性内容所占簇数是否为0

0572 06 push es

0573 1E push ds

0574 6660 pushad

0576 67807B0801 cmp byte ptr [ebx+08], 01tt;(00:常驻属性;01:非常驻属性)

057B 0F840300 je 0582

057F E9DFFB jmp 0161tttt;[ebx+8]不等于01,则转出错

0582 6683F900 cmp ecx, 00000000

0586 0F850600 jne 0590tttt;ecx不等于0则转0590

058A 6661 popad

058C 90 nop

058D 1F pop ds

058E 07 pop es

058F C3 ret

;循环读取非常驻属性数据

0590 6653

push ebxtttt;ebx=属性头开始地址

0592 6650 push eaxtttt;eax=已读的簇数

0594 6651 push ecxtttt;ecx=未读的簇数

0596 6657 push editttt;es:di目标缓冲地址

0598 06 push es

0599 E87304 call 0A0Ftttt;取要读的起始簇号,子运行所占簇数

059C 668BD1 mov edx, ecxttt;edx=子运行所占簇数

059F 07 pop es

05A0 665F pop edi

05A2 6659 pop ecx

05A4 663BCA cmp ecx, edxttt;ecx=未读的簇数,edx=子运行所占簇数

05A7 0F8D0300 jnl 05AEtttt;不低于转05AE

05AB 668BD1 mov edx, ecxttt;edx=要读的簇数,eax=要读的起始簇号

05AE E8ABFE call 045Ctttt;按簇读属性数据

05B1 662BCA sub ecx, edxttt;减去上次已读簇数

05B4 668BDA mov ebx, edxttt;ebx=上次已读簇数

05B7 668BC2 mov eax, edx

05BA 660FB6160D00 movzx edx, [000D]ttt;edx=每簇扇区数

05C0 66F7E2 mul edxtttt;eax=已读簇数x每簇扇区数=已读扇区数

05C3 660FB7160B00 movzx edx, word ptr [000B]tt;edx=每扇区字节数

05C9 66F7E2 mul edxtttt;eax=已读扇区数X每扇区字节数=已读字节数

05CC 6603F8 add edi, eaxttt;读盘缓冲区+已读字节数

05CF 6658 pop eax

05D1 6603C3 add eax, ebxttt;eax=已读簇数

05D4 665B pop ebx

05D6 EBAA jmp 0582tttt;继续读下一个子运行

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取索引记录的LCN,读索引记录

;入口参数: eax=索引相对扇区偏移 ebx=索引分配表属性首址 ecx=索引记录扇区数 edi=读盘缓冲区

;出口参数: es:edi=索引记录内容

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;检查是否为非常驻属性,属性内容所占簇数是否为0

05D8 06 push es

05D9 1E push ds

05DA 6660 pushadtttt;ebx=索引分配表属性首址

05DC 67807B0801 cmp byte ptr [ebx+08], 01tt;(00:常驻属性;01:非常驻属性)

05E1 0F840300 je 05E8

05E5 E979FB jmp 0161tttt;[ebx+8]不等于01,则转出错



05E8 6683F900 cmp ecx, 00000000ttt;ecx=[0266]=索引记录扇区数

05EC 0F850600 jne 05F6tttt;ecx不等于0 则转05F6

05F0 6661 popad

05F2 90 nop

05F3 1F pop ds

05F4 07 pop es

05F5 C3 ret

;取索引记录的LCN,计算索引记录的扇区偏移,要读的扇区数

05F6 6653 push ebxtttt;ebx=索引分配表属性首址

05F8 6650

push eaxtttt;eax=索引相对扇区偏移

05FA 6651 push ecxtttt;ecx=[0266]=索引记录扇区数

05FC 6657 push editttt;edi=[0242]=1000+R

05FE 06 push es

05FF 6651 push ecx

0601 6633D2 xor edx, edx

0604 660FB60E0D00 movzx ecx, [000D]

060A 66F7F1 div ecxtttt;eax=索引相对扇区偏移/每簇扇区数=索引vcn

060D 6652 push edxtttt;edx=剩余扇区数

060F E8FD03 call 0A0Ftttt;解析非常驻属性数据,取数据起始LCN,该子运行未读簇数

0612 660FB61E0D00 movzx ebx, [000D]

0618 66F7E3 mul ebxtttt;eax=数据起始LCN * 每簇扇区数

061B 665A pop edx

061D 6603C2 add eax, edxttt;eax=索引记录的扇区偏移

0620 6650 push eax

0622 660FB6060D00 movzx eax, [000D]

0628 66F7E1 mul ecxtttt;eax=每簇扇区数 * 该子运行未读簇数

062B 668BD0 mov edx, eaxttt;edx=要读的扇区数

062E 6658 pop eaxtttt;eax=索引记录的扇区偏移

0630 6659 pop ecx

0632 07 pop es

0633 665F pop editttt;edi=[0242]=1000+R

0635 6659 pop ecxtttt;ecx=[0266]=索引记录扇区数

0637 663BCA cmp ecx, edx

063A 0F8D0300 jnl 0641

063E 668BD1 mov edx, ecx

;读索引记录

0641 66A31000 mov dword ptr [0010], eaxtt;[0010]=索引记录的扇区偏移

0645 89160E00 mov [000E], dxttt;[000E]=要读的扇区数

0649 06 push es

064A 1E push ds

064B 6660 pushad

064D 8BDF mov bx, di

064F 83E30F and bx, 000F

0652 8CC0 mov ax, es

0654 66C1EF04 shr edi, 04

0658 03C7 add ax, di

065A 50 push ax

065B 07 pop estttt;es:bx=1000+R

065C E868FA call 00C7tttt;读索引记录

065F 6661 popad

0661 90 nop

0662 1F pop ds

0663 07 pop es

0664 662BCA sub ecx, edxttt;减去已读扇区数

0667 668BDA mov ebx, edxttt;ebx=已读扇区数

066A 668BC2 mov eax, edx

066D 660FB7160B00 movzx edx, word ptr [000B]

0673 66F7E2 mul edxtttt;eax=已读字节数

0676 6603F8 add edi, eaxttt;读盘缓冲区 + 已读字节数

0679 6658 pop eaxtttt;eax=索引相对扇区偏移 + 已读扇区数

067B 6603C3 add eax, ebx

067E 665B pop ebxtttt;ebx=索引分配表属性首址

0680 E965FF jmp 05E8tttt;没读完一个索引,继续读

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;修复校验MFT表(即用修复校验偏移的数据替换扇区结束标志)

;入口参数:edi=MFT表起始地址

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

0683 06 push es

0684 1E push ds

0685 6660 pushad

0687 2667660FB75F04 movzx ebx, word ptr es:[edi+04]t;ebx=修复校验偏移

068E 2667660FB74F06 movzx ecx, word ptr es:[edi+06]t;ecx=修复数据长度

0695 660BC9 or ecx, ecx

0698 0F84C5FA je 0161tttt;为零转出错

069C 6603DF add ebx, edi

069F 6683C302 add ebx, 00000002

06A3 6681C7FE010000 add edi, 000001FE

06AA 6649 dec ecx

06AC 660BC9 or ecx, ecx

06AF 0F841700 je 06CAtttt;cx=0 修复校验完毕

06B3 26678B03 mov ax, word ptr es:[ebx]tt;修复校验数据

06B7 26678907 mov word ptr es:[edi], ax

06BB 6683C302 add ebx, 00000002

06BF 6681C700020000 add edi, 00000200

06C6 6649 dec ecx

06C8 EBE2 jmp 06ACtttt;修复校验下一个数据

06CA 6661 popad

06CC 90 nop

06CD 1F pop ds

06CE 07 pop es

06CF C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读$MFT记录,搜索属性列表属性,分析数据属性内容

;出口参数:

[3800]=$MFT记录起始扇区号 tt[3804]=每个记录所占扇区数

;如果找到属性数据属性,则继续保存属性数据块的首址和大小:

[3808]=第一个属性数据块的扇区偏移 t[380C]=第一个属性数据块的扇区数

……

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

06D0 06 push es

06D1 1E push ds

06D2 6660 pushad

;在[3800]处保存$MFT记录起始扇区号,在[3804]处保存每个记录所占扇区数

06D4 66B801000000 mov eax, 00000001

06DA 66A31E02 mov dword ptr [021E], eaxtt;[021E]=$MFT数据属性内容所占记录数

06DE 66A11A02 mov eax, dword ptr [021A]tt;[021A]=00003000

06E2 6603065202 add eax, [0252]ttt;[0252]=每个记录所占字节数=400

06E7 66A35A02 mov dword ptr [025A], eaxtt;[025A]=00003400

06EB 6603065202 add eax, [0252]ttt;eax=00003800

06F0 66A34A02 mov dword ptr [024A], eaxtt;[024A]=00003800

06F4 66A13000 mov eax, dword ptr [0030]tt;[0030]=$MFT记录起始簇号

06F8 660FB61E0D00 movzx ebx, [000D]ttt;[000D]=每簇扇区数

06FE 66F7E3 mul ebxtttt;EAX=$MFT记录起始簇号X每簇扇区数=$MFT

记录起始扇区号

0701 668B1E4A02 mov ebx, [024A]ttt;ebx=00003800

0706 668907 mov [bx], eaxttt;[3800]=$MFT记录起始扇区号(4字节)

0709 66A31000 mov dword ptr [0010], eaxtt;[0010]=$MFT记录起始扇区号(4字节)(要读的扇区偏移)

070D 83C304 add bx, 0004

0710 66A15602 mov eax, dword ptr [0256]tt;[0256]=每个记录所占扇区数

0714 668907 mov [bx], eaxttt;[3800+4]=每个记录所占扇区数

0717 A30E00 mov word ptr [000E], axtt;[000E]=每个记录所占扇区数(2字节)=要读扇区数=2

071A 83C304 add bx, 0004

071D 66891E4A02 mov [024A], ebxttt;[024A]=00003808

;读$MFT记录,修复校验$MFT记录

0722 668B1E1A02 mov ebx, [021A]ttt;[021A]=00003000(读$MFT记录缓冲区)

0727 1E push dstttt;[0010]=$MFT记录起始扇区号,[000E]=要读扇区数

0728 07 pop estttt;es:bx=读盘缓冲区

0729 E89BF9 call 00C7tttt;读$MFT记录

072C 668BFB mov edi, ebxttt;edi=$MFT记录起始地址

072F E851FF call 0683tttt;修复校验$MFT记录]

;在$MFT记录中搜索属性列表属性

0732 66A11A02 mov eax, dword ptr [021A]tt;ds:[021A]=00003000=$MFT记录起始地址

0736 66BB20000000 mov ebx, 00000020ttt;20000000=属性列表属性

073C 66B900000000 mov ecx, 00000000ttt;属性名长度=0

0742 66BA00000000 mov edx, 00000000ttt;属性名地址=NULL

0748 E846FD call 0491tttt;查找属性列表属性

074B 660BC0 or eax, eax

074E 0F841601 je 0868tttt;没找到属性列表属性,则转0868(直接返回)

;读属性列表属性数据

0752 668BD8 mov ebx, eaxttt;ebx=属性列表属性开始地址

0755 1E push ds

0756 07 pop es

0757 668B3E1602 mov edi, [0216]ttt;es:edi=属性数据缓冲区(edi=0000E000)

075C E8DBFD call 053Atttt;读属性列表属性数据

075F 668B1E1602 mov ebx, [0216]

;在属性列表中搜索数据属性

0764 66813F80000000 cmp dword ptr [bx], 00000080

076B 0F84EB00 je 085Atttt;找到数据属性则转085A

076F 035F04 add bx, [bx+04]ttt;转到下一个属性头

0772 EBF0 jmp 0764tttt;继续找数据属性

;取数据属性内容起始LCN

0774 6653 push ebxtttt;ebx=数据属性头首址

0776 668B4710 mov eax, [bx+10]ttt;包含该属性的MFT记录号

077A 66F72656 mul dword ptr [0256]tt;[0256]=每个记录所占扇区数

077F 6650 push eaxtttt;eax=属性MFT记录扇区偏移

0781 6633D2 xor edx, edx

0784 660FB61E0D00 movzx ebx, [000D]ttt;[000D]=每簇扇区数

078A 66F7F3 div ebxtttt;eax=包含该属性的M

FT记录的起始VCN

078D 6652 push edxtttt;edx=起始簇后的扇区偏移

078F E8DC00 call 086Etttt;取指定MFT记录起始LCN

0792 660BC0 or eax, eax

0795 0F84C8F9 je 0161tttt;要读的起始LCN为0 转出错

0799 668B0E5602 mov ecx, [0256]ttt;[0256]=每个记录所占扇区数

079E 660FB61E0D00 movzx ebx, [000D]

07A4 66F7E3 mul ebxtttt;eax=属性数据的起始LCN X 每簇扇区数=扇区偏移

07A7 665A pop edx

07A9 6603C2 add eax, edxttt;eax=扇区偏移+该属性的起始簇后的扇区偏移=属性数据扇区偏移

07AC 668B1E4A02 mov ebx, [024A]

07B1 668907 mov [bx], eaxttt;[bx]=属性数据扇区偏移

07B4 83C304 add bx, 0004

07B7 660FB6060D00 movzx eax, [000D]

07BD 662BC2 sub eax, edxttt;eax=每簇扇区数 - 起始簇后的扇区偏移=该簇剩余扇区数

07C0 663BC1 cmp eax, ecxttt;ecx=每个记录所占扇区数=2

07C3 0F860300 jbe 07CAtttt;小于等于转07CA

07C7 668BC1 mov eax, ecx

07CA 668907 mov [bx], eaxttt;[bx]=eax=该块的扇区数

;分析当前MFT记录是否跨簇,内容是否连续

07CD 662BC8 sub ecx, eaxttt;ecx=每个记录所占扇区数

07D0 665A pop edxtttt;edx=属性MFT记录扇区偏移

07D2 0F847500 je 084Btttt;分析完一个数据属性,则转084B

07D6 6603C2 add eax, edxttt;eax=下一个数据块扇区偏移

07D9 6650 push eax

07DB 6633D2 xor edx, edx

07DE 660FB61E0D00 movzx ebx, [000D]

07E4 66F7F3 div ebxtttt;eax=下一个数据块起始VCN

07E7 6651 push ecx

07E9 E88200 call 086Etttt;取数据块起始LCN

07EC 6659 pop ecxtttt;ecx=剩余扇区数t

07EE 660BC0 or eax, eax

07F1 0F846CF9 je 0161tttt;LCN为0 转出错

07F5 660FB61E0D00 movzx ebx, [000D]

07FB 66F7E3 mul ebxtttt;eax=属性数据的起始LCN X 每簇扇区数=扇区偏移

07FE 668B1E4A02 mov ebx, [024A]ttt;ebx=[024A]=数据指针

0803 668B17 mov edx, [bx]ttt;edx=[bx]=上一个数据块扇区偏移

0806 83C304 add bx, 0004

0809 660317 add edx, [bx]ttt;edx=上一个数据块扇区偏移+上一个数据块的扇区数

080C 663BD0 cmp edx, eax

080F 0F851500 jne 0828tttt;不相等转0828(本数据块与上一数据块不连续)

0813 660FB6060D00 movzx eax, [000D]

0819 663BC1 cmp eax, ecx

081C 0F860300 jbe 0823

0820 668BC1 mov eax, ecx

0823 660107 add [bx], eaxttt;该块的扇区数+eax

0826 EBA5 jmp 07CDtttt;继续分析

;数据块

与上一数据块不连续,则增加一个数据记录项

0828 83C304 add bx, 0004ttt;分析下一个数据块

082B 66891E4A02 mov [024A], ebx

0830 668907 mov [bx], eaxttt;[bx]=eax=该块数据扇区偏移

0833 83C304 add bx, 0004

0836 660FB6060D00 movzx eax, [000D]

083C 663BC1 cmp eax, ecx

083F 0F860300 jbe 0846

0843 668BC1 mov eax, ecx

0846 668907 mov [bx], eaxttt;[bx]=eax=该块的扇区数t

0849 EB82 jmp 07CDtttt;继续分析

;分析完一个数据属性,准备查找、分析下一个数据属性

084B 83C304 add bx, 0004ttt;缓冲区指针+4

084E 66FF061E02 inc word ptr [021E]ttt;$MFT数据属性内容所占记录数+1

0853 66891E4A02 mov [024A], ebxttt;[024A]缓冲区指针

0858 665B pop ebxtttt;ebx=数据属性头首址

085A 035F04 add bx, [bx+04]ttt;转到下一个属性头

085D 66813F80000000 cmp dword ptr [bx], 00000080

0864 0F840CFF je 0774tttt;找到80数据属性则转0774



0868 6661 popad

086A 90 nop

086B 1F pop ds

086C 07 pop es

086D C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取指定MFT记录起始LCN

;入口参数:eax=指定MFT记录起始VCN

;出口参数:eax=指定MFT记录起始LCN

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;设置读$MFT记录数据属性内容所需变量

086E 668BD0 mov edx, eaxttt;edx=指定MFT记录起始VCN

0871 668B0E1E02 mov ecx, [021E]ttt;[021E]=$MFT数据属性内容所占记录数

0876 668B365A02 mov esi, [025A]ttt;读盘缓冲区=3400

087B 6603365202 add esi, [0252]ttt;[0252]=每个记录所占字节数,esi=3800

0880 6652 push edxtttt;MFT记录起始VCN

0882 6651 push ecxtttt;$MFT数据属性内容所占记录数

0884 6652 push edx

0886 668B1E5A02 mov ebx, [025A]ttt;读盘缓冲区=ebx=3400

088B 668B3E5602 mov edi, [0256]ttt;[0256]=每个记录所占扇区数

;读$MFT记录数据属性内容

0890 668B04 mov eax, [si]ttt;eax=[si]=$MFT记录数据属性内容的扇区偏移

0893 66A31000 mov dword ptr [0010], eaxtt;要读的扇区偏移

0897 83C604 add si, 0004

089A 668B04 mov eax, [si]ttt;eax=[si]=要读的扇区数

089D A30E00 mov word ptr [000E], axtt;[000E]=要读的扇区数

08A0 83C604 add si, 0004

08A3 1E push ds

08A4 07 pop estttt;es:bx=读盘缓冲区

08A5 E81FF8 call 00C7tttt;

读$MFT记录

08A8 662BF8 sub edi, eaxttt;减去已读扇数

08AB 0F840800 je 08B7tttt;读完一个记录转08B7

08AF F7260B00 mul word ptr [000B]ttt;eax=剩余扇数X每扇字节数

08B3 03D8 add bx, axtttt;没读完,读盘缓冲区+已读字节数

08B5 EBD9 jmp 0890tttt;继续读完一个记录

;取指定MFT记录起始LCN

08B7 668B3E5A02 mov edi, [025A]ttt;数据属性内容的MFT记录首址,edi=3400

08BC 1E push ds

08BD 07 pop es

08BE E8C2FD call 0683tttt;修复校验MFT表

08C1 66A15A02 mov eax, dword ptr [025A]tt;eax=数据属性内容的MFT记录首址

08C5 66BB80000000 mov ebx, 00000080ttt;数据属性标志80000000

08CB 66B900000000 mov ecx, 00000000

08D1 668BD1 mov edx, ecx

08D4 E8BAFB call 0491tttt;查找数据属性,返回:eax=数据属性首址

08D7 660BC0 or eax, eax

08DA 0F8483F8 je 0161tttt;eax=0 没找到,转出错

08DE 668BD8 mov ebx, eaxttt;ebx=eax=数据属性首址

08E1 6658 pop eaxtttt;eax=指定MFT记录起始VCN

08E3 6656 push esi

08E5 E82701 call 0A0Ftttt;解析非常驻属性数据,取数据起始LCN,该子运行未读簇数

08E8 665E pop esi

08EA 660BC0 or eax, eax

08ED 0F840500 je 08F6tttt;错误转08F6

08F1 665B pop ebxtttt;平衡堆栈

08F3 665B pop ebx

08F5 C3 retttttt;成功返回 eax=指定MFT记录起始LCN

;没找到 且 ecx >0 则继续读下一个记录

08F6 6659 pop ecxtttt;ecx=$MFT数据属性内容所占记录数

08F8 665A pop edxtttt;edx=指定MFT记录起始VCN

08FA E284 loop 0880tttt;ecx不为0则继续读下一个记录

08FC 6633C0 xor eax, eax

08FF C3 retttttt;失败返回 eax=0

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取MFT记录起始LCN,读MFT记录

;入口参数:eax=MFT记录号X每个记录的扇区数 ecx=要读的扇区数 es:edi=读盘缓冲区

;出口参数: es:edi=MFT记录内容

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;取MFT记录起始LCN

0900 06 push es

0901 1E push ds

0902 6660 pushad

0904 6650 push eaxtttt;eax=MFT记录号X每个记录的扇区数

0906 6651 push ecxtttt;ecx=要读的扇区数

0908 6633D2 xor edx, edx

090B 660FB61E0D00 movzx ebx, [000D]

0911 66F7F3 div ebxtttt;eax=MFT记录号X每个记录的扇区数/每簇扇区数=MFT记录起始VCN

091

4 6652 push edxtttt;edx=相对于MFT记录起始VCN的扇区偏移

0916 6657 push edi

0918 E853FF call 086Etttt;取MFT记录起始LCN

091B 665F pop edi

091D 660BC0 or eax, eax

0920 0F843DF8 je 0161tttt;eax=0 转出错

0924 660FB61E0D00 movzx ebx, [000D]

092A 66F7E3 mul ebx

092D 665A pop edxtttt;edx=相对于MFT记录起始VCN的扇区偏移

092F 6603C2 add eax, edxttt;eax=MFT记录起始LCN X 每簇扇区数 + 扇区偏移

0932 66A31000 mov dword ptr [0010], eaxtt;[0010]=MFT记录的扇区偏移

0936 6659 pop ecxtttt;ecx=要读的扇区数

0938 660FB61E0D00 movzx ebx, [000D]

093E 663BCB cmp ecx, ebx

0941 0F8E1300 jle 0958tttt;要读的扇区数 <= 每簇扇区数,则转0958

;要读的扇区数大于一簇则先读一簇

0945 891E0E00 mov [000E], bxttt;[000E]=每簇扇区数

0949 662BCB sub ecx, ebx

094C 6658 pop eaxtttt;eax=MFT记录号X每个记录的扇区数

094E 6603C3 add eax, ebxttt;eax=MFT记录号X每个记录的扇区数+每簇扇区数

0951 6650 push eax

0953 6651 push ecx

0955 EB14 jmp 096Btttt;没读完转096B

0957 90 nop

;要读的扇区数小于等于一簇则一次读完

0958 6658 pop eax

095A 6603C1 add eax, ecxttt;eax=MFT记录号X每个记录的扇区数+要读的扇区数

095D 6650 push eax

095F 890E0E00 mov [000E], cxttt;[000E]=要读的扇区数

0963 66B900000000 mov ecx, 00000000

0969 6651 push ecx

;读MFT记录

096B 06 push es

096C 6657 push edi

096E 8BDF mov bx, di

0970 83E30F and bx, 000F

0973 8CC0 mov ax, es

0975 66C1EF04 shr edi, 04

0979 03C7 add ax, di

097B 50 push ax

097C 07 pop estttt;es:bx=读盘缓冲区地址

097D E847F7 call 00C7tttt;读MFT记录

0980 665F pop edi

0982 07 pop es

0983 66033E4E02 add edi, [024E]ttt;[024E]=每簇字节数

0988 6659 pop ecx

098A 6658 pop eax

098C 6683F900 cmp ecx, 00000000

0990 0F8F70FF jg 0904tttt;没读完继续读

0994 6661 popad

0996 90 nop

0997 1F pop ds

0998 07 pop es

0999 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读MFT记录

;入口参数: eax=MFT记录号

;出口参数: es:edi=MFT记录内容

;<

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

099A 06 push esttt;eax=MFT记录号

099B 1E push ds

099C 6660 pushadttt[0256]=每个记录所占扇区数=2

099E 66F7265602 mul dword ptr [0256]t;eax=MFT记录号X每个记录的扇区数

09A3 668B0E5602 mov ecx,[0256]tt;ecx=2=要读的扇区数

09A8 E855FF tt call 0900 ttt;取MFT记录起始LCN,读MFT记录

09AB E8D5FCtt call 0683 ttt;修复校验MFT表

09AE 6661 popad

09B0 90 nop

09B1 1F pop ds

09B2 07 pop es

09B3 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读索引记录

;入口参数: eax=索引记录号

;出口参数: es:edi=索引记录内容

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

09B4 06 push es

09B5 1E push ds

09B6 6660 pushad

09B8 66F7266602 mul dword ptr [0266]t;[0266]=每个索引记录扇区数

09BD 668B1E3202 mov ebx,[0232]tt;[0232]=索引分配表属性首址

09C2 668B0E6602 mov ecx, [0266]tt;ecx=[0266]=索引记录扇区数

09C7 1E push ds

09C8 07 pop es

09C9 668B3E4202 mov edi, [0242]tt;edi=[0242]=1000+R

09CE E807FC call 05D8ttt;读索引记录

09D1 E8AFFC call 0683ttt;修复校验MFT表

09D4 6661 popad

09D6 90 nop

09D7 1F pop ds

09D8 07 pop es

09D9 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;测试索引记录号是否可用

;入口参数: eax=索引记录号

;出口参数: CF=0t成功 eax=要找的索引记录号; CF=1 失败

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

09DA 6650 push eaxttt;eax=索引记录数

09DC 6653 push ebx

09DE 6651 push ecx

09E0 668B1E4602 mov ebx, [0246]tt;ebx=[0246]=索引位图属性数据首址

09E5 668BC8 mov ecx, eaxtt;ecx=索引记录号

09E8 66C1E803 shr eax, 03ttt;eax=索引记录号的字节偏移

09EC 6683E107 and ecx, 00000007tt;ecx=索引记录号的位偏移

09F0 6603D8 add ebx, eaxtt;ebx=索引记录号对应位图数据的字节偏移

09F3 66B801000000 mov eax, 00000001

09F9 66D3E0 shl eax, cl tt;计算索引记录号对应的位

09FC 678403 test byte ptr [ebx], al

09FF 0F840400 je 0A07ttt;ZF=1 索引记录号不

可用,转0A07

0A03 F8 clc

0A04 EB02 jmp 0A08ttt;ZF=0 索引记录号可用,转0A08

0A06 90 nop

0A07 F9 stc

0A08 6659 pop ecx

0A0A 665B pop ebx

0A0C 6658 pop eax

0A0E C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;解析非常驻属性数据,取数据起始LCN,该子运行未读簇数

;入口:eax=数据起始VCN ebx=数据属性头首址址

;返回:eax=数据起始LCN ecx=该子运行未读簇数

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

0A0F 67807B0801 cmp byte ptr [ebx+08], 01tt;(00:常驻属性;01:非常驻属性)

0A14 0F840400 je 0A1C

0A18 662BC0 sub eax, eax

0A1B C3 ret

;检查子运行开始VCN和结束VCN是否正确

0A1C 67668D7310 lea esi, dword ptr [ebx+10]tt;esi=子运行开始VCN地址

0A21 67668B5608 mov edx, dword ptr [esi+08]tt;edx=子运行结束VCN

0A26 663BC2 cmp eax, edxttt;eax=数据起始VCN

0A29 0F870B00 ja 0A38tttt;大于转0A38(已读完)

0A2D 67668B16 mov edx, dword ptr [esi]tt;edx=子运行开始VCN

0A31 663BC2 cmp eax, edx

0A34 0F830400 jnb 0A3Ctttt;不小于转0A3C(继续读)

0A38 662BC0 sub eax, eax

0A3B C3 ret

;检查是否为非常驻属性,取子运行起始簇号、所占簇数

0A3C 67035E10 add bx, word ptr [esi+10]tt;[esi+10]=属性数据起始字节(相对于属性头起始地址)

0A40 662BF6 sub esi, esi

0A43 67803B00 cmp byte ptr [ebx], 00tt;[ebx]=子运行起始字节

0A47 0F843E00 je 0A89tttt;为 0 转0A89

0A4B E88100 call 0ACFtttt;取子运行起始簇号

0A4E 6603F1 add esi, ecxttt;esi=子运行起始簇号

0A51 E83900 call 0A8Dtttt;取子运行所占簇数

0A54 6603CA add ecx, edxttt;ecx=子运行所占簇数 + 子运行开始VCN =下一个子运行开始VCN

0A57 663BC1 cmp eax, ecxttt;eax=数据起始VCN

0A5A 0F8C2100 jl 0A7Ftttt;低于转0A7F(该子运行未读完,转读该子运行)

;取下一个子运行起始地址

0A5E 668BD1 mov edx, ecxttt;edx=下一个子运行开始VCN

0A61 6650 push eax

0A63 67660FB60B movzx ecx, byte ptr [ebx]

0A68 668BC1 mov eax, ecx

0A6B 6683E00F and eax, 0000000Fttt;eax=子运行簇数所占字节数

0A6F 66C1E904 shr ecx, 04tttt;ecx=子运行起始簇号所占字节数

0A73 6603D9 add ebx, ecx

0A76 6603D8 add ebx, eax

0A79 6643 inc ebxt

;ebx=下一个子运行起始地址

0A7B 6658 pop eax

0A7D EBC4 jmp 0A43tttt;解析下一个子运行



0A7F 662BC8 sub ecx, eaxttt;ecx=下一个子运行开始VCN-数据起始VCN=该子运行未读簇数

0A82 662BC2 sub eax, edxttt;eax=数据起始VCN-该子运行开始VCN=该子运行已读簇数

0A85 6603C6 add eax, esittt;eax=数据起始LCN

0A88 C3 ret



0A89 662BC0 sub eax, eax

0A8C C3 ret

;取子运行簇数所占字节数

0A8D 662BC9 sub ecx, ecx

0A90 678A0B mov cl, byte ptr [ebx]tt;[ebx]=属性数据起始字节

0A93 80E10F and cl, 0Ftttt;ecx=子运行簇数所占字节数

0A96 6683F900 cmp ecx, 00000000

0A9A 0F850400 jne 0AA2tttt;ecx不等于0 转0AA2

0A9E 662BC9 sub ecx, ecx

0AA1 C3 ret

;取子运行所占簇数

0AA2 6653 push ebxtttt;ebx=子运行起始地址

0AA4 6652 push edx

0AA6 6603D9 add ebx, ecx

0AA9 67660FBE13 movsx edx, byte ptr [ebx]tt;edx=子运行簇数最高位字节

0AAE 6649 dec ecx

0AB0 664B dec ebx

0AB2 6683F900 cmp ecx, 00000000

0AB6 0F840D00 je 0AC7

0ABA 66C1E208 shl edx, 08

0ABE 678A13 mov dl, byte ptr [ebx]

0AC1 664B dec ebx

0AC3 6649 dec ecx

0AC5 EBEB jmp 0AB2

0AC7 668BCA mov ecx, edxttt;ecx=edx=子运行所占簇数

0ACA 665A pop edx

0ACC 665B pop ebx

0ACE C3 ret

;取子运行簇数、簇号所占字节数

0ACF 6653 push ebxtttt;ebx=子运行起始地址

0AD1 6652 push edx

0AD3 662BD2 sub edx, edx

0AD6 678A13 mov dl, byte ptr [ebx]tt;dl=子运行首字节

0AD9 6683E20F and edx, 0000000Fttt;edx=子运行簇数所占字节数

0ADD 662BC9 sub ecx, ecx

0AE0 678A0B mov cl, byte ptr [ebx]

0AE3 C0E904 shr cl, 04tttt;ecx=子运行起始簇号所占字节数

0AE6 6683F900 cmp ecx, 00000000

0AEA 0F850800 jne 0AF6

0AEE 662BC9 sub ecx, ecx

0AF1 665A pop edx

0AF3 665B pop ebx

0AF5 C3 ret

;取子运行起始簇号

0AF6 6603DA add ebx, edxttt;ebx=属性数据起始地址

0AF9 6603D9 add ebx, ecx

0AFC 67660FBE13 movsx edx, byte ptr [ebx]tt;edx=子运行簇号最高位字节

0B01 6649 dec ecxtttt;子运行簇号所占字节数-1

0B03 664B dec ebx

0B05 6683F900 cmp ecx, 00000000

0B09 0F840D00 je 0B1A

0B0D

性首址是否为有0

0B78 66A13202 mov eax, dword ptr [0232]tt;[0232]=索引分配表属性首址

0B7C 660BC0 or eax, eax

0B7F 0F850800 jne 0B8B

0B83 6659 pop ecx

0B85 6659 pop ecx

0B87 6633C0 xor eax, eax

0B8A C3 ret

;计算索引记录数

0B8B 668B163202 mov edx, [0232]ttt;edx=[0232]=索引分配表属性首址

0B90 67668D5210 lea edx, dword ptr [edx+10]tt;edx=开始VCN地址

0B95 67668B4208 mov eax, dword ptr [edx+08]tt;eax=结束VCN

0B9A 6640 inc eaxtttt;索引分配表属性所占簇数

0B9C 668B1E4E02 mov ebx, [024E]ttt;ds:[024E]=每簇字节数

0BA1 66F7E3 mul ebxtttt;eax=索引分配表属性数据所占字节数

0BA4 6633D2 xor edx, edx

0BA7 66F7365E02 div dword ptr [025E]tt;[025E]=索引记录大小

0BAC 6650 push eax tttt;eax=索引记录数

;测试指定索引记录号是否可用

0BAE 6658 pop eaxtttt;eax=索引记录数

0BB0 660BC0 or eax, eax

0BB3 0F843000 je 0BE7

0BB7 6648 dec eaxtttt;eax=索引记录号

0BB9 6650 push eax

0BBB E81CFE call 09DAtttt;测试指定索引记录号是否可用

0BBE 72EE jb 0BAEtttt;CF=1不对应转0BAE,继续找

;搜索索引项,查找指定文件

0BC0 E8F1FD call 09B4tttt;取索引记录起始LCN,读索引记录

0BC3 665A pop edx

0BC5 6659 pop ecx

0BC7 665B pop ebx

0BC9 6653 push ebxtttt;ebx=文件名首址

0BCB 6651 push ecxtttt;ecx=文件名长度

0BCD 6652 push edx

0BCF 66A14202 mov eax, dword ptr [0242]tt;eax=索引记录头首址

0BD3 67668D4018 lea eax, dword ptr [eax+18]tt;eax=索引记录头首址+18=索引项的偏移地址

0BD8 E813F9 call 04EEtttt;搜索索引项,查找指定文件

0BDB 660BC0 or eax, eax

0BDE 74CE je 0BAEtttt;没找到指定文件,继续找上一个索引记录

0BE0 6659 pop ecx

0BE2 6659 pop ecx

0BE4 6659 pop ecx

0BE6 C3 retttttt;找到则eax=文件索引项首址

;没找到指定文件,返回0

0BE7 6659 pop ecx

0BE9 6659 pop ecx

0BEB 6633C0 xor eax, eax

0BEE C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<]

;读根目录,搜索指定属性

;入口参数: eax=要查找的属性 ecx=缓冲区首址

;出口参数: eax=指定属性首址

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;

读根目录的MFT记录

0BEF 6651 push ecxtttt;ecx=缓冲区首址

0BF1 6650 push eaxtttt;eax=要查找的属性

0BF3 66B805000000 mov eax, 00000005

0BF9 1E push ds

0BFA 07 pop es

0BFB 668BF9 mov edi, ecxttt;edi=缓冲区首址

0BFE E899FD call 099Atttt;读根目录的MFT记录

;查找索引根目录属性

0C01 668BC1 mov eax, ecxttt;eax=根目录MFT记录首址

0C04 665B pop ebxtttt;ebx=要查找的属性

0C06 6653 push ebx

0C08 660FB70E0C02 movzx ecx, word ptr [020C]tt;ecx=[020C]=0004(属性名长度)

0C0E 66BA0E020000 mov edx, 0000020Ettt;edx=属性名首址($I30)

0C14 E87AF8 call 0491tttt;查找索引根目录属性(返回:eax=属性首址)

0C17 665B pop ebxtttt;ebx=要查找的属性

0C19 6659 pop ecxtttt;ecx=MFT记录首址

0C1B 660BC0 or eax, eax

0C1E 0F852F00 jne 0C51tttt;找到转0C51(退出)

;在属性列表中查找索引根目录属性

0C22 668BC1 mov eax, ecxttt;eax=MFT记录首址

0C25 668BCB mov ecx, ebxttt;ecx=要查找的属性

0C28 6650 push eax

0C2A 6653 push ebx

0C2C E82300 call 0C52tttt;在属性列表中搜索指定属性

0C2F 665B pop ebxtttt;ebx=要查找的属性

0C31 665F pop editttt;edi=MFT记录首址

0C33 660BC0 or eax, eax

0C36 0F841700 je 0C51tttt;没找到索引根目录属性,则转0C51

0C3A 1E push dst

0C3B 07 pop estttt;es:edi=属性数据缓冲区,eax=MFT记录号

0C3C E85BFD call 099Atttt;读索引根目录属性的MFT记录ttt

0C3F 668BC7 mov eax, edittt;eax=MFT记录首址

0C42 660FB70E0C02 movzx ecx, word ptr [020C]tt;ecx=[020C]=0004=属性长度

0C48 66BA0E020000 mov edx, 0000020Ettt;edx=属性名地址($I30)

0C4E E840F8 call 0491tttt;查找索引根目录属性(返回:eax=属性首址)

0C51 C3 ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;在属性列表中搜索指定属性

;入口参数: eax=MFT记录首址,ecx=要找的属性

;出口参数: eax=包含指定的MFT记录号

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;读取属性列表数据

0C52 6651 push ecxtttt;ecx=要找的属性 eax=MFT记录首址

0C54 66BB20000000 mov ebx, 00000020

0C5A 66B900000000 mov ecx, 00000000

0C60 66BA00000000 mov edx, 00000000

0C66 E828F8 call 0491tttt;查找属性列表属性(返回:eax=属性首址)

0C69 660BC0

更多推荐

ntldr is missing