boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
阅读:8199回复:55

终于搞定了文件隐藏, 忙活了一个星期~哇哈哈

楼主#
更多 发布于:2007-08-27 16:59
测试win2KSP4基本正常,参考了FileMon的代码,其实驱动开发主要就是资料少,其它方面没有难度,无非就是按照MS设定好的套路写代码,写那个FASTIO的时候尤其是体力活啊,google才是最好的老师,论坛我问的问题没有任何人提醒我,也许是不屑于回答吧,但是对于一个新手来说,一个简单的问题也可以耗费好大量时间,需源码的新手Email我,我也才学一个多星期而已;-)

【环境搭设】
驱动开发一定要有一个调试环境,我是使用VMWare+共享文件夹+SoftICE+DebugView,在主机里面编译,然后切换到VM执行测试,再也不怕BSOD:-)
【变量声明】驱动程序在函数中声明变量,必须将所有的变量声明放函数开始的地方
【分配和释放字符串缓冲区】
RtlInitAnsiString函数初始化ANSI_STRING字符串。
RtlInitUnicodeString函数初始化UNICODE_STRING字符串。
RtlAnsiStringToUnicodeString函数把ANSI_STRING转化成UNICODE_STRING。
RtlFreeUnicodeString函数释放给字符串动态分配的内存。

RtlInitAnsiString和RtlInitUnicodeString初始化时不分配内存。不能使用RtlFreeUnicodeString函数。ANSI_STRING和UNICODE_STRING中的Buffer指向一个字符串常量,当调用RtlFreeUnicodeString时字符串常量占用的地址被释放。所以产生错误。
RtlAnsiStringToUnicodeString该函数被调用时,将为目标变量分配内存。所以在不使用该变量时要用该函数释放内存,以免内存泄漏。

例:
UNICODE_STRING string_unicode;
ANSI_STRING   string_ansi;
RtlInitUnicodeString(&string_unicode,L”Hello World!”);//不用释放内存
RtlInitAnsiString(&string_ansi,”Hello World!”);
RtlAnsiStringToUnicodeString(&string_unicode,&string_ansi,TRUE);//需要释放内存。
RtlFreeUnicodeString(&string_unicode);//释放动态分配的内存。

【DbgPrint 字符输出格式】
For DbgPrint (or macro KdPrint) - which is like printf - the following
formats should be used (expected type of argument):

1. %s    (PCHAR)
2. %ws    (PWCHAR)
3. %Z    (PSTRING, PANSI_STRING, POEM_STRING)
4. %wZ    (PUNICODE_STRING)

In fact %Z and %wZ are not documented in the official documentation,
but you can find them in CRT source file for _output().
【fastIO】
注意:一定要填写好FastIO函数,否则容易出问题
【DriverUnload】
注意:要首先使用IoDetachDevice卸载附在Device设备上的过滤设备,否则会导致BSOD

代码如下:
#include <ntddk.h>
#include "fastIO.h"
#include "test.h"

/*
 *    驱动主入口函数
 */
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
{
    int i;
    NTSTATUS status;
    UNICODE_STRING nameString;
    PDEVICE_OBJECT FilterDevice;
    //首先创建一个CDO
    RtlInitUnicodeString(&nameString, L"\\FileSystem\\SFilter");
    status = IoCreateDevice(
                            DriverObject,
                            0,
                            &nameString,
                            FILE_DEVICE_DISK_FILE_SYSTEM,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &g_CDO    
                            );
    if (!NT_SUCCESS(status))
    {
        KdPrint(("DriverEntry:Error Create cdo, status = %08x\n", status));
        return status;
    }
    //安装分发函数
    for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction = SfPassThrough;
    }
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FsDirectoryControl;    
    DriverObject->DriverUnload = DriverUnload;
    //Fast IO
    InitFastIo(DriverObject);
    //准备绑定C:\的设备
    RtlInitUnicodeString(&nameString, L"\\DosDevices\\C:\\");
    if (!AttachToDiskDevice(&nameString, &FilterDevice))
    {
        KdPrint(("DrierEntry Failed..\n"));
        IoDeleteDevice(FilterDevice);
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    return status;//STATUS_DEVICE_CONFIGURATION_ERROR;
}

/*
 *驱动卸载    
 */
VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    //卸载资源
    PDEVICE_OBJECT DO = DriverObject->DeviceObject;
    PDEVICE_OBJECT NextDO = NULL;
    PDEVICE_EXTENSION DevEx = NULL;

    if (DriverObject)
    {
        while(DO)
        {
            KdPrint (("Unload Device...\n"));
            NextDO = DO->NextDevice;
            DevEx = DO->DeviceExtension;
            if (DevEx)
            {
                if (DevEx->AttachedToDevice)
                {
                    IoDetachDevice(DevEx->AttachedToDevice);
                }
            }
            IoDeleteDevice(DO);
            DO = NextDO;
        }
    }
    //释放FastIo
    DestoryFastIo(DriverObject);
}

