一些 w10 的 NtQuerySystemInformation 问题

Problem with NtQuerySystemInformation with some w10

我正在处理外部代码,它是一款 MMORPG 游戏的反黑客软件。话虽这么说,代码在一些 Windows 10 个用户中出现崩溃或错误检测(它对 7 和 8.1 总是很好用),问题来自使用 NtQuerySystemInformation 然后比较进程句柄的函数。

感谢任何可以提供帮助或提供提示的人。 我会为你留下密码:

ProcessQuery.h

#pragma once

typedef LONG KPRIORITY;

typedef NTSTATUS(WINAPI*NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS,PVOID,ULONG,PULONG);

#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004)
#define STATUS_DATA_ERROR ((NTSTATUS)0xC000003E)
#define SystemExtendedProcessInformation ((SYSTEM_INFORMATION_CLASS)57)
#define SystemHandleInformation ((SYSTEM_INFORMATION_CLASS)16)
#define SystemExtendedHandleInformation ((SYSTEM_INFORMATION_CLASS)64)
#define SystemKernelDebuggerInformation ((SYSTEM_INFORMATION_CLASS)35)

enum THREAD_STATE
{
    Running = 2,
    Waiting = 5,
};

enum KWAIT_REASON
{
    Executive = 0,
    FreePage = 1,
    PageIn = 2,
    PoolAllocation = 3,
    DelayExecution = 4,
    Suspended = 5,
    UserRequest = 6,
    WrExecutive = 7,
    WrFreePage = 8,
    WrPageIn = 9,
    WrPoolAllocation = 10,
    WrDelayExecution = 11,
    WrSuspended = 12,
    WrUserRequest = 13,
    WrEventPair = 14,
    WrQueue = 15,
    WrLpcReceive = 16,
    WrLpcReply = 17,
    WrVirtualMemory = 18,
    WrPageOut = 19,
    WrRendezvous = 20,
    Spare2 = 21,
    Spare3 = 22,
    Spare4 = 23,
    Spare5 = 24,
    WrCalloutStack = 25,
    WrKernel = 26,
    WrResource = 27,
    WrPushLock = 28,
    WrMutex = 29,
    WrQuantumEnd = 30,
    WrDispatchInt = 31,
    WrPreempted = 32,
    WrYieldExecution = 33,
    WrFastMutex = 34,
    WrGuardedMutex = 35,
    WrRundown = 36,
    MaximumWaitReason = 37,
};

struct CLIENT_ID
{
    PVOID UniqueProcess;
    PVOID UniqueThread;
};

struct SYSTEM_THREAD_INFO
{
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER CreateTime;
    ULONG WaitTime;
    PVOID StartAddress;
    CLIENT_ID ClientId;
    KPRIORITY Priority;
    LONG BasePriority;
    ULONG ContextSwitches;
    ULONG ThreadState;
    KWAIT_REASON WaitReason;
};

struct SYSTEM_EXTENDED_THREAD_INFO
{
    SYSTEM_THREAD_INFO ThreadInfo;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID Win32StartAddress;
    PVOID TebAddress; // since VISTA
    ULONG Reserved1;
    ULONG Reserved2;
    ULONG Reserved3;
};

struct SYSTEM_PROCESS_INFO
{
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    LARGE_INTEGER WorkingSetPrivateSize; // since VISTA
    ULONG HardFaultCount; // since WIN7
    ULONG NumberOfThreadsHighWatermark; // since WIN7
    ULONGLONG CycleTime; // since WIN7
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    HANDLE InheritedFromUniqueProcessId;
    ULONG HandleCount;
    ULONG SessionId;
    ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG PageFaultCount;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    SIZE_T QuotaPeakPagedPoolUsage;
    SIZE_T QuotaPagedPoolUsage;
    SIZE_T QuotaPeakNonPagedPoolUsage;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER ReadOperationCount;
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;
    SYSTEM_THREAD_INFO Threads[1];
};

