8.4 ProcessHeap

processheap · 浏览次数 : 12

小编点评

**汇编代码** ```assembly ; 读取ProcessHeap首地址 mov eax, fs:[0x18] mov eax, [eax + 0x30] ; 读取ProcessHeap中的ForceFlags标志 mov eax, [eax + 0x44] mov Debug, eax ``` **C语言代码** ```c #include #include #include 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, Pbi, &pBi, sizeof(PROCESS_BASIC_INFORMATION), NULL); if (Status == NT_SUCCESS) { DWORD ByteRead = 0; DWORD ProcessHeap = 0; ULONG PebBase = (ULONG)Pbi.PebBaseAddress; DWORD ForceFlagsValue = 1; ReadProcessMemory(hProcess, (LPVOID)(PebBase + 0x18), &ProcessHeap, 2, &ByteRead); ReadProcessMemory(hProcess, (LPVOID)(ProcessHeap + 0x40), &ForceFlagsValue, 4, &ByteRead); if (ForceFlagsValue != 0) { return TRUE; } } CloseHandle(hProcess); } return FALSE; } ```

正文

ProcessHeap 是Windows进程的默认堆,每个进程都有一个默认的堆,用于在进程地址空间中分配内存空间。默认情况下ProcessHeap由内核进行初始化,该堆中存在一个未公开的属性,它被设置为加载器为进程分配的第一个堆的位置(进程堆标志),ProcessHeap标志位于PEB结构中偏移为0x18处,第一个堆头部有一个属性字段,这个属性叫做ForceFlags属性偏移为0x44,该属性为0说明程序没有被调试,非0说明被调试,另外的Flags属性为2说明被调试,不为2则说明没有被调试。

0:000> dt !_peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x018 ProcessHeap      : Ptr32 Void       // 找到Process偏移地址

0:000> !heap                                  // 找出堆区首地址
        Heap Address      NT/Segment Heap
             1270000              NT Heap

0:000> !heap -a 1270000                       // 查询heep的内存
Index   Address  Name      Debugging options enabled
  1:   01270000 
    Segment at 01270000 to 0136f000 (00006000 bytes committed)
    Flags:                40000062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000

0:000> dt _HEAP 1270000                       // 找到ForceFlags标志的偏移地址
ntdll!_HEAP
   +0x000 Segment          : _HEAP_SEGMENT
   +0x000 Entry            : _HEAP_ENTRY
   +0x040 Flags            : 0x40000062
   +0x044 ForceFlags       : 0x40000060

这里需要注意一点,堆区在不同系统中偏移值是不同的,在Windows10系统中ForceFlags属性位于堆头部偏移量为0x44处,而默认情况如果被调试则ForceFlags属性为0x40000060,而Flags标志为0x40000062,有了这些参考那么通过汇编语言实现将变得很容易,如下代码则是通过汇编分别读取这两个堆头参数;

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

// 两种方式输出
int IsDebug(DWORD x)
{
    DWORD Debug = 0;

    if (x == 1)
    {
        __asm
        {
            mov eax, fs:[0x18]       // TED基地址
            mov eax, [eax + 0x30]    // PEB基地址
            mov eax, [eax + 0x18]    // 定位 ProcessHeap
            mov eax, [eax + 0x44]    // 定位到 ForceFlags
            mov Debug, eax
        }
    }
    if (x == 2)
    {
        __asm
        {
            mov eax, fs:[0x18]       // TED基地址
            mov eax, [eax + 0x30]    // PEB基地址
            mov eax, [eax + 0x18]    // 定位 ProcessHeap
            mov eax, [eax + 0x40]    // 定位到 Flags
            mov Debug, eax
        }
    }

    return Debug;
}

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

    system("pause");
    return 0;
}

另一种通过C语言实现的反调试版本,其反调试原理与上方相同,只不过此处我们使用了系统的API来完成检测标志位的。

