CTF-RE 从0到N: windows反调试-获取Process Environment Block(PEB)信息来检测调试

news/2024/11/14 11:59:03/

在Windows操作系统中,Process Environment Block (PEB,进程环境块) 是一个包含特定进程信息的数据结构。它可以被用于反调试中

如何获取PEB指针?

在Windows操作系统中,获取PEB指针的常见方法主要有以下几种。:

1. 使用 NtCurrentPeb 获取 PEB

NtCurrentPeb 是Windows内核提供的一个函数,它返回当前进程的PEB指针。这个方法通常用于内核模式或通过非公开的API调用。在用户模式中,你可以使用 NtCurrentPeb 来获取PEB指针。

PEB* GetPEB()
{return NtCurrentPeb();  // 获取当前进程的PEB指针
}

NtCurrentPeb 是Windows的NT内核函数,通常不公开给用户模式程序直接调用,但可以通过动态加载 ntdll.dll 并使用 GetProcAddress 来调用。

2. 使用 NtQueryInformationProcess 获取 PEB

通过 NtQueryInformationProcess 函数,可以查询关于进程的信息,其中包括PEB的指针。这是通过NT内部函数来实现的。

#include <Windows.h>
#include <winternl.h>typedef struct _PROCESS_BASIC_INFORMATION {ULONG Reserved;ULONG PebBaseAddress;  // PEB的地址ULONG AffinityMask;ULONG BasePriority;ULONG UniqueProcessId;ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;typedef NTSTATUS(WINAPI* NtQueryInformationProcess_t)(HANDLE ProcessHandle,PROCESS_INFORMATION_CLASS ProcessInformationClass,PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength
);PEB* GetPEB(HANDLE hProcess)
{NtQueryInformationProcess_t NtQueryInformationProcess =(NtQueryInformationProcess_t)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess");PROCESS_BASIC_INFORMATION pbi;ULONG len = 0;NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &len);if (NT_SUCCESS(status)){return (PEB*)pbi.PebBaseAddress;}return NULL;
}

:此方法需要依赖动态加载 ntdll.dll,并调用 NtQueryInformationProcess 函数。这个函数是Windows的NT内核接口,返回关于进程的详细信息。

3. 直接通过 NtQueryInformationProcess 查询 PEB 地址

也可以通过调用 NtQueryInformationProcess 来获取进程的PEB地址。你可以查询有关进程的基本信息,其中就包含PEB的地址。

#include <windows.h>
#include <winternl.h>typedef enum _PROCESSINFOCLASS {ProcessBasicInformation = 0
} PROCESSINFOCLASS;typedef struct _PROCESS_BASIC_INFORMATION {ULONG Reserved;ULONG PebBaseAddress; // PEB地址ULONG AffinityMask;ULONG BasePriority;ULONG UniqueProcessId;ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;typedef NTSTATUS(WINAPI* NtQueryInformationProcess_t)(HANDLE ProcessHandle,PROCESSINFOCLASS ProcessInformationClass,PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength
);PEB* GetPEB(HANDLE processHandle)
{PROCESS_BASIC_INFORMATION pbi;ULONG len = 0;NtQueryInformationProcess_t NtQueryInformationProcess = (NtQueryInformationProcess_t)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationProcess");NTSTATUS status = NtQueryInformationProcess(processHandle, ProcessBasicInformation, &pbi, sizeof(pbi), &len);if (NT_SUCCESS(status)){return (PEB*)pbi.PebBaseAddress;}return NULL;
}

