8.3 NtGlobalFlag

ntglobalflag · 浏览次数 : 7

小编点评

**NtGlobalFlag 反调试方法** 1. **定位 TEB 和 PEB 结构:** - 使用汇编代码读取 TEB 的基地址。 - 通过 TEB 找到 PEB 的结构。 2. **获取 NtGlobalFlag 值:** - 从 PEB 结构中获取 `+0x068` 位的 `NtGlobalFlag` 值。 3. **判断程序是否被调试:** - 如果 `NtGlobalFlag` 为 `0x70`,则程序被调试。 **使用示例:** ```c #include #include // 声明 ZwQueryInformationProcess 函数 typedef NTSTATUS(NTAPI *typedef_ZwQueryInformationProcess)( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL ); int main() { // 获取进程句柄 HANDLE hProcess = GetCurrentProcessId(); // 加载 NTDLL 模块 HMODULE hModule = LoadLibrary("ntdll.dll"); // 获取 ZwQueryInformationProcess 函数地址 typedef_ZwQueryInformationProcess pZwQueryInformationProcess = (typedef_ZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess"); // 获取 PEB 结构 PROCESS_BASIC_INFORMATION Pbi; pZwQueryInformationProcess( hProcess, ProcessBasicInformation, &Pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL ); // 读取调试标志并判断 DWORD ByteRead = 0; WORD NtGlobalFlag = 0; ULONG PebBase = (ULONG)Pbi.PebBaseAddress; if (ReadProcessMemory(hProcess, (LPVOID)(PebBase + 0x68), &NtGlobalFlag, 2, &ByteRead) && ByteRead == 2) { if (NtGlobalFlag == 0x70) { // 程序被调试 printf("[*] 程序正在被调试 \\n"); } } // 关闭模块和进程句柄 FreeLibrary(hModule); CloseHandle(hProcess); return 0; } ``` **注意:** - 使用 `NtGlobalFlag` 反调试需要谨慎,因为它可能影响系统的正常运行。 - 代码仅供参考,可能需要根据实际情况进行修改。

正文

NtGlobalFlag 是一个Windows内核全局标记,在Windows调试方案中经常用到。这个标记定义了一组系统的调试参数,包括启用或禁用调试技术的开关、造成崩溃的错误代码和处理方式等等。通过改变这个标记,可以在运行时设置和禁用不同的调试技术和错误处理方式,比如调试器只能访问当前进程、只允许用户模式调试、启用特定的错误处理方式等等。但由于NtGlobalFlag标记是内核全局标记,其改变会影响整个系统的行为,需要谨慎处理。

利用该标记反调试,首先定位dt -rv ntdll!_TEB找到TEB结构并通过TEB找到PEB结构,然后找到+0x068 NtGlobalFlag,这个位置的NtGlobalFlag类似于BeingDebugged,如果是调试状态NtGlobalFlag的值会是0x70,所以可以判断这个标志是否为0x70来判断程序是否被调试了,首先我们来使用汇编代码解决。

#include <stdio.h>
#include <windows.h>

// 返回调试状态
BOOL IsDebug()
{
    DWORD Debug = 0;
    __asm
    {
        mov eax, fs:[0x18]       // TEB基地址
        mov eax, [eax + 0x30]    // 找到PEB
        mov eax, [eax + 0x68]    // 找打 NtGlobalFlag
        mov Debug, eax           // 取出值
    }

    if (Debug == 112)
    {
        return TRUE;
    }

    return FALSE;
}

int main(int argc, char * argv[])
{

    if (IsDebug)
    {
        printf("[-] 程序正在被调试 \n");
    }
    else
    {
        printf("[*] 程序正常 \n");
    }

    system("pause");
    return 0;
}

当然除了使用纯汇编实现反调试外,我们也可以使用NativeAPI中的ZwQueryInformationProcess()这个函数来读取到程序中的PET数据,然后判断PebBase+0x68是否等于70,由于这个函数并没有公开,所以在使用时应该自行声明一下结构类型。

#include <stdio.h>
#include <windows.h>
#include <winternl.h>

// 声明该函数
typedef NTSTATUS(NTAPI *typedef_ZwQueryInformationProcess)(
    IN HANDLE ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );

