(二)(三)(四) (五)见15楼,16楼,38楼,39楼,56楼
看看现在的网络,到处都是rootkit,bootkit,搞得乌烟瘴气的,再看看现在的看雪,已经不是我等小菜能涉猎的地方了,每天别人讨论的我都看不懂,但是又对这些感兴趣,好吧,我承认我落伍了,
再不学连鸡肋都比我跑的快了。犹豫了好久,还是弄本寒江独钓看吧,先从最基本的学起。学习过程重在积累知识,运用知识,这些我从中学到的一并都记录下来,并且加入自己的理解,不对的地方还请大牛们指正鄙视,顺便向sudami,MJ0011等大牛学习。
1:具体怎么安装DDK啊,VMware调试DDK之类的,没什么好说的,就那样。
2:现在主要学习NT式驱动结构,WDM和这差不多,驱动入口函数DriverEntry,虽然名字可以自己定义,但不建议修
改,NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path),该函数由system进程负责加载,
其两个参数,一个是驱动对象,另一个是驱动注册表的字符串,这两个结构在内核中都很重要,并且由系统传入。
3:驱动对象:代表着一个驱动程序,windows通过该结构来找出其对应的驱动有什么功能,比如windows中有很多组件
都有自己的DRIVER_OBJECT,如硬件驱动,类驱动disk,NTFS文件系统等,通过WinObj可以很形象的列出系统中存在
的驱动和设备,在WinDbg中,输入命令dt _DRIVER_OBJECT可以看清楚该结构成员。
kd> dt _DRIVER_OBJECT
nt!_DRIVER_OBJECT
+0x000 Type : Int2B--结构类型
+0x002 Size : Int2B--结构大小
+0x004 DeviceObject : Ptr32 _DEVICE_OBJECT--驱动所创建的设备对象,此对象是条设备链的第一个对象
+0x008 Flags : Uint4B
+0x00c DriverStart : Ptr32 Void--此驱动模块在内核空间中起始地址
+0x010 DriverSize : Uint4B--驱动对象的大小
+0x014 DriverSection : Ptr32 Void
+0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING--驱动名称
+0x024 HardwareDatabase : Ptr32 _UNICODE_STRING--
+0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH--快速I/O分发例程
+0x02c DriverInit : Ptr32 long
+0x030 DriverStartIo : Ptr32 void
+0x034 DriverUnload : Ptr32 void --对应驱动卸载例程
+0x038 MajorFunction : [28] Ptr32 long --主功能号,对应普通的分发函数。
4:UNICODE_STRING,与ring3下字符串不同,内核用的全部都是Unicode字符编码,为的是保障内核的安全和稳定性
避免产生缓冲区溢出等问题。下面看一下这个结构:
kd> dt _UNICODE_STRING
ntdll!_UNICODE_STRING
+0x000 Length : Uint2B--字符串字节长度
+0x002 MaximumLength : Uint2B--字符串总的字节大小
+0x004 Buffer : Ptr32 Uint2B--字符串缓冲区
5:DriverEntry的返回状态是NTSTATUS,他是一个错误码,使用NT_SUCCESS可以判断返回是否成功。
6:驱动就相当于是一个模块,而驱动创建产生的设备则有点像GUI编程中的窗口,那么窗口是可以接收消息的,驱动
中设备接收的消息就是IRP,在驱动编程中叫做请求,其实都一样,分为
IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_DEVICE_CONTROL等等,对应着读请求,写请求,控制请求等。一个驱动对象可以
创建许多个设备对象,这些设备对象连接成链。
kd> dt _DEVICE_OBJECT
ntdll!_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--当前IRP栈,使用StartIO例程,此域指向当前IRP对象
+0x018 Timer : Ptr32 _IO_TIMER--设备对象的定时器
+0x01c Flags : Uint4B-- 设备对象标志,以DO_作为前缀的一组常量
+0x020 Characteristics : Uint4B--设备的特征,以FILE_作为前缀的一组常量
+0x024 Vpb : Ptr32 _VPB--指向设备的卷参数块(Volumn Parameter Block)
+0x028 DeviceExtension : Ptr32 Void--指向设备对象的扩展部分
+0x02c DeviceType : Uint4B--设备类型
+0x030 StackSize : Char--设备栈的大小
+0x034 Queue : __unnamed
+0x05c AlignmentRequirement : Uint4B--缓冲区的对齐要求,其值等于对齐边界减一
+0x060 DeviceQueue : -- 设备队列,存放针对该设备的I/O请求
+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--保留的
刚刚学,这里面有的东西我也不太熟悉,有些也是通过查资料得来的。好吧,看了这么多,内容极其枯燥,来个
实例观察一下。键盘大家最熟悉不过了,系统中只要有驱动文件被载入内存,就会产生一个驱动对象。i8042prt 是
完成 ps/2 键盘驱动主
要功能的驱动程序,下面来观察一下这个i8042prt的情况
kd> !drvobj \driver\i8042prt
Driver object (823397c0) is for:
\Driver\i8042prt
Driver Extension List: (id , addr)
Device Object list:--设备列表
8233ac88 822d7310 --说明了这个驱动创建了两个设备对象
下面来看看这个驱动对象的具体内容
kd> !object \driver\i8042prt
Object: 823397c0 Type: (823ed040) Driver
ObjectHeader: 823397a8 (old version)
HandleCount: 0 PointerCount: 5
Directory Object: e1014838 Name: i8042prt
该对象的起始地址位于823397c0,好吧,查看DRIVER_OBJECT的内容
试了及好几次,命令!strct老是找不出对象结构体,不知什么原因,
哪位大侠能告知小弟啊???
遂用dt命令将就着看吧
kd> dt _DRIVER_OBJECT 823397c0
ntdll!_DRIVER_OBJECT
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : 0x8233ac88 _DEVICE_OBJECT--设备链中的第一个设备
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf86e4000 Void
+0x010 DriverSize : 0xb900
+0x014 DriverSection : 0x822d6078 Void
+0x018 DriverExtension : 0x82339868 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\i8042prt"
+0x024 HardwareDatabase : 0x806727e0 _UNICODE_STRING
"\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf86ed285 long i8042prt!GsDriverEntry+0
+0x030 DriverStartIo : 0xf86e4910 void i8042prt!I8xStartIo+0
+0x034 DriverUnload : 0xf86eaeb6 void i8042prt!I8xUnload+0
+0x038 MajorFunction : [28] 0xf86e7aa6 long i8042prt!I8xCreate+0
第一个设备对象已经获得了,下面使用!devobj命令看看其具体信息
kd> !devobj 8233ac88
Device object (8233ac88) is for:
\Driver\i8042prt DriverObject 823397c0
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt 8233ad40 DevObjExt 8233afd0
ExtensionFlags (0000000000)
AttachedDevice (Upper) 81eafba0*** ERROR: Module load completed but symbols could not be loaded for
vmmouse.sys
\Driver\vmmouse--看起来有点像跟鼠标有关
AttachedTo (Lower) 822dc770 \Driver\ACPI
Device queue is not busy.
再来通过DEVICE_OBJECT找到下一个设备
kd> dt _DEVICE_OBJECT 8233ac88
ntdll!_DEVICE_OBJECT
+0x000 Type : 0n3
+0x002 Size : 0x348
+0x004 ReferenceCount : 0n0
+0x008 DriverObject : 0x823397c0 _DRIVER_OBJECT--所属的驱动对象正好是上面的那个i8042prt
+0x00c NextDevice : 0x822d7310 _DEVICE_OBJECT--下一个设备的地址
+0x010 AttachedDevice : 0x81eafba0 _DEVICE_OBJECT
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0x2004
+0x020 Characteristics : 0
+0x024 Vpb : (null)
+0x028 DeviceExtension : 0x8233ad40 Void
+0x02c DeviceType : 0x27
+0x030 StackSize : 5 ''
+0x034 Queue : __unnamed
+0x05c AlignmentRequirement : 0
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : (null)
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 1
+0x0b0 DeviceObjectExtension : 0x8233afd0 _DEVOBJ_EXTENSION
+0x0b4 Reserved : (null)
先看看下一个设备干嘛的吧
kd> !devobj 822d7310
Device object (822d7310) is for:
\Driver\i8042prt DriverObject 823397c0
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt 822d73c8 DevObjExt 822d7658
ExtensionFlags (0000000000)
AttachedDevice (Upper) 8212ceb8*** ERROR: Module load completed but symbols could not be loaded for
DKbFltr.sys--这里名字没有显示出来,不知哪里设置问题,不过看这个驱动好像是个过滤驱动
\Driver\DKbFltr
AttachedTo (Lower) 822dc888 \Driver\ACPI
Device queue is not busy.
看看具体信息
kd> dt _DEVICE_OBJECT 822d7310
ntdll!_DEVICE_OBJECT
+0x000 Type : 0n3
+0x002 Size : 0x348
+0x004 ReferenceCount : 0n0
+0x008 DriverObject : 0x823397c0 _DRIVER_OBJECT--所属驱动仍然是i8042prt
+0x00c NextDevice : (null) --设备链已经结束了
+0x010 AttachedDevice : 0x8212ceb8 _DEVICE_OBJECT
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0x2004
+0x020 Characteristics : 0
+0x024 Vpb : (null)
+0x028 DeviceExtension : 0x822d73c8 Void
+0x02c DeviceType : 0x27
+0x030 StackSize : 5 ''
+0x034 Queue : __unnamed
+0x05c AlignmentRequirement : 0
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : (null)
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 1
+0x0b0 DeviceObjectExtension : 0x822d7658 _DEVOBJ_EXTENSION
+0x0b4 Reserved : (null)
从这里我们知道了,这个驱动程序i8042prt创建了两个设备,这两个设备互相形成链式结构,这个链表以NULL表示
结束,驱动对象通过 +04 struct _DEVICE_OBJECT *DeviceObject 可以找到这个链。设备对象通过 +0c struct
_DEVICE_OBJECT *NextDevice 链在一起。设备对象通过 +08 struct _DRIVER_OBJECT *DriverObject 可以找到创建
它的驱动的驱动对象。
要想获得更多的信息,还要了解一下设备栈的概念,一个物理设备的驱动任务,通常由几个驱动程序一层一层的共同
完成。每层一个设备对象,他们联系在一起,组成一个设备栈。一个设备栈上的设备对象,从上自下,联系在一起。
从下自上,也联系在一起。还以上面的那个键盘驱动为例,继续探索下设备栈的相关东西。
/************************* 设备栈**************** ***********************************************/
使用命令!devstack可以观看设备栈中的内容
kd> !devstack 822d7310
!DevObj !DrvObj !DevExt ObjectName
8212a030 \Driver\Kbdclass 8212a0e8 KeyboardClass0
8212ceb8 \Driver\DKbFltr 8212cf70
> 822d7310 \Driver\i8042prt 822d73c8
822dc888 \Driver\ACPI 8239bea0 00000076
!DevNode 82130ca8 :
DeviceInst is "ACPI\PNP0303\4&cd4a22c&0"
ServiceName is "i8042prt"
其中只有两个驱动对象有名字\Driver\Kbdclass ,\Driver\ACPI
/************************************************************************************/
我们从上往下依次看
第一个:
kd> !devobj 8212a030
Device object (8212a030) is for:
KeyboardClass0 \Driver\Kbdclass DriverObject 81ebf858
Current Irp 00000000 RefCount 0 Type 0000000b Flags 00002044
Dacl e13b5f84 DevExt 8212a0e8 DevObjExt 8212a1c8
ExtensionFlags (0000000000)
AttachedTo (Lower) 8212ceb8 \Driver\DKbFltr
Device queue is not busy.
设备KeyboardClass0属于驱动\Driver\Kbdclass
kd> dt _DEVICE_OBJECT 8212a030
ntdll!_DEVICE_OBJECT
+0x000 Type : 0n3
+0x002 Size : 0x198
+0x004 ReferenceCount : 0n0
+0x008 DriverObject : 0x81ebf858 _DRIVER_OBJECT
+0x00c NextDevice : (null) --
+0x010 AttachedDevice : (null) --上面没有其他设备对象
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0x2044
+0x020 Characteristics : 0
+0x024 Vpb : (null)
+0x028 DeviceExtension : 0x8212a0e8 Void
+0x02c DeviceType : 0xb
+0x030 StackSize : 7 ''
+0x034 Queue : __unnamed
+0x05c AlignmentRequirement : 0
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : 0xe13b5f70 Void
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 0
+0x0b0 DeviceObjectExtension : 0x8212a1c8 _DEVOBJ_EXTENSION
+0x0b4 Reserved : (null)
通过设备扩展可以看到下面一层的设备
kd> dt _DEVICE_EXTENSION 8212a1c8
ACPI!_DEVICE_EXTENSION
+0x000 Flags : 0x8212a030`0000000d
+0x000 UFlags : __unnamed
+0x008 Signature : 0x10
+0x00c DebugFlags : 0
+0x010 DispatchTable : (null)
+0x014 WorkContext : WORK_QUEUE_CONTEXT
+0x014 Fdo : _FDO_DEVICE_EXTENSION
+0x014 Filter : _FILTER_DEVICE_EXTENSION
+0x014 Pdo : _PDO_DEVICE_EXTENSION
+0x058 WorkQueue : EXTENSION_WORKER
+0x058 Button : BUTTON_EXTENSION
+0x058 Thermal : THERMAL_EXTENSION
+0x058 LinkNode : LINK_NODE_EXTENSION
+0x058 Dock : DOCK_EXTENSION
+0x058 Processor : _PROCESSOR_DEVICE_EXTENSION
+0x088 DeviceState : 0 ( Stopped )
+0x08c PreviousState : 0 ( Stopped )
+0x090 PowerInfo : _ACPI_POWER_INFO
+0x10c DeviceID : (null)
+0x10c Address : 0
+0x110 InstanceID : (null)
+0x114 ResourceList : (null)
+0x118 PnpResourceList : (null)
+0x11c OutstandingIrpCount : 0n0
+0x120 ReferenceCount : 0n0
+0x124 HibernatePathCount : 0n0
+0x128 RemoveEvent : (null)
+0x12c AcpiObject : (null)
+0x130 DeviceObject : (null)
+0x134 TargetDeviceObject : (null)
+0x138 PhysicalDeviceObject : 0x00010008 _DEVICE_OBJECT
+0x13c ParentExtension : 0x7466744e _DEVICE_EXTENSION
+0x140 ChildDeviceList : _LIST_ENTRY [ 0xa030001 - 0x20616349 ]
+0x148 SiblingDeviceList : _LIST_ENTRY [ 0x40000 - 0x0 ]
+0x150 EjectDeviceHead : _LIST_ENTRY [ 0x8212a318 - 0x8212a318 ]
+0x158 EjectDeviceList : _LIST_ENTRY [ 0xa080003 - 0x7266744e ]
嘿嘿,刚才找了下strct这个命令怎么不能用,把F:\WINDDK\7600.16385.1\Debuggers\w2kfre下的kdex2x86.dll
直接拷贝到system32目录下,然后使用命令!kdex2x86.strct 就可以查看啦,似乎比dt命令简洁多了
看效果:
kd> !kdex2x86.strct DEVOBJ_EXTENSION 8212a1c8
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type = 000d
+02 uint16 Size = 0000
+04 struct _DEVICE_OBJECT *DeviceObject = 8212A030
+08 uint32 PowerFlags = 00000010
+0c *Dope = 00000000
+10 uint32 ExtensionFlags = 00000000
+14 void *DeviceNode = 00000000
+18 struct _DEVICE_OBJECT *AttachedTo = 8212CEB8--直接找到下一层设备了
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink = 00000000
+20 struct _LIST_ENTRY *Blink = 00000000
/***************************************************************************************/
第二个:依旧如前
kd> !devobj 8212ceb8
Device object (8212ceb8) is for:
\Driver\DKbFltr DriverObject 82339398
Current Irp 00000000 RefCount 0 Type 0000000b Flags 00002004
DevExt 8212cf70 DevObjExt 8212cfd0
ExtensionFlags (0000000000)
AttachedDevice (Upper) 8212a030 \Driver\Kbdclass
AttachedTo (Lower) 822d7310 \Driver\i8042prt
Device queue is not busy.
kd> !strct device_object 8212ceb8
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 0114
+04 int32 ReferenceCount = 00000000
+08 struct _DRIVER_OBJECT *DriverObject = 82339398
+0c struct _DEVICE_OBJECT *NextDevice = 81EBFCD8
+10 struct _DEVICE_OBJECT *AttachedDevice = 8212A030
+14 struct _IRP *CurrentIrp = 00000000
+18 struct _IO_TIMER *Timer = 00000000
+1c uint32 Flags = 00002004
+20 uint32 Characteristics = 00000000
+24 struct _VPB *Vpb = 00000000
+28 void *DeviceExtension = 8212CF70
+2c uint32 DeviceType = 0000000b
+30 char StackSize = 06 .
+34 union __unnamed62 Queue
+34 struct _LIST_ENTRY ListEntry
+34 struct _LIST_ENTRY *Flink = 00000000
+38 struct _LIST_ENTRY *Blink = 00000000
+34 struct _WAIT_CONTEXT_BLOCK Wcb
+34 struct _KDEVICE_QUEUE_ENTRY WaitQueueEntry
+34 struct _LIST_ENTRY DeviceListEntry
+34 struct _LIST_ENTRY *Flink = 00000000
+38 struct _LIST_ENTRY *Blink = 00000000
+3c uint32 SortKey = 00000000
+40 byte Inserted = 00 .
+44 function *DeviceRoutine = 00000000
+48 void *DeviceContext = 00000000
+4c uint32 NumberOfMapRegisters = 00000000
+50 void *DeviceObject = 00000000
+54 void *CurrentIrp = 00000000
+58 struct _KDPC *BufferChainingDpc = 00000000
+5c uint32 AlignmentRequirement = 00000000
+60 struct _KDEVICE_QUEUE DeviceQueue
+60 int16 Type = 0014
+62 int16 Size = 0014
+64 struct _LIST_ENTRY DeviceListHead
+64 struct _LIST_ENTRY *Flink = 8212CF1C
+68 struct _LIST_ENTRY *Blink = 8212CF1C
+6c uint32 Lock = 00000000
+70 byte Busy = 00 .
+74 struct _KDPC Dpc
+74 int16 Type = 0000
+76 byte Number = 00 .
+77 byte Importance = 00 .
+78 struct _LIST_ENTRY DpcListEntry
+78 struct _LIST_ENTRY *Flink = 00000000
+7c struct _LIST_ENTRY *Blink = 00000000
+80 function *DeferredRoutine = 00000000
+84 void *DeferredContext = 00000000
+88 void *SystemArgument1 = 00000000
+8c void *SystemArgument2 = 00000000
+90 uint32 *Lock = 00000000
+94 uint32 ActiveThreadCount = 00000000
+98 void *SecurityDescriptor = 00000000
+9c struct _KEVENT DeviceLock
+9c struct _DISPATCHER_HEADER Header
+9c byte Type = 00 .
+9d byte Absolute = 00 .
+9e byte Size = 00 .
+9f byte Inserted = 00 .
+a0 int32 SignalState = 00000000
+a4 struct _LIST_ENTRY WaitListHead
+a4 struct _LIST_ENTRY *Flink = 00000000
+a8 struct _LIST_ENTRY *Blink = 00000000
+ac uint16 SectorSize = 0000
+ae uint16 Spare1 = 0001
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension = 8212CFD0--设备扩展在这
+b4 void *Reserved = 00000000
观看下一层设备
kd> !strct devobj_extension 8212CFD0
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type = 000d
+02 uint16 Size = 0000
+04 struct _DEVICE_OBJECT *DeviceObject = 8212CEB8
+08 uint32 PowerFlags = 00000000
+0c *Dope = 00000000
+10 uint32 ExtensionFlags = 00000000
+14 void *DeviceNode = 00000000
+18 struct _DEVICE_OBJECT *AttachedTo = 822D7310--下一层设备在此
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink = 00000000
+20 struct _LIST_ENTRY *Blink = 00000000
/////////////.............................................................///////////////////////
看吧,跟上面设备栈描述的一模一样,下面的两个观察跟上面的一样了,下面总结一下
!DevObj !DrvObj !DevExt ObjectName
8212a030 \Driver\Kbdclass 8212a0e8 KeyboardClass0
8212ceb8 \Driver\DKbFltr 8212cf70
> 822d7310 \Driver\i8042prt 822d73c8
822dc888 \Driver\ACPI 8239bea0 00000076
从上至下:驱动对象\Driver\Kbdclass创建的设备/Device/KeyboardClass0从设备扩展中能够找到没有名字的
DKbFltr,驱动对象\Driver\DKbFltr创建的设备又可以找到没有名字的
i8042prt,驱动对象\Driver\i8042prt创建的设备又可以找到驱动对象\Driver\ACPI 创建的设备00000076
从下而上也是一样的,在我这理解为,同一个驱动创建的设备对象是成水平关联的,关联成一个设备链表结构。
而很多个功能驱动对象FDO为同一个物理驱动PDO对象服务,这些FDO所创建的设备分别附加到PDO上,形成垂直
结构,这应该就是过滤驱动的来源吧。整个键盘驱动的设备栈建立过程大概都了解了,我想整个过程可以这样说
驱动Kbdclass,驱动DKbFltr,驱动i8042prt分别创建附加设备到键盘设备栈中,而最底层的设备由ACPI 创建,这四个设备构成键盘设备栈。其中DKbFltr创建的设备是虚拟机独有的吗?不是太了解,有知道的跟我科普一下,另外初学WinDbg,命令繁多,不是太熟悉,附件里把常用命令集合在一起了,有需要的下下来。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法