与调试相关的系统级函数

PEB相关
 
#include 
#include 
bool PEB_BeingDebugged()
{
    bool BeingDebugged = false;
    _asm
    {
        mov eax, dword ptr fs : [0x30];//dt _PEB
        mov al, byte ptr ds : [eax + 0x02];//BeingDebugged
        mov BeingDebugged, al;
    }
    return BeingDebugged;
}
int main()
{
    bool bDebug = false;
    bDebug = PEB_BeingDebugged();//等价于IsDebuggerPresent()
    printf("%d\n", bDebug);
    system("pause");
    return 0;
}

  • ProcessHeap的Flags与ForceFlags正常情况下为2与0,处于调试态会发生改变,此方法在NT 5.x版本以上无效。
 
#include 
#include 
bool PEB_ProcessHeap()
{
    int nFlags = 0;
    int nForceFlags = 0;
    _asm
    {
        PUSHAD;
        mov eax, dword ptr FS : [0x30];
        mov eax, dword ptr ds : [eax + 0x18];
        mov ebx, dword ptr ds : [eax + 0x0c];
        mov ecx, dword ptr ds : [eax + 0x10];
        mov nFlags, ebx;
        mov nForceFlags, ecx;
        POPAD;
    }
    return (nFlags == 2 && nForceFlags == 0) ? false : true;
}
int main()
{
    bool bDebug = false;
    bDebug = PEB_ProcessHeap();
    printf("%d\n", bDebug);
    system("pause");
    return 0;
}

  • NtGlobalFlag在当前进程处于调试状态时的值为0x70
 