// 调试状态检测
BOOL IsDebug()
{
    HANDLE hProcess = NULL;
    DWORD ProcessId = 0;
    PROCESS_BASIC_INFORMATION Pbi;
    typedef_ZwQueryInformationProcess pZwQueryInformationProcess = NULL;
    ProcessId = GetCurrentProcessId();
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);

    if (hProcess != NULL)
    {
        HMODULE hModule = LoadLibrary("ntdll.dll");
        pZwQueryInformationProcess = (typedef_ZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess");

        NTSTATUS Status = pZwQueryInformationProcess(hProcess, ProcessBasicInformation, &Pbi,sizeof(PROCESS_BASIC_INFORMATION), NULL);
        if (NT_SUCCESS(Status))
        {
            DWORD ByteRead = 0;
            WORD NtGlobalFlag = 0;
            ULONG PebBase = (ULONG)Pbi.PebBaseAddress;

            // 读取调试标志并判断
            if (ReadProcessMemory(hProcess, (LPCVOID)(PebBase + 0x68), &NtGlobalFlag, 2, &ByteRead) && ByteRead == 2)
            {
                if (NtGlobalFlag == 0x70)
                {
                    return TRUE;
                }
            }
        }
        CloseHandle(hProcess);
    }

    return FALSE;
}

int main(int argc, char * argv[])
{
    if (IsDebug() == TRUE)
    {
        printf("[-] 进程正在被调试 \n");
    }
    else
    {
        printf("[*] 程序正常 \n");
    }

    system("pause");
    return 0;
}

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/e45d84be.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

与8.3 NtGlobalFlag相似的内容:

8.3 NtGlobalFlag

NtGlobalFlag 是一个`Windows`内核全局标记,在`Windows`调试方案中经常用到。这个标记定义了一组系统的调试参数,包括启用或禁用调试技术的开关、造成崩溃的错误代码和处理方式等等。通过改变这个标记,可以在运行时设置和禁用不同的调试技术和错误处理方式,比如调试器只能访问当前进程、只允许用户模式调试、启用特定的错误处理方式等等。但由于`NtGlobalFlag`标记是内核全局标记

.NET周刊【8月第3期 2023-08-20】

## 国内主题 ### 抓的是周树人,与我鲁迅有什么关系? https://www.cnblogs.com/JulianHuang/p/17642511.html - **问题**:作者看到了一个关于Dictionary.Clear和new Dictionary的问题,想要探究为什么在foreach

Rancher 系列文章-RHEL7.8 离线有代理条件下安装单节点 Rancher

一 基础信息 1.1 前提 本次安装的为 20220129 最新版:Rancher v2.6.3 VM 版本为 RHEL 7.8, 7.9 或 8.2, 8.3, 8.4(Rancher 官网要求) VM YUM 仓库:已配置对应版本的 RHEL 和 EPEL YUM 仓库 VM 提供 root 权

[转帖]skywalking配置nacos集群模式

版本: nameversionnacos1.1.0skywalking6.2.0elasticsearch6.3.2 es集群管理工具 cerebro-0.8.3 https://github.com/lmenezes/cerebro 前置: es、nacos至少各有一个 1 开始: 1.将 apa

K3S 系列文章-RHEL7.8 离线有代理条件下安装 K3S

一 基础信息 1.1 前提 本次安装的为 k3s 1.21.7+k3s1 VM 版本为 RHEL 7.8, 7.9 或 8.2, 8.3, 8.4(K3s 官网要求) VM YUM 仓库:已配置对应版本的 RHEL 和 EPEL YUM 仓库 VM 提供 root 权限 已配置 ntp(防止因为时间

Unity开发Hololens2—交互发布配置

> 博客地址:https://www.cnblogs.com/zylyehuo/ ## 环境配置 ```bash unity2021.3.15f visual studio 2019 pro MRTK 2.8.3 OpenXR 1.8.0 Hololens2 ``` > Hololens2 环境配置

STM32 + RT-Thread + LVGL

一、基本信息 MCU:STM32F103ZET6 RT-Thread:5.0.2 LVGL:8.3.11 LCD:ST7735s 编译环境:RTThread studio 二、LVGL 移植要求 16、32或64位微控制器或处理器 建议速度大于16 MHz 闪存/ROM: > 64 kB(建议180

[转帖]JVM性能提升50%,聊一聊背后的秘密武器Alibaba Dragonwell

https://zhuanlan.zhihu.com/p/453437019 今年四月五日,阿里云开放了新一代ECS实例的邀测[1],Alibaba Dragonwell也在新ECS上进行了极致的优化。相比于之前的dragonwell_11.0.8.3版本,即将发布的dragonwell_11.0.

python基础环境

刚开始接触并学习一门开发语言,带着不求甚解的想法,其实也挺有好处的:我并不是所有的东西都知道,但是代码跑起来了。 但是时间久了,还是带着这种想法,可能就会遇到一些棘手的问题。比如电脑上不知不觉已经安装了多个python版本,python3.8/3.10/3.11,甚至一些软件中也集成有python解

[转帖]3.3.8. KWR运行期对比报告 KWR DIFF

https://help.kingbase.com.cn/v8/perfor/performance-optimization/performance-optimization-6.html#sys-ksh KWR报告是Diff报告的基础,在数据库运行过程中,通常在业务的高峰期和低谷期,或者在参数调