设为首页 收藏本站
查看: 1168|回复: 0

[经验分享] Windows内核函数(2) - 内核模式下的文件操作

[复制链接]

尚未签到

发表于 2015-12-16 10:40:03 | 显示全部楼层 |阅读模式
1.       文件的创建
对文件的创建或者打开都是通过内核函数ZwCreateFile实现的。和Windows API类似,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的。在文件操作完毕后,要关闭这个文件句柄。
NTSTATUS  
  ZwCreateFile(
    OUT PHANDLE  FileHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN PLARGE_INTEGER AllocationSize  OPTIONAL,
    IN ULONG  FileAttributes,
    IN ULONG  ShareAccess,
    IN ULONG  CreateDisposition,
    IN ULONG  CreateOptions,
    IN PVOID  EaBuffer  OPTIONAL,
    IN ULONG  EaLength
    );


FileHandle返回打开文件的句柄
DesiredAccess 一般指定为GENERIC_READ 或者 GENERIC_WRITE
ObjectAttributes:OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名。
IoStatusBlock:指向一个IO_STATUS_BLOCK结构体,该结构接收ZwCreateFile操作的结果状态。
AllocationSize是一个指针,指向一个64位整数,该数指定文件初始分配时的大小、该参数仅关系到创建或重写文件操作。如果忽略它,那么文件长度将从0开始,并随着写入而增长。
FileAttributes指定新创建文件的属性,一般为0FILE_ATTRIBUTE_NORMAL
ShareAccess指定文件的共享方式,0或者FILE_SHARE_READ
CreateDisposition指定当文件存在或不存在时,该如何处理
CreateOptionsFILE_SYNCHRONOUS_IO_NONALERT,指定控制打开操作和句柄使用的附加标志位。
EaBuffer一个指针,指向可选的扩展属性区
EaLength扩展属性区的长度

要创建的文件的文件名是通过第三个参数传入的。这个参数是一个OBJECT_ATTRIBUTES得结构。DDK提供了对OBJECT_ATTRIBUTES初始化的宏:
VOID
  InitializeObjectAttributes(
    OUT POBJECT_ATTRIBUTES  InitializedAttributes,
    IN PUNICODE_STRING  ObjectName,//文件名
    IN ULONG  Attributes,//一般为OBJ_CASE_INSENSITIVE,对大小写敏感
    IN HANDLE  RootDirectory,//一般为NULL
    IN PSECURITY_DESCRIPTOR  SecurityDescriptor //一般为NULL
    );