struct SYSTEM_EXTENDED_PROCESS_INFO
{
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    LARGE_INTEGER WorkingSetPrivateSize; // since VISTA
    ULONG HardFaultCount; // since WIN7
    ULONG NumberOfThreadsHighWatermark; // since WIN7
    ULONGLONG CycleTime; // since WIN7
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    HANDLE InheritedFromUniqueProcessId;
    ULONG HandleCount;
    ULONG SessionId;
    ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG PageFaultCount;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    SIZE_T QuotaPeakPagedPoolUsage;
    SIZE_T QuotaPagedPoolUsage;
    SIZE_T QuotaPeakNonPagedPoolUsage;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER ReadOperationCount;
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;
    SYSTEM_EXTENDED_THREAD_INFO Threads[1];
};

struct SYSTEM_HANDLE_ENTRY_INFO
{
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
};

struct SYSTEM_HANDLE_INFO
{
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_ENTRY_INFO Handles[1];
};

struct SYSTEM_HANDLE_ENTRY_INFO_EX
{
    PVOID Object;
    ULONG UniqueProcessId;
    ULONG HandleValue;
    ULONG GrantedAccess;
    USHORT CreatorBackTraceIndex;
    USHORT ObjectTypeIndex;
    ULONG HandleAttributes;
    ULONG Reserved;
};

struct SYSTEM_HANDLE_INFO_EX
{
    ULONG NumberOfHandles;
    ULONG Reserved;
    SYSTEM_HANDLE_ENTRY_INFO_EX Handles[1];
};

struct SYSTEM_KERNEL_DEBUGGER_INFO
{
    BOOLEAN DebuggerEnabled;
    BOOLEAN DebuggerNotPresent;
};

class CProcessQuery
{
public:
    CProcessQuery();
    virtual ~CProcessQuery();
    void Start();
    void Close();
    bool Fetch(SYSTEM_INFORMATION_CLASS SysInfoClass,DWORD QuerySize);
    SYSTEM_HANDLE_INFO* GetHandleInfo();
    SYSTEM_HANDLE_INFO_EX* GetExtendedHandleInfo();
    SYSTEM_KERNEL_DEBUGGER_INFO* GetKernelDebuggerInfo();
    SYSTEM_PROCESS_INFO* GetProcessInfoByID(HANDLE ProcessId);
    SYSTEM_EXTENDED_PROCESS_INFO* GetExtendedProcessInfoByID(HANDLE ProcessId);
    SYSTEM_THREAD_INFO* GetThreadInfoByID(SYSTEM_PROCESS_INFO* lpSystemProcessInfo,HANDLE ThreadId);
    SYSTEM_EXTENDED_THREAD_INFO* GetExtendedThreadInfoByID(SYSTEM_EXTENDED_PROCESS_INFO* lpSystemProcessInfo,HANDLE ThreadId);
public:
    static NTQUERYSYSTEMINFORMATION m_NtQuerySystemInformation;
private:
    BYTE* m_QueryData;
    DWORD m_QuerySize;
    NTSTATUS m_QueryStatus;
};

ProcessQuery.cpp:

void CProcessQuery::Start() // OK
{
    this->m_QueryData = 0;

    this->m_QuerySize = 0;

    this->m_QueryStatus = STATUS_SUCCESS;
}

void CProcessQuery::Close() // OK
{
    this->m_QueryData = ((this->m_QueryData==0)?(BYTE*)0:((HeapFree(GetProcessHeap(),0,this->m_QueryData)==0)?(BYTE*)0:(BYTE*)0));

    this->m_QuerySize = 0;

    this->m_QueryStatus = STATUS_SUCCESS;
}

bool CProcessQuery::Fetch(SYSTEM_INFORMATION_CLASS SysInfoClass,DWORD QuerySize) // OK
{
    while(this->m_QueryData != 0 || (this->m_QueryData=(BYTE*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(this->m_QuerySize=((this->m_QuerySize<QuerySize)?QuerySize:this->m_QuerySize)))) != 0)
    {
        DWORD ReturnLength;

        if((this->m_QueryStatus=CProcessQuery::m_NtQuerySystemInformation(SysInfoClass,this->m_QueryData,this->m_QuerySize,&ReturnLength)) == STATUS_INFO_LENGTH_MISMATCH)
        {
            this->m_QueryData = ((this->m_QueryData==0)?(BYTE*)0:((HeapFree(GetProcessHeap(),0,this->m_QueryData)==0)?(BYTE*)0:(BYTE*)0));
            this->m_QuerySize = ReturnLength;
        }
        else
        {
            return ((this->m_QueryStatus==STATUS_SUCCESS)?1:0);
        }
    }

    return 0;
}