#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;
            DWORD ProcessHeap = 0;
            ULONG PebBase = (ULONG)Pbi.PebBaseAddress;
            DWORD ForceFlagsValue = 1;

            ReadProcessMemory(hProcess, (LPCVOID)(PebBase + 0x18), &ProcessHeap, 2, &ByteRead);
            ReadProcessMemory(hProcess, (LPCVOID)(ProcessHeap + 0x40), &ForceFlagsValue, 4, &ByteRead);

            if (ForceFlagsValue != 0)
            {
                return TRUE;
            }
        }
        CloseHandle(hProcess);
    }
    return FALSE;
}

int main(int argc, char * argv[])
{
    if (IsDebug())
    {
        printf("[-] 正在被调试 \n");
    }

    system("pause");
    return 0;
}

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

与8.4 ProcessHeap相似的内容:

8.4 ProcessHeap

ProcessHeap 是`Windows`进程的默认堆,每个进程都有一个默认的堆,用于在进程地址空间中分配内存空间。默认情况下`ProcessHeap`由内核进行初始化,该堆中存在一个未公开的属性,它被设置为加载器为进程分配的第一个堆的位置(进程堆标志),`ProcessHeap`标志位于`PEB`结构中偏移为`0x18`处,第一个堆头部有一个属性字段,这个属性叫做`ForceFlags`属性偏

mysql-8.4.0解压版安装记录

MySQL 8.4.0解压版安装记录 这几天,安装最新版mysql 8.4的时候,遇到了不少问题,网上的教程大多数都是旧版本的,也安装不成功。 参考了大量教程后,经过自己的摸索终于装好了,这里记录一下。 我下载的是8.4.0 LTS MySQL :: Download MySQL Community

升级到 MySQL 8.4,MySQL 启动报错:io_setup() failed with EAGAIN

问题 最近碰到一个 case,一台主机上,部署了多个实例。之前使用的是 MySQL 8.0,启动时没有任何问题。但升级到 MySQL 8.4 后,部分实例在启动时出现了以下错误。 [Warning] [MY-012582] [InnoDB] io_setup() failed with EAGAIN

前瞻 PHP8.4 的新特性

前瞻 PHP8.4 的新特性 PHP 8.4 将于 2024 年 11 月 21 日发布。它将包括属性钩子、JIT 改进,以及在不需要额外括号的情况下链式调用方法。这是一个大变化! 属性钩子 RFC 现代 PHP 历史上最大的变化之一:定义属性钩子的能力。 class BookViewModel {

.NET周刊【8月第4期 2023-08-27】

## 国内文章 ### AgileConfig-1.7.0 发布,支持 SSO 🎉🎉🎉 https://www.cnblogs.com/kklldog/p/agileconfig-170.html AgileConfig 已经好久好久没有更新过比较大的功能了。一是 AgileConfig 本身

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(防止因为时间

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 权

HarmonyOS系统级推送服务,打造消息通知新体验

8月4日,第五届华为开发者大会 2023(HDC.Together)再次启航。在本次大会上,华为为广大用户带来了HarmonyOS 4全新升级的体验,同时,针对HarmonyOS应用的开发,此次也全面升级了HarmonyOS SDK开放能力。[账号服务](https://developer.huaw

华为开发者大会2023:云空间筑牢鸿蒙生态“云基因”

8月4日,华为开发者大会2023在东莞·松山湖举办,众多开发者及合作伙伴共赴盛会,见证鸿蒙生态的最新进展。在本届大会的HarmonyOS应用开发(端云能力)分论坛上,华为Drive Kit生态架构技术总监官宣云空间服务升级,赋能开发者高效开发,为鸿蒙生态应用注入“云基因”。 ![](https://

4.8 x64dbg 学会扫描应用堆栈

LyScript 插件中提供了针对堆栈的操作函数,对于堆的开辟与释放通常可使用`create_alloc()`及`delete_alloc()`在之前的文章中我们已经使用了堆创建函数,本章我们将重点学习针对栈的操作函数,栈操作函数有三种,其中`push_stack`用于入栈,`pop_stack`用于出栈,而最有用的还属`peek_stack`函数,该函数可用于检查指定堆栈位置处的内存参数,利用这