• 【旧文章搬运】摘除过滤驱动


    原文发表于百度空间,2009-02-03
    ==========================================================================

    开始本文之前先膜拜一下老V~
    “无法F5的驱动,不是好驱动啊~不是好驱动啊~ ”            -----killvxk语录

    这两天下午的时间,破解那个驱动保护搞得好痛苦,每次关机都要蓝一次,有时候设备还不工作,郁闷...
    而且VMware用得很伤心,每次开GuestOS都得6分钟左右,要不是时间不多懒得换它,早就把它扔到垃圾堆里去了~~~~~~~~~~
    忘了今天主题了,摘除过滤驱动来着~
    某些驱动创建自己的Device之后调用IoAttachDeviceXXX函数来将自己的设备附加到目标设备上,成为其上一层驱动,这样当有IRP发来的时候就有了优先处理权。这个其实可以认为是M$给你提供的正统的Hook方式,否则的话你要优先处理IRP可能就得Hook及DispatchRoutine了~如果拿到IRP就处理的话,可以认为是SetOnBefore的Hook方式,如果拿到IRP后设置CompleteRoutine然后继续下发,可以认为是SetOnAfter的Hook方式。又说到Hook这东西了,这东西其实主要在思想,越邪恶越WS才越强大~
    进行附加设备的函数有:
    IoAttachDevice
    IoAttachDeviceByPointer
    IoAttachDeviceToDeviceStack
    IoAttachDeviceToDeviceStackSafe
    它们都调用了未导出的IopAttachDeviceToDeviceStackSafe,要Hook的话就搞它吧~我的驱动里就这么干的,发现调用来自某XX驱动的话就直接返回个失败结果,这样就拒绝某些特定的驱动进行Attach操作(不知道如果把那个XX驱动的AddDevice函数给直接Patch掉会怎么样)。
    当AttachDevice操作成功后,目标设备的AttachedDevice指向刚附加上的设备,而附加上的设备的_DEVOBJ_EXTENSION结构中的AttachedTo则指向它附加上的设备。
    结构如下:

    lkd> dt _DEVICE_OBJECT
    nt!_DEVICE_OBJECT
       +0x000 Type             : Int2B
       +0x002 Size             : Uint2B
       +0x004 ReferenceCount   : Int4B
       +0x008 DriverObject     : Ptr32 _DRIVER_OBJECT
       +0x00c NextDevice       : Ptr32 _DEVICE_OBJECT
       +0x010 AttachedDevice   : Ptr32 _DEVICE_OBJECT
       +0x014 CurrentIrp       : Ptr32 _IRP
       +0x018 Timer            : Ptr32 _IO_TIMER
       +0x01c Flags            : Uint4B
       +0x020 Characteristics : Uint4B
       +0x024 Vpb              : Ptr32 _VPB
       +0x028 DeviceExtension : Ptr32 Void
       +0x02c DeviceType       : Uint4B
       +0x030 StackSize        : Char
       +0x034 Queue            : __unnamed
       +0x05c AlignmentRequirement : Uint4B
       +0x060 DeviceQueue      : _KDEVICE_QUEUE
       +0x074 Dpc              : _KDPC
       +0x094 ActiveThreadCount : Uint4B
       +0x098 SecurityDescriptor : Ptr32 Void
       +0x09c DeviceLock       : _KEVENT
       +0x0ac SectorSize       : Uint2B
       +0x0ae Spare1           : Uint2B
       +0x0b0 DeviceObjectExtension : Ptr32 _DEVOBJ_EXTENSION
       +0x0b4 Reserved         : Ptr32 Void
    lkd> dt _DEVOBJ_EXTENSION
    nt!_DEVOBJ_EXTENSION
       +0x000 Type             : Int2B
       +0x002 Size             : Uint2B
       +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
       +0x008 PowerFlags       : Uint4B
       +0x00c Dope             : Ptr32 _DEVICE_OBJECT_POWER_EXTENSION
       +0x010 ExtensionFlags   : Uint4B
       +0x014 DeviceNode       : Ptr32 Void
       +0x018 AttachedTo       : Ptr32 _DEVICE_OBJECT
       +0x01c StartIoCount     : Int4B
       +0x020 StartIoKey       : Int4B
       +0x024 StartIoFlags     : Uint4B
       +0x028 Vpb              : Ptr32 _VPB


    也就是说,每个设备对象中的AttachedDevice和AttachedTo这两个域承上启下,通过它可以找到它的上一层设备和下一层设备,像什么?对了,双向链表!


    如图,要摘除中间这个过滤驱动B的话,只要断开这个双链就可以了。同时把B的AttachedDevice和AttachedTo这两个域清零。整个操作很像断链隐藏进程,都是双向链表嘛~
    0GiNr上FC的一篇文章《摘除过滤驱动》提供的代码是这样的:

    /////////////////////////////////////代码开始///////////////////////////////////////////////
    RtlInitUnicodeString ( &TcpipName, L"\Driver\Tcpip" );
    ObReferenceObjectByName( &TcpipName,
    OBJ_CASE_INSENSITIVE,
    NULL,
    0,
    *IoDriverObjectType,
    KernelMode,                                          
    NULL,
    &TcpipDrvObj);
    TcpipDevice = TcpipDrvObj->DeviceObject;
    while(TcpipDevice!= NULL )
    {
    TcpipDevice->AttachedDevice=0;
    TcpipDevice = TcpipDevice->NextDevice; 
    }
    //////////////////////////////////////代码结束//////////////////////////////////////////////////////////

    这种摘除法,有点太暴力了(狙剑的过滤驱动摘除就是这么暴力)~而且摘除方法不是很正规吧~

    FC说“首先Reference最底层的,然后循环摘下附在上面的设备”,不知是我最初看到这句话时理解错了还是FC说的不太准确,我觉得同一个驱动创建的多个设备应该是并行的关系没有谁上谁下,而过滤设备与原设备才是上下的关系。所以FC的“最底层的,附在上面”貌似容易引起误解。
    我的摘除法稍“温柔”一点,摘之前判断一下是不是目标设备的,全摘了也不太好~

    //////////////////////////////////////////////////代码开始/////////////////////////////////////////////////////////////
    VOID DetachSecureDevicesFromTargetDriver(PDRIVER_OBJECT pOwnerDrvObject)
    {
    PDEVICE_OBJECT pDevObj,pNextDev;
    
    if (pOwnerDrvObject)
    {
       //取第一个设备
       pNextDev=pOwnerDrvObject->DeviceObject;
       do 
       {
        pDevObj=pNextDev;
        ////////////////////////////////////////////////////////////////////////////////
        ///内部循环摘除单个设备上所附加的设备
        //DbgPrint("正在检查设备0x%08X
    ",pDevObj);
        while(pDevObj->AttachedDevice)
        {
         //判断第一个设备的附加设备
         //进行判断
         if (IsSecurDevice(pDevObj->AttachedDevice))
         {
          DbgPrint("Detaching Device:0x%08X
    ",pDevObj->AttachedDevice);
          IoDetachDevice(pDevObj);//若是XX系统的设备,就摘掉它
         }
         else
         {
          pDevObj=pDevObj->AttachedDevice;//若不是,取上一层设备
         }
        }
        //////////////////////////////////////////////////////////////////////////////
        pNextDev=pNextDev->NextDevice;
       } while(pNextDev);
      
      
    }
    
    }
    
    ////////////////////////////////////////代码结束/////////////////////////////////////////////////////////////////

    摘除效果还可以,有选择性地摘嘛,呵呵~

  • 相关阅读:
    git学习
    我们碰到了大麻烦,一个新来的传教士惹恼了上帝,上帝很愤怒,要求我们把圣经(bbe.txt)背熟,直至他说哪个单词,我们就要飞快的回答出这个单词在第几行第几个单词位置。听说你是个优秀的程序员,那么髟助我们完成这个不可能的任务吧
    jquery 获取radio的值
    <label>标签 for属性
    jquery easyui datebox 的使用
    解析json对象出现$ref: "$.list[0]"的解决办法
    $.messager.show({
    jquery --- 定时器和实时进度条
    js每隔5分钟执行一次ajax请求的实现方法
    JavaScript中清空数组的三种方式
  • 原文地址:https://www.cnblogs.com/achillis/p/10181180.html
Copyright © 2020-2023  润新知