windows文件操作简单笔记--发文于2013.9.16

 windows中文件操作:

copyfile->copyfileexw(fileopcr.c)->BasepCopyFileExW(检查源文件是否存在,看是否是链接文件
  NtQueryInformationFile查询文件拷贝的大小)->BaseCopyStream(查询原文件时间和属性,新建目的文件,做目的文件的句柄处理,拷贝数据,处理the reparse point(后面待看,不懂) ,拷贝文件安全属性。)
 
movefile->MoveFileWithProgressA->MoveFileWithProgressW(试图去做:看原文件是否存在->将原文件内容拷入缓冲区->写入新文件)-》BasepCopyFileExW
(打开原文件—》查询要移动的文件大小)
上面错误。正确:
通过NtSetInformationFile,做改名操作
FileRenameInformation.
 
deletefile->deletefileW(看原文件是否存在)->Disposition.DeleteFile = TRUE->NtSetInformationFile
createfile:ntcreatefile->IoCreateFile(区分是邮槽,管道,文件等)->ObOpenObjectByName-

>ObpLookupObjectName->(通过 \??\X: 符号链接找到设备对象\Device\Harddisk0\PartitionX调用其解析函

数IopParseDevice)(ObReferenceObjectByHandle,ObReferenceObjectByPointer,ParseProcedure

(IopCreateObjectTypes初始化这个处理例程))->IopParseFile->IopParseDevice(IopCheckVpbMounted检测

文件卷是否安装->IopAllocateIrp->IoCallDriver)通过vpb找到fsd上层的过滤设备,发送irp
上面这个可以不用调用IopParseDevice,直接调用IoCallDriver,获取设备发irp向文件系统发删除等的irp.(自保代码有强制删除文件部分)
IoCallDriver->IofcallDriver->pIofCallDriver   windows内核安全编程从入门到实践有详细描述。
 !drvobj  disk 2
!devstack addr
bu CLASSPNP!ClassReadWrite
!drvobj vmscsi
scsi 做dma操作



GetProcessImageFileName->NtQueryInformationProcess->SeLocateProcessImageName-

>PsReferenceProcessFilePointer ->MmGetFileObjectForSection->
ObQueryNameString(遍历对象目录树,组建文件路径)->2,

进程改路径的问题:
运行c:\456\qq.exe,
通过驱动和应用层拿到正确进程路径。比如
1. _EPROCESS->_SE_AUDIT_PROCESS_CREATION_INFO->_OBJECT_NAME_INFORMATION ,  
2. _EPROCESS->_SECTION_OBJECT->_SEGMENT_OBJECT->_CONTROL_AREA->_FILE_OBJECT,
3. _PEB->_PEB_LDR_DATA->_LDR_DATA_TABLE_ENTRY,
4. _PEB->_RTL_USER_PROCESS_PARAMETERS。
关闭qq.exe,修改路径456为123,驱动中得到的路径错误。应用层从peb拿到的路径正确。
_EPROCESS->_SE_AUDIT_PROCESS_CREATION_INFO->_OBJECT_NAME_INFORMATION ,
_EPROCESS->_SECTION_OBJECT->_SEGMENT_OBJECT->_CONTROL_AREA->_FILE_OBJECT, 以上俩错误。
_PEB->_PEB_LDR_DATA->_LDR_DATA_TABLE_ENTRY,
_PEB->_RTL_USER_PROCESS_PARAMETERS。 以上俩正确。

NTFS 使用逻辑簇号(Logical Cluster Number,LCN)和虚拟簇号(Virtual
Cluster Number,VCN)来对簇进行定位。LCN 是对整个卷中所有的簇从头到尾
所进行的简单编号。用卷因子乘以LCN,NTFS 就能够得到卷上的物理字节偏移
量,从而得到物理磁盘地址。VCN 则是对属于特定文件的簇从头到尾进行编号,
以便于引用文件中的数据。VCN 可以映射成LCN,而不必要求在物理上连续。

在NTFS 卷上,跟随在BPB 后的数据字段形成一个扩展BPB。这些字段中
的数据使得Ntldr 能够在启动过程中找到主文件表MFT(Master File Tabl )。
NTFS 中文件通过主文件表(MFT,Main File Table)确定其在磁盘上的位置。
MFT 是一个数据库,由一系列文件记录组成。卷中每一个文件都有一个文件记
录,其中第一个文件记录称作基本文件记录,里面存储有其他扩展文件记录的信
息。主文件表也有自己的文件记录。
NTFS 卷上的每个文件都各有一个唯一的64 位的文件引用号(File Reference
Number,也称文件索引号)。文件引用号由两部分组成:文件号和文件顺序号。
文件号48 位,对应该文件在MFT 中的位置;文件顺序号随着文件记录的重用而
增加(考虑到NTFS 一致性检查)。