SYSTEM_HANDLE_INFO* CProcessQuery::GetHandleInfo() // OK
{
    return ((SYSTEM_HANDLE_INFO*)this->m_QueryData);
}

SYSTEM_HANDLE_INFO_EX* CProcessQuery::GetExtendedHandleInfo() // OK
{
    return ((SYSTEM_HANDLE_INFO_EX*)this->m_QueryData);
}

SYSTEM_KERNEL_DEBUGGER_INFO* CProcessQuery::GetKernelDebuggerInfo() // OK
{
    return ((SYSTEM_KERNEL_DEBUGGER_INFO*)this->m_QueryData);
}

SYSTEM_PROCESS_INFO* CProcessQuery::GetProcessInfoByID(HANDLE ProcessId) // OK
{
    SYSTEM_PROCESS_INFO* lpSystemProcessInfo = (SYSTEM_PROCESS_INFO*)this->m_QueryData;

    while(true)
    {
        if(lpSystemProcessInfo->UniqueProcessId == ProcessId)
        {
            return lpSystemProcessInfo;
        }

        if(lpSystemProcessInfo->NextEntryOffset == 0)
        {
            break;
        }

        lpSystemProcessInfo = (SYSTEM_PROCESS_INFO*)((BYTE*)lpSystemProcessInfo+lpSystemProcessInfo->NextEntryOffset);
    }

    return 0;
}

SYSTEM_EXTENDED_PROCESS_INFO* CProcessQuery::GetExtendedProcessInfoByID(HANDLE ProcessId) // OK
{
    SYSTEM_EXTENDED_PROCESS_INFO* lpSystemProcessInfo = (SYSTEM_EXTENDED_PROCESS_INFO*)this->m_QueryData;

    while(true)
    {
        if(lpSystemProcessInfo->UniqueProcessId == ProcessId)
        {
            return lpSystemProcessInfo;
        }

        if(lpSystemProcessInfo->NextEntryOffset == 0)
        {
            break;
        }

        lpSystemProcessInfo = (SYSTEM_EXTENDED_PROCESS_INFO*)((BYTE*)lpSystemProcessInfo+lpSystemProcessInfo->NextEntryOffset);
    }

    return 0;
}

SYSTEM_THREAD_INFO* CProcessQuery::GetThreadInfoByID(SYSTEM_PROCESS_INFO* lpSystemProcessInfo,HANDLE ThreadId) // OK
{
    SYSTEM_THREAD_INFO* lpSystemThreadInfo = lpSystemProcessInfo->Threads;

    for(DWORD n=0;n < lpSystemProcessInfo->NumberOfThreads;n++,lpSystemThreadInfo++)
    {
        if(lpSystemThreadInfo->ClientId.UniqueThread == ThreadId)
        {
            return lpSystemThreadInfo;
        }
    }

    return 0;
}

SYSTEM_EXTENDED_THREAD_INFO* CProcessQuery::GetExtendedThreadInfoByID(SYSTEM_EXTENDED_PROCESS_INFO* lpSystemProcessInfo,HANDLE ThreadId) // OK
{
    SYSTEM_EXTENDED_THREAD_INFO* lpSystemThreadInfo = lpSystemProcessInfo->Threads;

    for(DWORD n=0;n < lpSystemProcessInfo->NumberOfThreads;n++,lpSystemThreadInfo++)
    {
        if(lpSystemThreadInfo->ThreadInfo.ClientId.UniqueThread == ThreadId)
        {
            return lpSystemThreadInfo;
        }
    }

    return 0;
}

扫描功能:

