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;
}

本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/e45d84ae.html
版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章