• _KWAIT_BLOCK使用时遇到的问题


    最近在写代码的时候遇到一个问题,就是_KWAIT_BLOCK中的取出来的Kthread取出来的数据是有问题的。

    首先了解一下_KWAIT_BLOCK是什么东西,这个结构体是挂在_Kevent下面的Header,这个header只要是可等待对象都会有这个结构体(能够被wiatforsingleobject等待的都是可等待对象),这个header最后一个字段里面有一个双向链表指向这个事件的Kwait_block这个结构体,同时这个结构体会挂在正在等待的线程的KWAIT_BLOCK这个字段上,我们可以通过Kwait_block的thread字段得到是哪个线程在等待这个事件。

    typedef struct _KEVENT {
        DISPATCHER_HEADER Header;
    } KEVENT, *PKEVENT, *PRKEVENT;
    
    typedef struct _DISPATCHER_HEADER {
        union {
            union {
                volatile LONG Lock;
                LONG LockNV;
            } DUMMYUNIONNAME;
    
            struct {                            // Events, Semaphores, Gates, etc.
                UCHAR Type;                     // All (accessible via KOBJECT_TYPE)
                UCHAR Signalling;
                UCHAR Size;
                UCHAR Reserved1;
            } DUMMYSTRUCTNAME;
    
            struct {                            // Timer
                UCHAR TimerType;
                union {
                    UCHAR TimerControlFlags;
                    struct {
                        UCHAR Absolute : 1;
                        UCHAR Wake : 1;
                        UCHAR EncodedTolerableDelay : TIMER_TOLERABLE_DELAY_BITS;
                    } DUMMYSTRUCTNAME;
                };
    
                UCHAR Hand;
                union {
                    UCHAR TimerMiscFlags;
                    struct {
    
    #if !defined(KENCODED_TIMER_PROCESSOR)
    
                        UCHAR Index : TIMER_EXPIRED_INDEX_BITS;
    
    #else
    
                        UCHAR Index : 1;
                        UCHAR Processor : TIMER_PROCESSOR_INDEX_BITS;
    
    #endif
    
                        UCHAR Inserted : 1;
                        volatile UCHAR Expired : 1;
                    } DUMMYSTRUCTNAME;
                } DUMMYUNIONNAME;
            } DUMMYSTRUCTNAME2;
    
            struct {                            // Timer2
                UCHAR Timer2Type;
                union {
                    UCHAR Timer2Flags;
                    struct {
                        UCHAR Timer2Inserted : 1;
                        UCHAR Timer2Expiring : 1;
                        UCHAR Timer2CancelPending : 1;
                        UCHAR Timer2SetPending : 1;
                        UCHAR Timer2Running : 1;
                        UCHAR Timer2Disabled : 1;
                        UCHAR Timer2ReservedFlags : 2;
                    } DUMMYSTRUCTNAME;
                } DUMMYUNIONNAME;
    
                UCHAR Timer2ComponentId;
                UCHAR Timer2RelativeId;
            } DUMMYSTRUCTNAME3;
    
            struct {                            // Queue
                UCHAR QueueType;
                union {
                    UCHAR QueueControlFlags;
                    struct {
                        UCHAR Abandoned : 1;
                        UCHAR DisableIncrement : 1;
                        UCHAR QueueReservedControlFlags : 6;
                    } DUMMYSTRUCTNAME;
                } DUMMYUNIONNAME;
    
                UCHAR QueueSize;
                UCHAR QueueReserved;
            } DUMMYSTRUCTNAME4;
    
            struct {                            // Thread
                UCHAR ThreadType;
                UCHAR ThreadReserved;
    
                union {
                    UCHAR ThreadControlFlags;
                    struct {
                        UCHAR CycleProfiling : 1;
                        UCHAR CounterProfiling : 1;
                        UCHAR GroupScheduling : 1;
                        UCHAR AffinitySet : 1;
                        UCHAR Tagged : 1;
                        UCHAR EnergyProfiling: 1;
                        UCHAR SchedulerAssist: 1;
    
    #if !defined(_X86_)
    
                        UCHAR ThreadReservedControlFlags : 1;
    
    #else
    
                        UCHAR Instrumented : 1;
    
    #endif
    
                    } DUMMYSTRUCTNAME;
                } DUMMYUNIONNAME;
    
                union {
                    UCHAR DebugActive;
    
    #if !defined(_X86_)
    
                    struct {
                        BOOLEAN ActiveDR7 : 1;
                        BOOLEAN Instrumented : 1;
                        BOOLEAN Minimal : 1;
                        BOOLEAN Reserved4 : 3;
                        BOOLEAN UmsScheduled : 1;
                        BOOLEAN UmsPrimary : 1;
                    } DUMMYSTRUCTNAME;
    
    #endif
    
                } DUMMYUNIONNAME2;
            } DUMMYSTRUCTNAME5;
    
            struct {                         // Mutant
                UCHAR MutantType;
                UCHAR MutantSize;
                BOOLEAN DpcActive;
                UCHAR MutantReserved;
            } DUMMYSTRUCTNAME6;
        } DUMMYUNIONNAME;
    
        LONG SignalState;                   // Object lock
        LIST_ENTRY WaitListHead;            // Object lock
    } DISPATCHER_HEADER, *PDISPATCHER_HEADER;
    
    typedef struct _LIST_ENTRY {
       struct _LIST_ENTRY *Flink;
       struct _LIST_ENTRY *Blink;
    } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

    基本了解要干什么之后,分析一下为什么会出现这个问题

    看一下_KWAIT_BLOCK在ddk 7.1的定义,通常为了兼容都会选择比较低的版本。

    typedef struct _KWAIT_BLOCK
    {
         LIST_ENTRY WaitListEntry;
         PKTHREAD Thread;
         PVOID Object;
         PKWAIT_BLOCK NextWaitBlock;
         WORD WaitKey;
         UCHAR WaitType;
         UCHAR SpareByte;
    } KWAIT_BLOCK, *PKWAIT_BLOCK;

    可以看到如果是x64模式下+0x10的位置就是线程结构体的偏移;但是打开最新的wdk可以看到这个结构体发生了变化。

    typedef struct _KWAIT_BLOCK {
        LIST_ENTRY WaitListEntry;
        UCHAR WaitType;
        volatile UCHAR BlockState;
        USHORT WaitKey;
    
    #if defined(_WIN64)
    
        LONG SpareLong;
    
    #endif
    
        union {
            struct _KTHREAD *Thread;
            struct _KQUEUE *NotificationQueue;
        };
    
        PVOID Object;
        PVOID SparePtr;
    
    } KWAIT_BLOCK, *PKWAIT_BLOCK, *PRKWAIT_BLOCK;

    可以看到在原来的基础上多了一个字段,所以导致+0x10的位置不在是线程结构体了。

    最后在网上找到了对比图在win7 sp1之后就发生了变化,对应版本就是nt6.2开始,也就是win8

     
  • 相关阅读:
    ES6基础之——对象表达式
    ES6基础之——函数的名字name属性
    ES6基础之——解构参数 Destructured Parameters
    ES6基础之——展开操作符Spread和剩余操作符Rest
    ES6基础之——箭头函数Arrow Fuctions
    ES6基础——默认参数 Default Parameter Values
    node.js 调用第三方服务
    node 创建server 及加载静态页面
    VUE插件-图片濑加载
    Less函数说明
  • 原文地址:https://www.cnblogs.com/csnd/p/16675597.html
Copyright © 2020-2023  润新知