/*
 *    驱动的目录处理函数
 */
NTSTATUS
FsDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp)
{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);    //当前Irp(IO_STACK_LOCATION)的参数
    PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PFILE_BOTH_DIR_INFORMATION dirInfo = NULL;
    KEVENT waitEvent;
    //UNICODE_STRING path;

    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
    if (IRP_MN_QUERY_DIRECTORY != irpSp->MinorFunction)
    {
        goto SkipHandle;
    }
    if (Irp->RequestorMode == KernelMode)
    {
        goto SkipHandle;
    }
    if (FileBothDirectoryInformation != ((PQUERY_DIRECTORY)&irpSp->Parameters)->FileInformationClass)
    {    
        goto SkipHandle;
    }
    //设置完成回调函数
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    //IoSetCompletionRoutine(Irp,CompletionRoutine,context,InvokeOnSuccess,InvokeOnError,InvokeOnCancel);
    IoSetCompletionRoutine(    
                            Irp,
                            DirControlCompletion,        //CompletionRoutine
                            &waitEvent,                    //context parameter
                            TRUE,
                            TRUE,
                            TRUE
                            );

    status = IoCallDriver(devExt->AttachedToDevice, Irp);
    if (STATUS_PENDING == status)
    {
        //等待完成
        status = KeWaitForSingleObject(&waitEvent,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL
                                        );
        ASSERT(STATUS_SUCCESS == status);
    }
    if (!NT_SUCCESS(status) ||(0 == irpSp->Parameters.QueryFile.Length))
    {    
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    //KdPrint(("Hook Directory.\n"));
    HandleDirectory(Irp->UserBuffer,  &((PQUERY_DIRECTORY)&irpSp->Parameters)->Length);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;

SkipHandle:
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(devExt->AttachedToDevice, Irp);
}

BOOLEAN
HandleDirectory(IN OUT PFILE_BOTH_DIR_INFORMATION DirInfo, IN PULONG lpBufLenth)
{
    //处理目录操作
    PFILE_BOTH_DIR_INFORMATION currentDirInfo = DirInfo;
    ULONG offset = 0;
    ULONG position = 0;
    ULONG newLenth = *lpBufLenth;
    WCHAR fileName[] = L"HideTest.txt";
    do
    {
        offset = currentDirInfo->NextEntryOffset;

        if (!(FILE_ATTRIBUTE_DIRECTORY & currentDirInfo->FileAttributes) &&
            (0 == wcsncmp(currentDirInfo->FileName, fileName, currentDirInfo->FileNameLength>>1)))
        {
            //Now We Will Test The FileName
            //KdPrint(("%08x Hided File:%ws[%d]\n", currentDirInfo->FileAttributes, currentDirInfo->FileName, currentDirInfo->FileNameLength));
            RtlMoveMemory(currentDirInfo, (PUCHAR)currentDirInfo + offset, *lpBufLenth - position - offset);
            newLenth -= offset;
            position += offset;
        }
        else
        {
            //KdPrint(("%08x Directory:%ws\n", currentDirInfo->FileAttributes, currentDirInfo->FileName));
            //Move Next
            position += offset;
            currentDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)currentDirInfo + offset);
        }
    } while (0 != offset);
    *lpBufLenth = newLenth;
    return TRUE;
}

BOOLEAN
CmpWString(const WCHAR *s1, const WCHAR *s2, ULONG size)
{
    return TRUE;
}

NTSTATUS
DirControlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
    //if (Irp->PendingReturned) IoMarkIrpPending(Irp);
    KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
    return STATUS_MORE_PROCESSING_REQUIRED;    //注:必须返回这个值
}
BOOLEAN
IS_MY_DEVICE_OBJECT(PDEVICE_OBJECT DeviceObject)
{
    return DeviceObject->DriverObject == g_CDO->DriverObject;
}

/*
 *     挂载到指定的磁盘设备
 */
