📄 用ntldr加载进dos.txt
字号:
pop ecx
ret
FindFile90:
; 文件没找到,失败回.
pop ecx
pop ecx
xor eax,eax
ret
FindFile endp
;******************************************************************************************
;IsBlockInUse: 索引分配块用来检查索引位图.
;入口: eax=块号
IsBlockInUse proc
push eax
push ebx
push ecx
mov ebx, IndexBitmapBuffer
mov ecx, eax
shr eax, 03h ;eax=字节号
and ecx, 00000007h ;ecx=在字节的位号
add ebx, eax ;ebx -> byte to test
mov eax, 00000001h
shl eax, cl ;eax=mask
test byte ptr [ebx], al
je IBU10
clc ;Block is not in use.
jmp IBU20
IBU10:
stc ; Block is in use.
IBU20:
pop ecx
pop ebx
pop eax
ret
IsBlockInUse endp
;*********************************************************************
;LcnFromMappingPair:
;入口: ebx->映射字节数
;出口: ecx->LCN来自映射
LcnFromMappingPair proc
push ebx
push edx
sub edx, edx
mov dl, byte ptr [ebx] ;edx = count byte
and edx, 0000000Fh ;edi = v
sub ecx, ecx
mov cl, byte ptr [ebx]
shr cl, 04h ;ecx = l
cmp ecx, 00000000
jne LFMP5
sub ecx, ecx
pop edx
pop ebx
ret
LFMP5:
add ebx, edx ;ebx->压缩的VCN前个字节
add ebx, ecx ;ebx->LCN最字节
movsx edx, byte ptr [ebx]
dec ecx
dec ebx
LFMP10:
cmp ecx, 00000000
je LFMP20
shl edx, 08h
mov dl, byte ptr [ebx]
dec ebx
dec ecx
jmp LFMP10
LFMP20:
mov ecx, edx
pop edx
pop ebx
ret
LcnFromMappingPair endp
;********************************************************
;LoadIndexFrs: 根据索引类型代码定位并装入相应的FRS
;入口: eax=索引类型代码 ecx->要装入的FRS缓冲
;出口: eax->在FRS缓冲的偏移(为0失败)
LoadIndexFrs proc
push ecx
push eax
mov eax, 00000005h ;设置为根目录索引代码
push ds
pop es
mov edi, ecx ;es:edi装入的缓冲
call ReadFrs
mov eax, ecx ;搜索到FRS
pop ebx
push ebx
movzx ecx, index_name_length ;属性名长度
mov dx, offset index_name ;mov edx,offset index_name
call LocateAttributeRecord
pop ebx
pop ecx
or eax, eax
jne LoadIndexFrs$Exit ;如果在目录找到,返回.
; 如果在当前FRS没有找到,则搜索属性列表.
mov eax, ecx
mov ecx, ebx
push eax
push ebx
call SearchAttrList
pop ebx
pop edi
or eax, eax
je LoadIndexFrs$Exit
push ds
pop es
call ReadFrs
mov eax, edi
movzx ecx, index_name_length
mov dx, offset index_name ;mov edx,offset index_name
call LocateAttributeRecord
LoadIndexFrs$Exit:
ret
LoadIndexFrs endp
;********************************************************************************
;LocateAttributeRecord: 查找一个属性在记录在一个FRS
;入口: eax->FRS ebx=属性代码
; ecx=属性名长度 edx->属性名
;出口: eax->属性记录(0表示未找到)
LocateAttributeRecord proc
add ax, word ptr [eax+14h] ;eax->下一个属性记录
lar10:
cmp dword ptr [eax], 0FFFFFFFFh ;属性记录结束
je lar99
cmp dword ptr [eax], ebx
jne lar80 ;比较属性代码
or ecx, ecx ;属性名长度不为0时
jne lar20
cmp byte ptr [eax+09h], 00 ;比较属性名长度
jne lar80
ret
lar20:
cmp cl, byte ptr [eax+09h]
jne lar80
mov esi, eax
add si, word ptr [eax+0Ah] ;esi->属性名保存缓冲
call UpcaseName
push ecx
push ds
pop es
mov edi, edx
repz cmpsw ;比较属性名
pop ecx
jne lar80
ret
lar80:
; 到下一个属性记录
cmp dword ptr [eax+04h], 00000000
je lar99 ;属性记录为0退出
add eax, dword ptr [eax+04h] ;eax->下一个属性记录
jmp lar10 ;继续查找
lar99:
; 未找到,失败返回
sub eax, eax
ret
LocateAttributeRecord endp
;********************************************************************
;LocateIndexEntry: 在一个文件名索引查找一个索引入口
;入口: eax->索引头 ebx->要查找文件名 ecx=文件名长度
;出口: eax->索引入口(为0失败)
LocateIndexEntry proc
mov esi, ebx
call UpcaseName
add eax, dword ptr [eax] ;eax->第一个索引入口
lie10:
test word ptr [eax+0Ch], 0002h ;索引入口结束
jne lie99
lea edx, dword ptr [eax+10h] ;edx -> FILE_NAME属性值
cmp cl, byte ptr [edx+40h] ;比较文件名长度
jne lie80
lea esi, dword ptr [edx+42h] ;esi->文件名缓冲
call UpcaseName
push ecx
push ds
pop es
mov edi, ebx
repz cmpsw ;比较文件名
pop ecx
jne lie80
ret
lie80:
cmp word ptr [eax+08h], 0000 ;入口长度为0退出
je lie99
add ax, word ptr [eax+08h] ;eax->下一个入口
jmp lie10 ;继续查找
lie99:
; 没找到失败返回
xor eax, eax
ret
LocateIndexEntry endp
;*************************************************
;MultiSectorFixup: 修正读磁盘结构.....
;入口: es:edi=缓冲
MultiSectorFixup proc
push es
push ds
pushad
movzx ebx, word ptr es:[edi+04h];ebx=更新偏移
movzx ecx, word ptr es:[edi+06h];ecx=更新偏移
or ecx, ecx
je ErrorExit
add ebx, edi
add ebx, 00000002h
add edi, 000001feh ;SEQUENCE_NUMBER_STRIDE - 2
dec ecx
MSF10:
or ecx, ecx
je MSF30
mov ax, word ptr es:[ebx]
mov word ptr es:[edi], ax
add ebx, 00000002h
add edi, 00000200h ;SEQUENCE_NUMBER_STRIDE
dec ecx
jmp MSF10
MSF30:
popad
pop ds
pop es
ret
MultiSectorFixup endp
;*************************************************************
;ReadClusters: 在磁盘读一个运行簇
;入口: eax=要读的LCN edx=要读的簇 es:edi->缓冲
;注意: 真正要读的开始扇区LBA)=SectorBase+HiddenSectors
ReadClusters proc
push es
push ds
pushad
mov ebx, edx
movzx ecx, SectorsPerCluster
mul ecx ;转换LCN到扇区编号
mov SectorBase, eax ;保存扇区编号(LBA)
mov eax, ebx
mul ecx
mov SectorCount,ax ;要读的扇区数
; 将es:edi参数转换成调用int13h时的es:ebx
mov ebx,edi
call DoRead ;调用磁盘读
popad
pop ds
pop es
ret
ReadClusters endp
;**************************************************
;ReadFrs: 读一个FRS
;入口: eax=FRS号 es:edi=缓冲
ReadFrs proc
push es
push ds
pushad
mul SectorsPerFrs ;eax=在MFT数据属性的扇区号
mov ecx, SectorsPerFrs
call ReadMftSectors
call MultiSectorFixup
popad
pop ds
pop es
ret
ReadFrs endp
;*******************************************************************
;ReadIndexBlock: 在根目录读一个索引块
;入口: eax=块号
ReadIndexBlock proc
push es
push ds
pushad
mul SectorsPerIndexBlock ;eax=要读的第一个VBN
mov ebx, IndexAllocation ;ebx->$INDEX_ALLOCATION属性
mov ecx, SectorsPerIndexBlock ;ecx=要读的扇区
push ds
pop es
mov edi, IndexBlockBuffer ;es:edi->索引块缓冲
call ReadIndexBlockSectors
call MultiSectorFixup
popad
pop ds
pop es
ret
ReadIndexBlock endp
;**********************************************************************
;ReadIndexBlockSectors: 读扇区来自一个索引分配属性
;入口: eax=要读的开始VBN
; ebx->属性
; ecx=要读的扇区数
; es:edi=缓冲
;注意: 真正要读的开始扇区LBA)=SectorBase+HiddenSectors
ReadIndexBlockSectors proc
push es
push ds
pushad
cmp byte ptr [ebx+08h], 01h ;.ATTR_FormCode, NONRESIDENT_FORM
je ReadIBS_10
; 这是个常驻属性
jmp ErrorExit
ReadIBS_10:
cmp ecx, 00000000
jne ReadIBS_20
; 没有要读的,返回.
popad
pop ds
pop es
ret
ReadIBS_20:
push ebx
push eax ;当前VBN
push ecx
push edi
push es
; VBN转换到VCN:用VBN除以每簇扇区数 余数X
; VCN转换到LCN:通过属性里面的映射
; LCN转换到LBN:用LCN乘以每簇扇区数 加上X
; VBN除以每簇扇区数,余数表示其余扇区在簇里
push ecx ;保存剩余扇区数
xor edx, edx
movzx ecx, SectorsPerCluster;ecx=每簇扇区数
div ecx ;eax=VCN
push edx ;保存余数
call ComputeLcn ;获取VCN的LCN.返回eax=LCN ecx=剩余簇
movzx ebx, SectorsPerCluster
mul ebx ;eax=LBN簇
pop edx
add eax, edx
push eax ;保存我们的LBN
movzx eax, SectorsPerCluster
mul ecx ;eax=在扇区的剩余运行长度
mov edx, eax ;剩余运行长度
pop eax ;eax=LBN
pop ecx ;要读的剩余扇区
pop es
pop edi
pop ecx
cmp ecx, edx
jnl ReadIBS_30
; 运行长度高于剩余的.只读剩余
mov edx, ecx
ReadIBS_30:
mov SectorBase,eax
mov SectorCount,dx
; 将es:edi参数转换成调用int13h时的es:ebx
push ebx
mov ebx,edi
call DoRead
pop ebx
sub ecx, edx ;修正要读的剩余扇区
mov ebx, edx
mov eax, edx
movzx edx, BytesPerSector
mul edx
add edi, eax ;修正缓冲以备下一个读的扇区
pop eax
add eax, ebx ;修正要读的VBN
pop ebx
jmp ReadIBS_10
ReadIndexBlockSectors endp
;***********************************************
;ReadMftSectors: 读扇区来自MFT
;入口: eax=开始VBN ecx=要读的扇区数
; es:edi=缓冲区
ReadMftSectors proc
push es
push ds
pushad
RMS$Again:
push eax ;保存开始VBN
push ecx
xor edx, edx
; VBN除以SectorsPerCluster得到VCN
movzx ebx, SectorsPerCluster
div ebx ;eax=VCN
push edx ;保存剩余的
push edi
call ComputeMftLcn ;eax=LCN
pop edi
or eax, eax ;LCN=0
je ErrorExit
movzx ebx, SectorsPerCluster
mul ebx ;eax=开始LBN簇
pop edx ;edx=剩余扇区
add eax, edx ;eax=LBN
mov SectorBase,eax
pop ecx ;要读的扇区数
movzx ebx, SectorsPerCluster
cmp ecx, ebx
jle RMS10
mov SectorCount,bx ;这时读一个簇
sub ecx, ebx ;ecx=要读的剩余扇区数
pop eax ;eax=VBN
add eax, ebx ;VBN+=要读的扇区数
push eax ;保存下一个VBN
push ecx ;剩余扇区数
jmp RMS20
RMS10:
pop eax ;eax=VBN
add eax, ecx ;VBN += sectors this read
push eax
mov SectorCount,cx
mov ecx, 00000000
push ecx ;保存剩余的
RMS20:
; 将es:edi参数转换成调用int13h时的es:ebx
mov ebx,edi
call DoRead
add edi, BytesPerCluster
pop ecx
pop eax
cmp ecx, 00000000
jg RMS$Again
popad
pop ds
pop es
ret
ReadMftSectors endp
;****************************************************************
;ComputeMftLcn: 算出MFT一个簇的LCN
;入口: eax=VCN
;出口: eax=LCN(0,失败)注意:与调试的win2k版本代码不同
ComputeMftLcn proc
mov edx, eax
mov ecx, SegmentsInMft ;ecx=要搜索的文件记录号(FRS)
mov eax, MftFrs ;eax->要搜索的第一个FRS
MftLcn10:
push edx
push eax
push ecx
push edx
mov ebx, 00000080h ;$DATA
mov ecx, 00000000
mov edx, ecx
call LocateAttributeRecord
; eax->$DATA属性
or eax, eax
je ErrorExit ;这个文件记录里没有$DATA属性
mov ebx, eax ;ebx->属性
pop eax ;eax=VCN
call ComputeLcn
or eax, eax
je MftLcn20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -