实现FileCopy(Ring0 x86 x64)

 

 

1.1 内核不接受一个字符串文件路径,必须填写一个OBJECT_ATTRIBUTES结构。
    这个结构,在InitializeObjectAttributes初始化


typedef struct _OBJECT_ATTRIBUTES {
  ULONG  Length;
  HANDLE  RootDirectory;
  PUNICODE_STRING  ObjectName;                //路径
  ULONG  Attributes;
  PVOID  SecurityDescriptor;
  PVOID  SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;




VOID 
  InitializeObjectAttributes(
    OUT POBJECT_ATTRIBUTES  InitializedAttributes,
    IN PUNICODE_STRING  ObjectName,                            //路径
    IN ULONG  Attributes,                                          //OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE  忽略大小写 |打开内核句柄
    IN HANDLE  RootDirectory,
    IN PSECURITY_DESCRIPTOR  SecurityDescriptor            //打开的是内核句柄  传NULL
    );

NTSTATUS 
  ZwCreateFile(
    __out PHANDLE  FileHandle,
    __in ACCESS_MASK  DesiredAccess,                            //申请的权限GENERIC_ALL
    __in POBJECT_ATTRIBUTES  ObjectAttributes,
    __out PIO_STATUS_BLOCK  IoStatusBlock,                    //
    __in_opt PLARGE_INTEGER  AllocationSize,
    __in ULONG  FileAttributes,
    __in ULONG  ShareAccess,
    __in ULONG  CreateDisposition,
    __in ULONG  CreateOptions,
    __in_opt PVOID  EaBuffer,
    __in ULONG  EaLength
    );

如果CreateOptions 带有FILE_NO_INTERMEDIATE_BUFFERING CreateOptions 表示不通过缓冲区 直接操作磁盘,所以每次
操作读写都必须以磁盘扇区大小(通常为512字节)对齐,否则返回错误,
typedef struct _IO_STATUS_BLOCK {
    union {
        NTSTATUS Status;            //成功则为STATUS_SUCCESS
        PVOID Pointer;
    } DUMMYUNIONNAME;
    ULONG_PTR Information;            //返回的更多信息
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;






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
    );

读取的实际长度在ioStatusBlock.Information里
读取完  返回STATUS_END_OF_FILE

       

NTSTATUS 
  ZwWriteFile(
    IN HANDLE  FileHandle,
    IN HANDLE  Event  OPTIONAL,
    IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
    IN PVOID  ApcContext  OPTIONAL,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    IN PVOID  Buffer,
    IN ULONG  Length,
    IN PLARGE_INTEGER  ByteOffset  OPTIONAL,
    IN PULONG  Key  OPTIONAL
    );

 

 下面是实现代码:
/***************************************************************************************
* AUTHOR : icqw
* DATE   : 2015-7-30
* MODULE : FileOption.H
*
* IOCTRL Sample Driver
*
* Description:
*        Demonstrates communications between USER and KERNEL.
*
****************************************************************************************
* Copyright (C) 2010 icqw.
****************************************************************************************/
#ifndef CXX_FILEOPTION_H
#define CXX_FILEOPTION_H
#include <ntifs.h>
#include <devioctl.h>
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING pRegistryString);
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObj);
HANDLE OpenFile(WCHAR* wzFilePath);
NTSTATUS    ReadFile(HANDLE hFile,CHAR* szBuffer,PULONG ulLength,PLARGE_INTEGER Offset);
NTSTATUS    WriteFile(HANDLE hFile,CHAR* szBuffer,PULONG ulLength,PLARGE_INTEGER Offset);
NTSTATUS FileCopy(WCHAR* wzDest,WCHAR* wzSour);
#endif

 

#ifndef CXX_FILEOPTION_H
#    include "FileOption.h"
#endif
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING pRegisterPath)
{
    NTSTATUS        status = STATUS_SUCCESS;
// #if DBG
//     _asm int 3
// 
// #endif
    DriverObject->DriverUnload = DriverUnload;
    FileCopy(L"\\??\\D:\\Dest.txt",L"\\??\\D:\\Sour.txt");
    
    DbgPrint("[FileOption] DriverEntry Success\r\n");
    return STATUS_SUCCESS;
}
NTSTATUS FileCopy(WCHAR* wzDest,WCHAR* wzSour)
{
    HANDLE hSourFile    =    OpenFile(wzSour);
    HANDLE hDestFile    =    OpenFile(wzDest);
    ULONG     ulLength    =    0;
    CHAR*     szBuffer    =    NULL;
    NTSTATUS Status        =    STATUS_UNSUCCESSFUL;
    LARGE_INTEGER Offset    =    {0};
    if (hSourFile==NULL||hDestFile==NULL)
    {
        return STATUS_UNSUCCESSFUL;
    }
    szBuffer    =    (char*)ExAllocatePool(NonPagedPool,4*1024+1);
    while(TRUE)
    {
        RtlZeroMemory(szBuffer,4*1024+1);
        ulLength    =    4*1024;
        //
        Status        =    ReadFile(hSourFile,
                                 szBuffer,
                                 &ulLength,
                                 &Offset);
        if (!NT_SUCCESS(Status))
        {
                break;
        }
        //
        Status        =    WriteFile(hDestFile,
                                  szBuffer,
                                  &ulLength,
                                  &Offset);
        if (!NT_SUCCESS(Status))
        {
            break;
        }
    }
    DbgPrint("Copy Success!");
    ZwClose(hSourFile);
    ZwClose(hDestFile);
    return STATUS_SUCCESS;
}
HANDLE OpenFile(WCHAR* wzFilePath)
{
    UNICODE_STRING    uniName;
    OBJECT_ATTRIBUTES    Ob;
    HANDLE hFile    =    NULL;
    NTSTATUS Status    =    STATUS_UNSUCCESSFUL;
    IO_STATUS_BLOCK ioStatus    =    {0};
    
    RtlInitUnicodeString(&uniName,wzFilePath);
    InitializeObjectAttributes(&Ob,
        &uniName,
        OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
        NULL,
        NULL);
    Status    =    ZwCreateFile(&hFile,
                             GENERIC_ALL|SYNCHRONIZE,
                             &Ob,
                             &ioStatus,
                             NULL,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ,
                             FILE_OPEN_IF,
                             FILE_NON_DIRECTORY_FILE|
                             FILE_RANDOM_ACCESS|
                             FILE_SYNCHRONOUS_IO_NONALERT,
                             NULL,
                             0);
    if (!NT_SUCCESS(Status))
    {
        return NULL;
    }
    return hFile;
}
//读文件 ulLength 为读取实际长度
NTSTATUS    ReadFile(HANDLE hFile,CHAR* szBuffer,PULONG ulLength,PLARGE_INTEGER Offset)
{
    //这里用    
    NTSTATUS    Status            =    STATUS_UNSUCCESSFUL;
    IO_STATUS_BLOCK    ioStatus    =    {0};
        
    
    Status    =    ZwReadFile(hFile,
                            NULL,
                            NULL,
                            NULL,
                            &ioStatus,
                            szBuffer,
                            *ulLength,            
                            Offset,
                            NULL);
    if (!NT_SUCCESS(Status))
    {
        //Status==STATUS_END_OF_FILE)
        
        return STATUS_UNSUCCESSFUL;  
        
    }
    *ulLength    =    ioStatus.Information;
    return Status;;
}
//写文件
NTSTATUS    WriteFile(HANDLE hFile,CHAR* szBuffer,PULONG ulLength,PLARGE_INTEGER Offset)
{
    NTSTATUS    Status            =    STATUS_UNSUCCESSFUL;
    IO_STATUS_BLOCK    ioStatus    =    {0};
    
    Status    =    ZwWriteFile(hFile,
                            NULL,
                            NULL,
                            NULL,
                            &ioStatus,
                            szBuffer,
                            *ulLength,
                            Offset,
                            NULL);
    if (!NT_SUCCESS(Status))
    {
        return STATUS_UNSUCCESSFUL;  //!!!!
    }
    (*Offset).QuadPart    +=    *ulLength;            //Offset移动
    return Status;;
}
VOID
DriverUnload(IN PDRIVER_OBJECT pDriverObj)
{
    DbgPrint("[FileOption] Unloaded Success\r\n");
    return;
}

 

posted @ 2015-07-31 12:01  icqw  阅读(365)  评论(0编辑  收藏  举报