BOOLEAN
AttachToDiskDevice(IN PUNICODE_STRING pDiskName, OUT PDEVICE_OBJECT *pOurDevice)
{
    NTSTATUS status;
    PDEVICE_EXTENSION DevEx;
    PDEVICE_OBJECT DiskDeviceObject;
    PDEVICE_OBJECT NewDeviceObject;

    IO_STATUS_BLOCK ioStatus;
    OBJECT_ATTRIBUTES objectAttributes;
    PFILE_OBJECT fileObject = NULL;
    HANDLE ntFileHandle;
    // We have to figure out what device to hook - first open the volume's
    // root directory
    //
    InitializeObjectAttributes(&objectAttributes, pDiskName, OBJ_CASE_INSENSITIVE, NULL, NULL );
    status = ZwCreateFile(&ntFileHandle, SYNCHRONIZE|FILE_ANY_ACCESS,
                            &objectAttributes, &ioStatus, NULL, 0,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE,
                            NULL, 0);

    if (!NT_SUCCESS(status))
    {
        DbgPrint(("Filemon: Could not open drive\n"));
        return FALSE;
    }
    KdPrint(("Open Device is OK\n"));
    //
    // Got the file handle, so now look-up the file-object it refers to
    //
    status = ObReferenceObjectByHandle(ntFileHandle, FILE_READ_DATA, NULL, KernelMode, &fileObject, NULL);
    if(!NT_SUCCESS(status))
    {
        DbgPrint(("Filemon: Could not get fileobject from handle\n"));
        ZwClose(ntFileHandle);
        return FALSE;            
    }
    DiskDeviceObject = IoGetRelatedDeviceObject(fileObject);
    if(!DiskDeviceObject)
    {
        DbgPrint(("Filemon: Could not get related device object\n"));
        goto ErrHand;
    }
    //创建挂载设备
    status = IoCreateDevice(
                            g_CDO->DriverObject,
                            sizeof(DEVICE_EXTENSION),
                            NULL,
                            DiskDeviceObject->DeviceType,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &NewDeviceObject
                            );
    if (!NT_SUCCESS(status))
    {
        goto ErrHand;
    }
    NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    *pOurDevice = NewDeviceObject;

    DevEx = NewDeviceObject->DeviceExtension;
    DevEx->AttachedToDevice = DiskDeviceObject;
    DevEx->DeviceName.Length = 0;
    DevEx->DeviceName.MaximumLength = sizeof(DevEx->DeviceNameBuffer);
    DevEx->DeviceName.Buffer = DevEx->DeviceNameBuffer;
    //RtlFillMemory(DevEx->DeviceName.Buffer, sizeof(DevEx->DeviceNameBuffer), 0);
    SfGetObjectName(g_CDO, &(DevEx->DeviceName));

    //执行挂载
    DevEx->AttachedToDevice = IoAttachDeviceToDeviceStack(NewDeviceObject, DiskDeviceObject);
    if (!DevEx->AttachedToDevice)
    {
        goto ErrHand;
    }

    KdPrint(("Attath Device is OK\n"));
    ObDereferenceObject(fileObject);
    ZwClose(ntFileHandle);
    return TRUE;

ErrHand:
    KdPrint(("AttachDevice Failed status %08x\n", status));
    ObDereferenceObject(fileObject);
    ZwClose(ntFileHandle);
    return  FALSE;
}


/*
 *    不处理的Irp
 */
NTSTATUS
SfPassThrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    //不处理
    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDevice, Irp);
}

/*
 *    得到一个对象的名称
 */
VOID
SfGetObjectName(
    IN PVOID Object,
    IN OUT PUNICODE_STRING Name
)
{
    NTSTATUS status;
    CHAR nibuf[512]; //buffer that receives NAME information and name

    POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)nibuf;
    ULONG retLength;
    
    status = ObQueryNameString(Object, nameInfo, sizeof(nibuf), &retLength);
    
    Name->Length = 0;
    if (NT_SUCCESS( status ))
    {
        RtlCopyUnicodeString(Name, &nameInfo->Name);
        //KdPrint(("Object %wZ,Len = %d.[%d]\n", Name, retLength, Name->Length));
    }
}
boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
沙发#
发布于:2007-08-27 17:02
怎么代码帖出来就是斜的了??极度不喜欢中。。。
strpic
驱动小牛
驱动小牛
  • 注册日期2006-11-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望238点
  • 贡献值0点
  • 好评度156点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-08-27 22:27
祝贺楼主!学习。能发给代码吗?谢谢! jskcxqhk@yahoo.com.hk
wyhbbs
驱动牛犊
驱动牛犊
  • 注册日期2007-07-27
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分91分
  • 威望13点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-08-28 08:44
希望也给我发一份共同学习,谢谢!
Email:gzwuyh@gmail.com
yonghen21
驱动牛犊
驱动牛犊
  • 注册日期2006-08-25
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分329分
  • 威望96点
  • 贡献值0点
  • 好评度32点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-08-28 10:11
谢谢共享 :)
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2007-08-28 10:24
虽然我也实现了,但还是佩服LZ的精神,顶你一个.
驱网无线,快乐无限
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2007-08-28 10:25
你的代码我没看,我也实现禁止访问,但对冰刀无效,LZ的呢
驱网无线,快乐无限
ldljlzw
驱动中牛
驱动中牛
  • 注册日期2002-03-16
  • 最后登录2014-01-02
  • 粉丝1
  • 关注0
  • 积分1021分
  • 威望372点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-08-28 10:26