磁盘驱动:
类驱动收到irp后,对irp重组,格式化成srb(scsi请求快,,包含有scsi命令描述符块CDB),发给下层驱动

。磁盘端口驱动收到请求后,将srb转换成总线特定的命令,然后发给HBA(总线适配器)。这步就是oem厂商

提供的小端口驱动了。通过!drvobj disk !devstack xxx看。主要是read和write(逻辑簇号->柱面,磁道,

扇区的转换 )

writefile(非缓冲):
nt!IoGetRelatedDeviceObject(得到文件系统设备栈顶端设备sr,系统恢复驱动,下面是ntfs)。->nt!

IoAllocateIrp->sr!SrWrite->Ntfs!NtfsFsdWrite->Ntfs!NtfsCommonWrite->Ntfs!NtfsNonCachedIo->
VolSnap!VolSnapWrite(实现卷快照,位于文件系统和卷管理器驱动之间)->ftdisk!FtDiskReadWrite(磁盘卷

管理驱动,代表一个逻辑卷.和文件系统之间通过vpb链接)->PartMgr!PmReadWrite->Disk驱动的写请求处理

函数CLASSPNP!ClassReadWrite(把irp转为srb)->SCSIPORT磁盘端口驱动SCSIPROT!ScsiPortGlobalDispatch

(IRP_MJ_INTERNAL_DEVICE_CONTROL)->vmscsi(虚拟机的磁盘小端口驱动)->nt!IoStartPacket(排入StartIO

队列串行处理irp)->SCSIPORT!ScsiPortStartIo->IoAllocateAapterChannel(做dma操作)->SCSIPORT!

SpStartIoSynchronized调用vmscsi的某个函数,将SRB的信息通过Write_port_uchar写入小端口驱动的io空间

,然后写入硬件。

WriteFile(缓冲):
nt!NtWriteFile->sr!SrWrite->Ntfs!NtfsFsdWrite->Ntfs!NtfsCommonWrite->nt!CcCanIWrite(判断是否交

由缓存管理器处理)->nt!CcInitializeCacheMap(初始化缓存文件)->nt!CcCopyWrite(写入缓存文件)->缓存

管理器根据算法写入磁盘吸入


MmCreateSection:
   if (AllocationAttributes & SEC_IMAGE) {
            ControlArea = MiFindImageSectionObject (File, TRUE, &GlobalNeeded);
        }

MiFindImageSectionObject:ControlArea = (PCONTROL_AREA)(File->SectionObjectPointer-

>ImageSectionObject);


typedef struct _CONTROL_AREA {
    PSEGMENT Segment;
   xxxxxx
    ULONG NumberOfSectionReferences;    // All section refs & image flushes
 xxxxx
} CONTROL_AREA, *PCONTROL_AREA;

typedef struct _SEGMENT {
    struct _CONTROL_AREA *ControlArea;
    xxxxx
    SEGMENT_FLAGS SegmentFlags;
    PVOID BasedAddress;
    union {
        SIZE_T ImageCommitment;     // for image-backed sections only
        PEPROCESS CreatingProcess;  // for pagefile-backed sections only
    } u1;
    union {
        PSECTION_IMAGE_INFORMATION ImageInformation;    // for images only
        PVOID FirstMappedVa;        // for pagefile-backed sections only
    } u2;
xxxxx
} SEGMENT, *PSEGMENT;

_EPROCESS->_SECTION_OBJECT->_SEGMENT_OBJECT->_CONTROL_AREA->_FILE_OBJECT,
修改_SECTION_OBJECT_POINTERS中的ImageSectionObject()为0后,
不同的文件对象指向同一个 _CONTROL_AREA结构,
FileObject的路径就正确了。
在IopParseDevice中对FileObject初始化。
gloomy对内核的介绍(内存与进程管理器有简单介绍)

设置文件属性操作过程:
SetFileAttributesA(RtlDosPathNameToNtPathName_U,路径前面加\??\)->NtSetInformationFile(
进程句柄,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL,
 FileBasicInformation)

->NtfsCommonSetInformation->NtfsFsdSetInformation->
CcWriteBehind->CcWorkerThread(CcLazyWriteScan )
->NtfsAcquireSharedVcb
->NtfsSetBasicInfo->NtfsUpdateStandardInformation
->NtfsChangeAttributeValue

nt4\private\windows\base\client\filemisc.c 
nt4\private\ntos\io\qsinfo.c
nt4\private\ntos\cntfs\fileinfo.c

你可能感兴趣的:(windows,安全,内核)