虚拟软盘镜像..以及在ntfs下查找文件....
.386p
CSEG SEGMENT USE16
ASSUME CS:CSEG,DS:CSEG,ES:CSEG
START PROC
CodeStart:
;************************************************************************
;主引导程序第一个扇区:
;完成将代码拷贝到2000:0处,接着转到该处继续执行.......
BOOTCodeSector1 proc
org 0 ;第一个扇区开始于0
cli
xor ax,ax
mov ss,ax ;设置新堆栈0:2000h
mov sp,2000h
sti
push cs
pop ds ;ds=cs
mov ax,2000h
mov es,ax ;es=2000h
mov si,offset CodeStart ;ds:si->CodeStart
xor di,di ;es:di->新缓冲区
; 注意:拷贝代码长度2000h=16*512,这是因为Ntldr加载多扇区启动时.
; 要求的最小度为16个扇区长度,小于16个扇区时只加载1个扇区..
mov cx,2000h ;不用计算代码长度..
cld ;我们代码没这么长...
repz movsb ;把代码拷贝到2000:0处
push es
push offset BOOTCode10 - offset CodeStart
retf ;转到BOOTStart处执行
;***************************************************************************
;完成在NTFS卷下查找文件ghost.img(这是个可启动的软盘镜像文件)找到加载启动它..
BOOTCode10:
jmp BOOTCode20
file_name_length dw 9
file_name dw 'G', 'H', 'O', 'S', 'T','.','I','M','G'
filenamebuffer db 256 dup (0)
BOOTCode20:
push cs
pop ds
call NTFSMain ;安装NTFS参数等
movzx ecx, file_name_length
mov ax, offset file_name
call FindFile ;查找文件
or eax, eax
je BOOTCode99 ;没找到文件退出
mov ebp,0 ;获取开始LBA
call GetFileDATAorLBA ;eax=开始LBA
or eax, eax
je BOOTCode99 ;失败退出
mov ebp,eax ;ebp=开始LBA
call HardDiskImageVirtualFloppy
xor ax,ax
mov es,ax
mov bx,7c00h
mov ax,0201h
mov cx,1
mov dx,0
int 13h
push es
push 7c00h
retf ;启动可启动软盘镜像
BOOTCode99:
int 18h ;出错退出
org 1ffh ;第一个扇区结束于1ffh
BOOTCodeSector1 endp
;***************************************************************
;引导程序第二个扇区:无条件转到第一个扇区开始处执行.....
;注意:Ntldr加载长于一个扇区时:要求1:全长代码不小于2000h(也就是
; 16个扇区长),要求2:必须定义第二个扇区,而且第二个扇区的开始处
; 代码要无条件转到第一个扇区开始处执行.分析得来!没具体资料...
BOOTCodeSector2 proc
org 200h ;第二个扇区开始于200h
jmp BOOTCodeSector1
org 3ffh ;第二个扇区结束于3ffh
BOOTCodeSector2 endp
;****************************************************************
;注意:其他代码从这里开始,Ntldr要求所有代度长度最低要占用16个扇区.
; 我们这里不足尾部填0.达到Ntldr要求长度....
org 400h
;******************************************************************************
;******************************************************************************
;******************************************************************************
;NTFSDOSAPI: NTFS文件操作DOS系统调用接口!
;入口: eax=要调用的API号 以及相应API参数
;出口: eax=零严重错误返回 以及相应API返回
NTFSDOSAPI proc
;push cs
;pop ds
;jmp FoundNTFSAPI
;*******************************************************************
;可以把NTFS封装成公共接口.安装成中断调用也可以..定义子函数入口偏移
NTFSAPIStart:
dw offset NTFSMain
dw offset FindFile
dw offset ReadFrs
;*********************************************************************
;杂乱的定义.注意:默认操作的是C盘.....
index_name dw '$', 'I', '3', '0'
index_name_length dw 4
DriveNumber db 80h ;默认操作的是C盘
SectorBase dd ? ;操作扇区开始LBA
SectorCount dw ? ;操作的扇区数
NtfsSP dw ? ;保存堆栈
NtfsRET dw ? ;保存返回偏移
NtfsCS dw ? ;保存返回段值
NTFSFlags dw ? ;保存标志寄存器
;*******************************************************
;NTFS分区BPB这里需要的参数,以及计算机出来的参数...
BytesPerSector dw ? ;每扇区字节数
SectorsPerCluster db ? ;每簇扇区数
HiddenSectors dd ? ;隐藏扇区数
MftStartLcn dd ? ;MFT开始LCN
ClustersPerFrs dd ? ;每文件记录簇数
BytesPerCluster dd ? ;每簇字节数
BytesPerFrs dd ? ;每文件记录段字节数
SectorsPerFrs dd ? ;每文件记录段扇区数
BytesPerIndexBlock dd ? ;在根索引每索引块字节数
ClustersPerIndexBlock dd ? ;在根索引每索引块簇数
SectorsPerIndexBlock dd ? ;在根索引每索引块扇区数
;********************************************************
;NTFS初始化要用的文件记录文件等缓冲及地址
AttrList dd 0e000h;属性链表缓冲首址
MftFrs dd 03000h;第一个MFT文件记录首址
SegmentsInMft dd ? ;文件记录号在MFT数据属性记录
RootIndexFrs dd ? ;根索引文件记录地址
AllocationIndexFrs dd ? ;分配索引文件记录地址
BitmapIndexFrs dd ? ;位图索引文件记录地址
IndexRoot dd ? ;根索引$INDEX_ROOT属性地址
IndexAllocation dd ? ;根索引$INDEX_ALLOCATION属性地址
IndexBitmap dd ? ;根索引$BITMAP属性地址
FileFrs dd ? ;要查找的文件的文件记录地址
IndexBlockBuffer dd ? ;当前索引缓冲区地址
IndexBitmapBuffer dd ? ;索引位图缓冲区地址
NextBuffer dd ? ;在缓冲区的下一个空闲缓冲区
;数据定义结束.
;***************************************************************
;***************************************************************
;Main: 获取设置NTFS常用的参数,安装NTFS要用到的文件记录...
; 如:每簇扇区数,每文件记录扇区数,,如:根目录索引记录.
NTFSMain proc
push ds
pushad
push cs
pop ds
mov ax,0201h
mov ebx,MftFrs
mov cx,1
mov dh,01
mov dl,DriveNumber
int 13h ;读NTFS引导记录(LBA:3fh)
cmp dword ptr [bx+3],5346544eh ;是NTFS?
jnz ErrorExit
; 获取NTFS资料.......
mov ax,[bx+0bh]
mov BytesPerSector,ax
mov al,[bx+0dh]
mov SectorsPerCluster,al
mov eax,[bx+1ch]
mov HiddenSectors,eax
mov eax,[bx+30h]
mov MftStartLcn,eax
mov eax,[bx+40h]
mov ClustersPerFrs,eax
movzx eax, BytesPerSector ;eax=每扇区字节数
movzx ebx, SectorsPerCluster ;ebx=每簇扇区数
mul ebx
mov BytesPerCluster,eax ;eax=每簇字节数
mov ecx, ClustersPerFrs
cmp cl, 00
jg NTFSMain1
neg cl
mov eax, 00000001
shl eax, cl ;eax=每FRS字节数
jmp NTFSMain2
NTFSMain1:
mov eax, BytesPerCluster
mul ecx ;eax=每FRS字节数
NTFSMain2:
mov BytesPerFrs,eax
movzx ebx,BytesPerSector
xor edx, edx
div ebx
mov SectorsPerFrs,eax
call SetupMft
; 下面是加载各个属性
mov ecx, NextBuffer
mov RootIndexFrs, ecx
add ecx, BytesPerFrs
mov AllocationIndexFrs,ecx
add ecx, BytesPerFrs
mov BitmapIndexFrs,ecx
add ecx, BytesPerFrs
mov FileFrs, ecx
add ecx,BytesPerFrs
mov IndexBlockBuffer,ecx
mov eax, 00000090h ;$INDEX_ROOT
mov ecx, AllocationIndexFrs
call LoadIndexFrs
or eax, eax
je ErrorExit
mov IndexRoot,eax
mov eax, 000000A0h ;$INDEX_ALLOCATION
mov ecx, AllocationIndexFrs
call LoadIndexFrs
mov IndexAllocation, eax
mov eax, 000000B0h ;$BITMAP
mov ecx, BitmapIndexFrs
call LoadIndexFrs
mov IndexBitmap,eax
mov eax,IndexRoot
or eax, eax
je ErrorExit
cmp byte ptr [eax+08h], 00
jne ErrorExit
; eax -> $INDEX_ROOT 属性记录
lea edx, dword ptr [eax+10h] ;edx->常驻信息
add ax, word ptr [edx+04h] ;eax -> value of $INDEX_ROOT
movzx ecx, byte ptr [eax+0Ch]
mov ClustersPerIndexBlock,ecx
mov ecx, dword ptr [eax+08h]
mov BytesPerIndexBlock,ecx
mov eax, BytesPerIndexBlock
movzx ecx, BytesPerSector
xor edx, edx
div ecx
mov SectorsPerIndexBlock,eax
mov eax, IndexBlockBuffer
add eax, BytesPerIndexBlock
mov IndexBitmapBuffer,eax
cmp IndexAllocation,00000000
je NTFSMain30
cmp IndexBitmap,00000000
je ErrorExit
mov ebx, IndexBitmap
push ds
pop es
mov edi, IndexBitmapBuffer
call ReadWholeAttribute
NTFSMain30:
popad
pop ds
ret
;********************************************
; 所有NTFS严重错误都无条件转到这里处理.
ErrorExit:
int 18h
NTFSMain endp
;******************************************************************************
;GetFileDATAorLBA :根据文件记录索引入口获取在硬盘的位置(LBA)及数据
;入口: eax=文件记录索引入口ebp=0获取位置非0获取数据es:edi=缓冲区
;出口: eax=文件开始LBA(0表示失败) es:edi=文件数据
GetFileDATAorLBA proc
pushad
push es
push edi
; 读文件记录的DATA属性
; eax -> 文件记录索引