bool HANDLE_PROTECTION_INIT() // OK
{
    CProcessQuery ProcessQuery;

    HANDLE HandleValue = OpenProcess(PROCESS_VM_READ,0,GetCurrentProcessId());

    if(ProcessQuery.Fetch(SystemExtendedHandleInformation,sizeof(SYSTEM_HANDLE_INFO_EX)) != 0)
    {
        SYSTEM_HANDLE_INFO_EX* lpSystemHandleInfo = ProcessQuery.GetExtendedHandleInfo();

        if(lpSystemHandleInfo != 0)
        {
            SYSTEM_HANDLE_ENTRY_INFO_EX* lpSystemHandleEntryInfo = lpSystemHandleInfo->Handles;

            if(lpSystemHandleEntryInfo != 0)
            {
                for(DWORD n=0;n < lpSystemHandleInfo->NumberOfHandles;n++,lpSystemHandleEntryInfo++)
                {
                    if(lpSystemHandleEntryInfo->UniqueProcessId == GetCurrentProcessId() && lpSystemHandleEntryInfo->HandleValue == ((DWORD)HandleValue))
                    {
                        HandleProtectionNumber = (DWORD)lpSystemHandleEntryInfo->ObjectTypeIndex;
                        HandleProtectionObject = (DWORD)lpSystemHandleEntryInfo->Object;
                        ProcessQuery.Close();
                        return 1;
                    }
                }
            }
        }
    }

    ProcessQuery.Close();

    return 0;
}

bool HANDLE_PROTECTION_SCAN() // THIS FUNCTION IS CALLED IN A THREAD EVERY 2000 MS.
{
    if(gMemoryGuardSwitch == 0 || (gMemoryGuardNumber & MEMORY_GUARD_NUMBER_HANDLE) == 0)
    {
        return 1;
    }

    static CProcessQuery ProcessQuery;

    std::map<DWORD,std::vector<DWORD>> HandleProtectionTable;

    if(ProcessQuery.Fetch(SystemExtendedHandleInformation,sizeof(SYSTEM_HANDLE_INFO_EX)) != 0)
    {
        SYSTEM_HANDLE_INFO_EX* lpSystemHandleInfo = ProcessQuery.GetExtendedHandleInfo();

        if(lpSystemHandleInfo != 0)
        {
            SYSTEM_HANDLE_ENTRY_INFO_EX* lpSystemHandleEntryInfo = lpSystemHandleInfo->Handles;

            if(lpSystemHandleEntryInfo != 0)
            {
                for(DWORD n=0;n < lpSystemHandleInfo->NumberOfHandles;n++,lpSystemHandleEntryInfo++)
                {
                    if(lpSystemHandleEntryInfo->UniqueProcessId != GetCurrentProcessId() && lpSystemHandleEntryInfo->ObjectTypeIndex == HandleProtectionNumber && lpSystemHandleEntryInfo->Object == ((LPVOID)HandleProtectionObject) && (lpSystemHandleEntryInfo->GrantedAccess & PROCESS_VM_WRITE) != 0)
                    {
                        std::map<DWORD,std::vector<DWORD>>::iterator it = HandleProtectionTable.find(lpSystemHandleEntryInfo->UniqueProcessId);

                        if(it == HandleProtectionTable.end())
                        {
                            HandleProtectionTable.insert(std::pair<DWORD,std::vector<DWORD>>(lpSystemHandleEntryInfo->UniqueProcessId,std::vector<DWORD>(1,lpSystemHandleEntryInfo->HandleValue)));
                            continue;
                        }
                        else
                        {
                            if(it->second.size() >= MAX_HANDLE_PROTECTION_COUNT)
                            {
                                CGDetect(CLIENT_DISCONNECT_MEMORY_DETECTION, 0, 0);
                                //CHClientDisconnectSend(CLIENT_DISCONNECT_MEMORY_DETECTION,0,lpSystemHandleEntryInfo->UniqueProcessId);
                                return 0;
                            }
                            else
                            {
                                it->second.push_back(lpSystemHandleEntryInfo->HandleValue);
                                continue;
                            }
                        }
                    }
                }
            }
        }
    }

    return 1;
}

内存保护结构:

enum eMemoryGuardNumber
{
    MEMORY_GUARD_NUMBER_NONE = 0,
    MEMORY_GUARD_NUMBER_HANDLE = 1,
    MEMORY_GUARD_NUMBER_INJECT = 2,
};
if(IsWindows10OrGreater)
    {
        DWORD gMemoryGuardNumber = 8;
    }
    else
    {
        DWORD gMemoryGuardNumber = 3;
    }

好吧,万一对某人有用,问题是 handlecount 如果 w7 与 w10 不同...必须在 w10 中放置最多 12 才能正确使用