#include 
#include 
bool PEB_NtGlobalFlag()
{
    int nNtGlobalFlag = 0;
    _asm
    {
        mov eax, dword ptr fs:[0x30];
        mov eax, dword ptr ds : [eax + 0x68];
        mov nNtGlobalFlag, eax;
    }
    return (nNtGlobalFlag != 0x70) ? false : true;
}
int main()
{
    bool bDebug = false;
    bDebug = PEB_NtGlobalFlag();
    printf("%d\n", bDebug);
    system("pause");
    return 0;
}

  • NtQueryInformationProcess-ProcessDebugPort,如果目标进程处于未调试状态,端口为0,否则为0xFFFFFFFF
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQIP_ProcessDebug()
{
    int nDebugPort = 0;
    NtQueryInformationProcess(
        GetCurrentProcess(),
        ProcessDebugPort,
        &nDebugPort,
        sizeof(nDebugPort),
        NULL);
    return nDebugPort == 0xFFFFFFFF ? true : false;
}
int main()
{
    bool nDebug = false;
    nDebug = NQIP_ProcessDebug();
    printf("%d\n", nDebug);
    system("pause");
    return 0;
}

  • ProcessDebugObjectHandle可以获取目标进程的调试对象句柄,如果未处于调试状态,则获取的值为NULL
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQIP_ProcessDebugObjectHandle()
{
    HANDLE hDebug = NULL;
    NtQueryInformationProcess(
        GetCurrentProcess(),
        (PROCESSINFOCLASS)0x1E,
        &hDebug,
        sizeof(hDebug),
        NULL);
    return hDebug? true : false;
}
int main()
{
    bool nDebug = false;
    nDebug = NQIP_ProcessDebugObjectHandle();
    printf("%d\n", nDebug);
    system("pause");
    return 0;
}

  • ProcessDebugFlag可获取目标进程的调试标记,若处于调试状态值为0,否则为1
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQIP_ProcessDebugFlag()
{
    BOOL bDebugFlag = FALSE;
    NtQueryInformationProcess(
        GetCurrentProcess(),
        (PROCESSINFOCLASS)0x1F,
        &bDebugFlag,
        sizeof(bDebugFlag),
        NULL);
    return bDebugFlag ? false : true;
}
int main()
{
    bool nDebug = false;
    nDebug = NQIP_ProcessDebugFlag();
    printf("%d\n", nDebug);
    system("pause");
    return 0;
}

  • 可获取指定进程的父进程PID,将其与Explorer.exe的PID对比,不匹配则不是被双击运行的。
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQIP_CheckParentProcess()
{
    struct PROCESS_BASIC_INFORMATION
    {
        ULONG ExitStatus;//进程返回码
        PPEB PebBaseAddress;//PEB地址
        ULONG AffinityMask;//CPU亲和性掩码
        LONG BasePriority;//基本优先级
        ULONG UniqueProcessId;//本进程PID
        ULONG InheritedFromUniqueProcessId;//父进程PID
    }stcProcInfo;
    NtQueryInformationProcess(
        GetCurrentProcess(),
        ProcessBasicInformation,
        &stcProcInfo,
        sizeof(stcProcInfo),
        NULL);
    DWORD dwExplorerPID = 0;
    DWORD dwCurrentPID = stcProcInfo.InheritedFromUniqueProcessId;
    GetWindowThreadProcessId(FindWindow("explorer.exe", NULL), &dwExplorerPID);
    return dwExplorerPID == dwCurrentPID ? false : true;
}
int main()
{
    bool nDebug = false;
    nDebug = NQIP_CheckParentProcess();
    printf("%d\n", nDebug);
    system("pause");
    return 0;
}

  • NtQuerySystemInformation()可获取当前系统是否开启调试模式
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQSI_SystemKernelDebuggerInformation()
{
    struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
    {
        BOOLEAN DebuggerEnabled;
        BOOLEAN DebuggerNotPresent;
    }DebuggerInfo = {0};
    NtQuerySystemInformation(
        (SYSTEM_INFORMATION_CLASS)0x23,
        &DebuggerInfo,
        sizeof(DebuggerInfo),
        NULL);
    return DebuggerInfo.DebuggerEnabled;
}
int main()
{
    BOOLEAN bDebug = FALSE;
    bDebug = NQSI_SystemKernelDebuggerInformation();
    printf("%d\n", bDebug);
    system("pause");
    return 0;
}

  • NtQueryObject
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
bool NQO_NtQueryObject()
{
    typedef struct _OBJECT_TYPE_INFORMATION
    {
        UNICODE_STRING TypeName;
        ULONG TotalNumberOfHandlers;
        ULONG TotalNumberOfObjects;
    }OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
    typedef struct _OBJECT_ALL_INFORMATION
    {
        ULONG NumberOfObjectTypes;
        OBJECT_TYPE_INFORMATION ObjTypeInfo[1];
    }OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION;
    ULONG uSize = 0;
    NtQueryObject(NULL, (OBJECT_INFORMATION_CLASS)0x03, &uSize, sizeof(uSize), &uSize);
    POBJECT_ALL_INFORMATION pObj = (POBJECT_ALL_INFORMATION)new BYTE[uSize];
    NtQueryObject(NULL, (OBJECT_INFORMATION_CLASS)0x03, pObj, uSize, &uSize);
    POBJECT_TYPE_INFORMATION pObjTypeInfo = pObj->ObjTypeInfo;
    for (int i = 0; i < pObj->NumberOfObjectTypes; ++i)
    {
        if (!wcscmp(L"DebugObject", pObjTypeInfo->TypeName.Buffer))return true;
        //获取对象名占用空间大小
        ULONG uNameLength = pObjTypeInfo->TypeName.Length;
        ULONG uDataLength = uNameLength - uNameLength % sizeof(ULONG) + sizeof(ULONG);
        //指向下一个对象
        pObjTypeInfo = (POBJECT_TYPE_INFORMATION)pObjTypeInfo->TypeName.Buffer;
        pObjTypeInfo = (POBJECT_TYPE_INFORMATION)((PBYTE)pObjTypeInfo + uDataLength);
    }
    delete[] pObj;
    return false;
}
int main()
{
    bool bDebug = false;
    bDebug = NQO_NtQueryObject();
    printf("%d\n", bDebug);
    system("pause");
    return 0;
}

  • ZwSetInformationThread,此函数可以主动脱离调试器,这个碉堡了。
 
#include 
#include 
#pragma comment(lib,"ntdll.lib")
#include 
typedef enum THREAD_INFO_CLASS
{ ThreadHideFromDebugger = 17 };
typedef NTSTATUS(NTAPI *ZW_SET_INFORMATION_THREAD)
(
_In_ HANDLE ThreadHandle,
_In_ THREAD_INFO_CLASS ThreadInformationClass,
_In_ PVOID ThreadInformation,
_In_ ULONG ThreadInformationLength
);
void ZSIT_DetachDebug()
{
    ZW_SET_INFORMATION_THREAD Func;
    Func = (ZW_SET_INFORMATION_THREAD)GetProcAddress(LoadLibrary("ntdll.dll"), "ZwSetInformationThread");
    Func(GetCurrentThread(), ThreadHideFromDebugger, NULL, NULL);
}
int main()
{
    ZSIT_DetachDebug();
    return 0;
}

你可能感兴趣的:(与调试相关的系统级函数)