谢谢共享,顶!
wwg266543
驱动小牛
驱动小牛
  • 注册日期2007-07-03
  • 最后登录2014-08-27
  • 粉丝3
  • 关注1
  • 积分3分
  • 威望882点
  • 贡献值0点
  • 好评度9点
  • 原创分0分
  • 专家分54分
8楼#
发布于:2007-08-28 10:28
楼主厉害呀!我也正在学习这块内容,能给我一份代码吗?
wwg266543@sina.com
fantaidu
驱动牛犊
驱动牛犊
  • 注册日期2007-04-02
  • 最后登录2008-11-21
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望27点
  • 贡献值0点
  • 好评度24点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-08-28 10:56
好人 楼主  我也要代码 xiaoyaozhiyu123@163.com
谢谢
boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
10楼#
发布于:2007-08-28 11:29
To abc13271552
冰刀那个家伙是自己发IRP直接到NTFS的,绕过了我们的过滤驱动了,所以不行啊
我现在还不会,要是有好办法,希望通知一下 我的Email:Boywhp@126.com
zhangheyang
驱动牛犊
驱动牛犊
  • 注册日期2007-05-19
  • 最后登录2014-04-17
  • 粉丝0
  • 关注0
  • 积分140分
  • 威望30点
  • 贡献值0点
  • 好评度29点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-08-28 13:50
发份代码学习一下,zhangheyang2008@126.com
另请问我做的文件保护,为什么在文件被装入内存后就不会再受IRP_MJ_READ控制呢?大家是怎么清Cache的呢?我的代码很简单,就是在IRP_MJ_READ里禁止非我的进程访问某个特殊的文件夹。是不是要在FastIO中作什么?如何做呢?
xx_qiang
驱动小牛
驱动小牛
  • 注册日期2004-07-30
  • 最后登录2017-02-27
  • 粉丝2
  • 关注1
  • 积分31分
  • 威望249点
  • 贡献值0点
  • 好评度171点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2007-08-28 14:51
这种方式的隐藏,360safe一个检查就把你的设备给detach了。想想当年自己也写过这个,真怀念阿。

另请问我做的文件保护,为什么在文件被装入内存后就不会再受IRP_MJ_READ控制呢?大家是怎么清Cache的呢?我的代码很简单,就是在IRP_MJ_READ里禁止非我的进程访问某个特殊的文件夹。是不是要在FastIO中作什么?如何做呢?


你在irp_mj_create 里处理一下应该比较好
boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
13楼#
发布于:2007-08-28 15:04
应该在rp_mj_create就让其得到失败的消息

也没有什么好的方法呢?可以隐藏比较好;-( xx_qiang提示一下,目前刚学驱动,太复杂的不会了
zhangheyang
驱动牛犊
驱动牛犊
  • 注册日期2007-05-19
  • 最后登录2014-04-17
  • 粉丝0
  • 关注0
  • 积分140分
  • 威望30点
  • 贡献值0点
  • 好评度29点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2007-08-28 17:45
你在irp_mj_create 里处理一下应该比较好,中也处理了。
是cache的问题,当文档存在于内存中。像WORD这类软件就可以从Cache中打开了。
looksail
荣誉会员
荣誉会员
  • 注册日期2005-05-22
  • 最后登录2014-03-15
  • 粉丝2
  • 关注0
  • 积分1016分
  • 威望991点
  • 贡献值0点
  • 好评度239点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2007-08-28 17:53
赞扬楼主的奉献精神!
提问归提问,还是只能靠自己
moshior
驱动牛犊
驱动牛犊
  • 注册日期2007-06-08
  • 最后登录2013-06-20
  • 粉丝0
  • 关注0
  • 积分110分
  • 威望12点
  • 贡献值0点
  • 好评度11点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2007-08-28 18:22
楼主,mail一个给我吧moshior_li@yahoo.com.cn
pandaforum
驱动小牛
驱动小牛
  • 注册日期2007-02-13
  • 最后登录2011-09-06
  • 粉丝0
  • 关注0
  • 积分728分
  • 威望282点
  • 贡献值1点
  • 好评度66点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2007-08-28 18:38
想学习一下楼主的代码 谢谢 pandaemail@163.com
boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
18楼#
发布于:2007-08-28 21:37
VRV0424
驱动牛犊
驱动牛犊
  • 注册日期2007-04-24
  • 最后登录2007-10-22
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2007-08-29 15:09
楼主给我一份研究一下,chinabjhyn2008@sina.com
驱网无线,快乐无限
上一页
游客

返回顶部