检测PEB的哪些位置来检测调试?

  1. 检查BeingDebugged标志:

    • PEB结构中的BeingDebugged字段直接指示进程是否正在被调试。该字段是一个布尔值,当进程在调试器下运行时,它的值为1,否则为0。
    BOOL IsDebuggerPresent()
    {PEB* peb = (PEB*)__readfsdword(0x30); // 获取PEB地址return peb->BeingDebugged; // 返回BeingDebugged字段的值
    }
    
  2. 检查NtGlobalFlag标志:

    • PEB中的NtGlobalFlag字段包含一些系统标志,其中某些标志在进程被调试器附加时会被设置。例如,FLG_HEAP_ENABLE_TAIL_CHECK, FLG_HEAP_ENABLE_FREE_CHECKFLG_HEAP_VALIDATE_PARAMETERS 会在调试器附加时被设置。
    BOOL CheckNtGlobalFlag()
    {PEB* peb = (PEB*)__readfsdword(0x30); // 获取PEB地址DWORD NtGlobalFlag = peb->NtGlobalFlag;return (NtGlobalFlag & 0x70) != 0; // 检查特定的调试标志
    }
    
  3. 检查Heap Flags和ForceFlags:

    • 调试器通常会修改PEB中的Heap Flags和ForceFlags,以启用更严格的堆检查。在PEB中的ProcessHeap字段指向进程的默认堆,这些标志位于该堆结构中。
    BOOL CheckHeapFlags()
    {PEB* peb = (PEB*)__readfsdword(0x30); // 获取PEB地址PVOID heap = peb->ProcessHeap; // 获取默认堆地址DWORD heapFlags = *(DWORD*)((BYTE*)heap + 0x40);DWORD forceFlags = *(DWORD*)((BYTE*)heap + 0x44);return (heapFlags & 2) || (forceFlags != 0);
    }
    
  4. 通过PEB中的StartupInfo检查调试器:

    • PEB中的StartupInfo结构包含有关进程启动的详细信息。可以通过检查StartupInfo中的特定字段来判断是否有调试器存在。
    BOOL CheckStartupInfo()
    {PEB* peb = (PEB*)__readfsdword(0x30); // 获取PEB地址STARTUPINFO* startupInfo = &peb->ProcessParameters->StartupInfo;return startupInfo->dwFlags & STARTF_FORCEONFEEDBACK; // 检查特定标志
    }
    

示例crackMe

以下是反调试代码的反编译示例

if ( *((_DWORD *)NtCurrentPeb()->ProcessHeap + 3) != 2 )a2[v6] = 34;
if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )v12 = v10 + v11;
if ( (unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{v10 = -83;v11 = 43;
}

http://www.ppmy.cn/news/1546595.html

相关文章

Chromium 中chrome.system.display扩展接口定义c++

一、chrome.system.display 使用 system.display API 查询展示元数据。 权限 system.display 类型 ActiveState Chrome 117 及更高版本 用于指示系统是否检测到和使用显示屏的枚举。如果系统未检测到显示屏&#xff08;可能断开连接&#xff0c;或因睡眠模式等原因而被视…

学习记录:js算法(九十二):克隆图

文章目录 克隆图思路一 克隆图 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。 图中的每个节点都包含它的值 val&#xff08;int&#xff09; 和其邻居的列表&#xff08;list[Node]&#xff09;。 class Node {public int…

Linux中开启 Vim 之旅:从快捷键到插件的实用手册

文章目录 1. vim 的主要特点2. vim 的基本使用模板3. vim的基本操作4. vim正常模式命令集5. vim末行模式命令集6. 简单vim配置 vim 是 Linux 系统中非常强大的文本编辑器之一&#xff0c;全称为 “Vi IMproved”。它是 vi 编辑器的增强版&#xff0c;提供了更加丰富的功能&…

深度学习——AE、VAE

&#x1f33a;历史文章列表&#x1f33a; 机器学习——损失函数、代价函数、KL散度机器学习——特征工程、正则化、强化学习机器学习——常见算法汇总机器学习——感知机、MLP、SVM机器学习——KNN机器学习——贝叶斯机器学习——决策树机器学习——随机森林、Bagging、Boostin…

sql表的约束练习题

1. 如何创建一个包含非空约束的表&#xff1f; A. CREATE TABLE t01(id integer, name text, score numeric); B. CREATE TABLE t01(id integer NOT NULL, name text, score numeric); C. CREATE TABLE t01(id integer UNIQUE, name text, score numeric); D. CREA…

装杯 之 Linux指令【补充篇】

“生活就像海洋&#xff0c;只有意志坚强的人&#xff0c;才能到达彼岸” ---马克思 目录 1.grep指令 ​编辑 2.zip/unzip指令 3.tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 4.bc指令 5.uname 指令 1.grep…

YOLOv8改进 | 利用YOLOv8进行视频划定区域目标统计计数

简介 本项目旨在利用YOLOv8算法来实现视频中划定区域目标的统计计数。YOLOv8是一种目标检测算法,能够实现实时目标检测和定位。视频划定区域目标统计计数是指在一个视频中,对于指定的区域,统计出该区域内出现的目标物体数量。 该项目的工作流程如下:首先,利用YOLOv8算法…

hive表批量造数据

目录 1 . 使用 INSERT INTO 从已有表批量插入数据2. 使用 INSERT OVERWRITE 从文件或目录导入数据3. 使用 Hive 中的 SELECT 语句生成数据4. 使用 RAND() 或 UUID() 生成随机数据5. 使用 hive 的自定义 UDF 生成批量数据6. 使用 Python 脚本结合 Hive 进行数据生成7. 使用 hive…