示例代码:
VOID TetsCreateFile()
{
    UNICODE_STRING string;
    RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

    OBJECT_ATTRIBUTES objattr;
    InitializeObjectAttributes(&objattr,
&string, OBJ_CASE_INSENSITIVE, NULL, NULL);

    HANDLE hFile;
    IO_STATUS_BLOCK iostatus;
    NTSTATUS status = ZwCreateFile(&hFile,
GENERIC_READ | GENERIC_WRITE, &objattr, &iostatus,
              NULL, FILE_ATTRIBUTE_NORMAL, 0,
FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
   
    if (!NT_SUCCESS(status))
    {
       KdPrint(("文件创建失败!\n"));
    }
    else
    {
       KdPrint(("文件创建成功!\n"));
    }

    //文件操作
    //......
    //关闭文件句柄
    ZwClose(hFile);
}


2.  文件的创建
除了可以用ZwCreateFile函数打开文件,DDK还为我们提供了一个ZwOpenFile函数用来打开文件,以简化文件的打开操作。
NTSTATUS
  ZwOpenFile(
    OUT PHANDLE  FileHandle,
    IN ACCESS_MASK  DesiredAccess, //打开权限,一般为GENERIC_ALL
    IN POBJECT_ATTRIBUTES  ObjectAttributes,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    IN ULONG  ShareAccess,
    IN ULONG  OpenOptions//打开选项,一般为FILE_SYNCHRONOUS_IO_NONALERT
    );



3.  获取或修改文件属性
获取和修改文件属性,包括获取文件大小,获取或修改文件指针位置,获取或修改文件名,获取或修改文件属性(只读属性,隐藏属性),获取或修改文件创建,修改日期。
NTSTATUS
  ZwSetInformationFile(
    IN HANDLE  FileHandle,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    IN PVOID  FileInformation,
    IN ULONG  Length,
    IN FILE_INFORMATION_CLASS  FileInformationClass
    );


NTSTATUS
  ZwQueryInformationFile(
    IN HANDLE  FileHandle,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    OUT PVOID  FileInformation,
    IN ULONG  Length,
    IN FILE_INFORMATION_CLASS  FileInformationClass
    );


FileInformation:依据FileInformationClass不同而不同。
LengthFileInformation数据的长度
FileInformationClass描述修改属性的类型

(1)   FileInformationClass FileStandardInformation 时,输入和输出数据是FILE_STANDARD_INFORMATION结构体,描述文件的标准信息。
typedef struct FILE_STANDARD_INFORMATION {
  LARGE_INTEGER  AllocationSize; //为文件非配的大小
  LARGE_INTEGER  EndOfFile; //距离文件结尾还有多少字节
  ULONG  NumberOfLinks; //有多少要个链接文件
  BOOLEAN  DeletePending; //是否准备删除
  BOOLEAN  Directory; //是否为目录
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;


(2)   FileInformationClass FileBasicInformation 时,输入和输出数据是FILE_BASIC_INFORMATION结构体,描述文件的基本信息。
typedef struct FILE_BASIC_INFORMATION {
  LARGE_INTEGER  CreationTime;
  LARGE_INTEGER  LastAccessTime;
  LARGE_INTEGER  LastWriteTime;
  LARGE_INTEGER  ChangeTime;
  ULONG  FileAttributes; //文件属性
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;


(3)   FileInformationClass FileNameInformation 时,输入和输出数据是FILE_NAME_INFORMATION结构体,描述文件名信息。
typedef struct _FILE_NAME_INFORMATION {
  ULONG  FileNameLength; //文件名长度
  WCHAR  FileName[1]; //文件名
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;


(4)   FileInformationClass FilePositionInformation 时,输入和输出数据是FILE_POSITION_INFORMATION结构体,描述文件指针位置信息。
typedef struct FILE_POSITION_INFORMATION {
  LARGE_INTEGER  CurrentByteOffset; //代表当期文件指针为止
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;


示例代码:
VOID TetsFile()
{
    UNICODE_STRING string;
    RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

    OBJECT_ATTRIBUTES objattr;
    InitializeObjectAttributes(&objattr,
&string, OBJ_CASE_INSENSITIVE, NULL, NULL);

    HANDLE hFile;
    IO_STATUS_BLOCK iostatus;

    //打开文件
    NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ,
&objattr, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, F
ILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
   
    if (!NT_SUCCESS(status))
    {
       KdPrint(("文件打开失败!\n"));
    }
    else
    {
       KdPrint(("文件打开成功!\n"));

       FILE_BASIC_INFORMATION fbi;
        //查询文件基本信息
status = ZwQueryInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);

        if (NT_SUCCESS(status))
        {
           KdPrint(("查询文件属性成功!\n"));
        }
      
       //设置文件只读属性
        fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY;
status = ZwSetInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);

        if (NT_SUCCESS(status))
        {
           KdPrint(("设置文件只读属性成功!\n"));
        }
       //关闭文件句柄
        ZwClose(hFile);
    }  
}


4.  文件的写操作
NTSTATUS
  ZwWriteFile(
    IN HANDLE  FileHandle,
    IN HANDLE  Event  OPTIONAL, //一般设为NULL
    IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL, //一般设为NULL
    IN PVOID  ApcContext  OPTIONAL, //一般设为NULL
    OUT PIO_STATUS_BLOCK  IoStatusBlock, //记录实际写的字节数
    IN PVOID  Buffer, //从这个缓冲区中开始往文件里写
    IN ULONG  Length, //准备写多少字节
    IN PLARGE_INTEGER  ByteOffset  OPTIONAL, //从文件的多少偏移开始写
    IN PULONG  Key  OPTIONAL //一般设为NULL
    );

IoStatusBlockIoStatusBlock.Information记录实际写了多少字节。

示例代码:
#define BUFFER_SIZE 1024
#pragma INITCODE
VOID TetsFile()
{
         UNICODE_STRING string;
         RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

         OBJECT_ATTRIBUTES objattr;
         InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE,
NULL, NULL);

         HANDLE hFile;
         IO_STATUS_BLOCK iostatus;

         //打开文件
         NTSTATUS status = ZwCreateFile(&hFile, GENERIC_WRITE,
&objattr, &iostatus,
                                               NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
        
         //分配Buffer空间
         PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);
         RtlFillMemory(pBuffer, BUFFER_SIZE, 'A');
         //写文件
         status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
pBuffer, BUFFER_SIZE, NULL, NULL);
        
         LARGE_INTEGER  ByteOffset;
         ByteOffset.QuadPart = 1024i64; //设置文件指针偏移
         RtlFillMemory(pBuffer, BUFFER_SIZE, 'B');

         status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus,
pBuffer, BUFFER_SIZE, &ByteOffset, NULL);
         //关闭文件句柄
         ZwClose(hFile);
         //释放内存
         ExFreePool(pBuffer);
}


5.       文件的读操作
NTSTATUS
  ZwReadFile(
    IN HANDLE  FileHandle,
    IN HANDLE  Event  OPTIONAL,
    IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
    IN PVOID  ApcContext  OPTIONAL,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    OUT PVOID  Buffer,
    IN ULONG  Length,
    IN PLARGE_INTEGER  ByteOffset  OPTIONAL,
    IN PULONG  Key  OPTIONAL
    );

如果需要读取整个文件,那么得知道文件的大小,我们可以用ZwQueryInformationFile来实现。

示例代码:
#pragma INITCODE
VOID TetsFile()
{
         UNICODE_STRING string;
         RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");

         OBJECT_ATTRIBUTES objattr;
         InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);

         HANDLE hFile;
         IO_STATUS_BLOCK iostatus;

         //打开文件
         NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus,
                   NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

         //获得文件的大小
         FILE_STANDARD_INFORMATION fsi;
         status = ZwQueryInformationFile(hFile,
&iostatus, &fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);

         //分配Buffer空间
         PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,
(LONG)fsi.EndOfFile.QuadPart);
        
         //读文件
         status = ZwReadFile(hFile, NULL, NULL, NULL,
&iostatus, pBuffer, (LONG)fsi.EndOfFile.QuadPart, NULL, NULL);
         KdPrint(("Read %d bytes\n", iostatus.Information));

         //关闭文件句柄
         ZwClose(hFile);
         //释放内存
         ExFreePool(pBuffer);
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-151905-1-1.html 上篇帖子: Windows内核函数(3) - 内核模式下的注册表操作 下篇帖子: Windows内核函数(1) - 字符串处理函数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表