8.4 ProcessHeap
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;
}
												
											8.4 ProcessHeap的更多相关文章
- 关于《加密与解密》的读后感----对dump脱壳的一点思考
		
偶然翻了一下手机日历,原来今天是夏至啊,时间过的真快.ISCC的比赛已经持续了2个多月了,我也跟着比赛的那些题目学了2个月.......虽然过程很辛苦,但感觉还是很幸运的,能在大三的时候遇到ISCC, ...
 - windows进程中的内存结构[转载]
		
在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识. 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变 ...
 - Windows x86/ x64 Ring3层注入Dll总结
		
欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ...
 - KPROCESS IDT PEB Ldr 《寒江独钓》内核学习笔记(3)
		
继续上一篇(2)未完成的研究,我们接下来学习 KPROCESS这个数据结构. 1. 相关阅读材料 <深入理解计算机系统(原书第2版)> 二. KPROCESS KPROCESS,也叫内核进 ...
 - java\c程序的内存分配
		
JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该 ...
 - 旧书重温:0day2【3】 详细解读PEB法 查找kener32地址
		
题外话:上一篇文章中的 PEB法查找kerner32地址的方法 对TEB.PEB .PE结构 知识要求很高,确实在写汇编代码时候小编 感觉自己能力,信手啪啪一顿乱撸,结果一运行,非法访问了,没办法翻阅 ...
 - 旧书重温:0day2【2】 实验:三种获取kernel32.dll基址的方法
		
0x01 找kernel32基地址的方法一般有三种: 暴力搜索法.异常处理链表搜索法.PEB法. 0x02 基本原理 暴力搜索法是最早的动态查找kernel32基地址的方法.它的原理是几乎所有的win ...
 - [c++]堆和栈的区别
		
堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...
 - windows进程中的内存结构(好多API,而且VC最聪明)
		
在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识. 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这 ...
 - 堆和栈的区别【zz】
		
一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.2. ...
 
随机推荐
- 源码深度解析 Handler 机制及应用
			
本文以源码分析+实际应用的形式,详细讲解了 Handler 机制的原理,以及在开发中的使用场景和要注意的地方. 一.基本原理回顾 在 Android 开发中,Handler及相关衍生类的应用经常用到, ...
 - ngix反向代理服务器
			
Nginx ("engine x") 是一个高性能的HTTP 和反向代理 服务器,在大负载的情况下表现十分优秀. 1.正向代理 正向代理也是大家最常接触的到的代理模式.正向代理最大 ...
 - echarts折线图美化(颜色渐变、背景透明、隐藏坐标轴)
			
echarts折线图美化(颜色渐变.背景透明.隐藏坐标轴) https://blog.csdn.net/Changeable0127/article/details/81333559?utm_medi ...
 - freeswitch号码变化方案
			
概述 freeswitch是一款简单易用的开源音视频软交换平台. 在生产环境中,由于各个线路的号码规则并不统一,经常需要针对中继线路做号码变换的方案. 本文主要介绍fs中有哪些可选的号码变换方案. 环 ...
 - java基础-java面向对象01-day08
			
1. 一个简单的类 认识类 成员变量 类方法 public class Person { //类的成员变量 int age; String name; double height; double we ...
 - PMP项目变更管理及变更流程总结
			
转载请注明出处: 1. 变更管理流程 2.变更管理流程十步: 0 预防--1发起变更请求--2分析影响--3备选方案--4CCB批准--5更新项目管理计划--6沟通干系人--7执行--8检查--9总结 ...
 - steam无法登陆/更新客户端
			
1.问题 最近CS2更新,正准备尝试游玩一下,发现提示要使用最新版本客户端,在检查steam客户端更新时,却发现检查更新失败,无法更新,有可能是丢失了某些文件导致的. (之前有过一次重新安装的经历,但 ...
 - 【SI】source insight4 添加指定类型的文件
			
Options->File Type Options 红框可选择是否将指定类型的文件添加到工程 绿框可添加自定义文件类型,如汇编*.s;*.S 蓝框可新增文件类别,用于自定义文件类型 如不需将t ...
 - [转帖]Linux的缓存内存(cache memory)
			
PS:为什么Linux系统没运行多少程序,显示的可用内存这么少?其实Linux与Win的内存管理不同,会尽量缓存内存以提高读写性能,通常叫做Cache Memory. 为什么Linux系统没运行多少程 ...
 - [转帖]umount -fl用法
			
https://www.cnblogs.com/xingmuxin/p/8446178.html umount, 老是提示:device is busy, 服务又不能停止的.可以用"umou ...