Heap Flags
About Heap flags¶
Heap flags
contains two flags initialized with NtGlobalFlag
: Flags
and ForceFlags
. The values of these two fields will not only be affected by the debugger, but also by the windows version, the location of the fields. Also depends on the version of windows.
- Flags field:
- In 32-bit Windows NT, Windows 2000 and Windows XP,
Flags
is at the0x0C
offset of the heap. On 32-bit Windows Vista and newer systems, it is located at the offset of0x40
. - In 64-bit Windows XP, the
Flags
field is at the0x14
offset of the heap, and on 64-bit Windows Vista and newer systems, it is at the0x70
offset. - ForceFlags field:
- In 32-bit Windows NT, Windows 2000 and Windows XP,
ForceFlags
is located at the0x10
offset of the heap. On 32-bit Windows Vista and newer systems, it is located at the offset of0x44
. - In 64-bit Windows XP, the
ForceFlags
field is at the0x18
offset of the heap, and on 64-bit Windows Vista and newer systems, it is at the0x74
offset.
In all versions of Windows, the value of the Flags
field is normally set to HEAP_GROWABLE(2)
, and the ForceFlags
field is normally set to 0
. However for a 32-bit process (64-bit programs are not There will be troubles. Both of these default values depend on the [subsystem
] of its host process (https://msdn.microsoft.com/en-us/library/ms933120.aspx) Version (this does not refer to the Linux subsystem such as win10). Only when subsystem
is in 3.51
and higher, the default value of the field is as described above. If it is in 3.10-3.50
Between, the two fields of HEAP_CREATE_ALIGN_16 (0x10000)
will be set. If the version is lower than 3.10
, then this program file will not be run at all.
If an operation sets the values of the Flags
and ForgeFlags
fields to 2
and 0
, respectively, but does not check the subsystem
version, then it can be indicated that the action is to hide the debugger. .
When the debugger is present, under the Windows NT
, Windows 2000
and 32-bit Windows XP
systems, the Flags
field will set the following flags:
HEAP_GROWABLE (2)
HEAP_TAIL_CHECKING_ENABLED (0x20)
HEAP_FREE_CHECKING_ENABLED (0x40)
HEAP_SKIP_VALIDATION_CHECKS (0x10000000)
HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)
On the 64-bit Windows XP
system, Windows Vista
and newer system versions, the Flags
field will set the following flags (less HEAP_SKIP_VALIDATION_CHECKS (0x10000000)
):
HEAP_GROWABLE (2)
HEAP_TAIL_CHECKING_ENABLED (0x20)
HEAP_FREE_CHECKING_ENABLED (0x40)
HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)
For the ForgeFlags
field, the following flags are normally set:
HEAP_TAIL_CHECKING_ENABLED (0x20)
HEAP_FREE_CHECKING_ENABLED (0x40)
HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)
Because of the relationship of the NtGlobalFlag
flag, heap
will also set some flag bits.
- If the
FLG_HEAP_ENABLE_TAIL_CHECK
flag is set in theNtGlobalFlag
field, theHEAP_TAIL_CHECKING_ENABLED
flag will be set in theheap
field. - If the
FLG_HEAP_ENABLE_FREE_CHECK
flag is set in theNtGlobalFlag
field, theFLG_HEAP_ENABLE_FREE_CHECK
flag will be set in theheap
field. - If the
FLG_HEAP_VALIDATE_PARAMETERS
flag is set in theNtGlobalFlag
field, theHEAP_VALIDATE_PARAMETERS_ENABLED
flag will be set in theheap
field (theHEAP_CREATE_ALIGN_16 (0x10000) will also be set in
Windows NTand
Windows 2000`. Sign).
heap flags
is also the same as NtGlobalFlag
in the previous section, but it is subject to the registry HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ <filename>
Location's PageHeapFlags"
key control.
Get the heap location¶
There are several ways to know the location of the heap
. One of the methods is the GetProcessHeap()
function of kernel32
. Of course, you can also use the following 32-bit assembly code to detect the 32-bit environment (there are actually some shells to avoid). Use this api function to directly query PEB):
mov eax, fs:[30h] ;Process Environment Block
mov eax, [eax+18h] ;get process heap base
Or use the following 64-bit code to detect a 64-bit environment
push 60h
pop rsi
gs:lodsq ;Process Environment Block
mov eax, [rax+30h] ;get process heap base
Or use the following 32-bit code to detect a 64-bit environment
mov eax, fs:[30h] ;Process Environment Block
;64-bit Process Environment Block
;follows 32-bit Process Environment Block
mov eax, [eax+1030h] ;get process heap base
The other method is to use the GetProcessHeaps()
function of kernel32
. In fact, it is simply transferred to the ntdll
RtlGetProcessHeaps()
function, which returns an array of the heap belonging to the current process. The first heap of the array is the same as the GetProcessHeap()
function of kernel32
.
This process can be implemented with 32-bit code detection for 32-bit windows environments:
push 30h
pop how
fs:lodsd ;Process Environment Block
;get process heaps list base
mov how, [how + eax + 5ch]
lodsd
As above, the code for detecting 64-bit windows environment with 64-bit code is:
push 60h
pop rsi
gs:lodsq ;Process Environment Block
;get process heaps list base
mov esi, [rsi * 2 + rax + 20h]
lodsd
Or use a 32-bit code to detect a 64-bit window environment:
mov eax, fs:[30h] ;Process Environment Block
;64-bit Process Environment Block
;follows 32-bit Process Environment Block
mov esi, [eax+10f0h] ;get process heaps list base
lodsd
Detect Flags field¶
So obviously, we can detect the debuggers from the flags of Flags
and ForgeFlags
.
First look at the detection code of the Flags
field, use a 32-bit code to detect the 32-bit windows environment, and the subsystem
version is between 3.10-3.50
:
call GetVersion
cmp al, 6
cc
sbb ebx, ebx
and ebx, 34h
mov eax, fs:[30h] ;Process Environment Block
mov eax, [eax+18h] ;get process heap base
mov eax, [eax+ebx+0ch] ;Flags
;neither HEAP_CREATE_ALIGN_16
;nor HEAP_SKIP_VALIDATION_CHECKS
and eax, 0effeffffh
;HEAP_GROWABLE
;+ HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp eax, 40000062h
je being_debugged
The 32-bit code detects the 32-bit windows environment, and the subsystem
is 3.51
and higher:
call GetVersion
cmp al, 6
cc
sbb ebx, ebx
and ebx, 34h
mov eax, fs:[30h] ;Process Environment Block
mov eax, [eax+18h] ;get process heap base
mov eax, [eax+ebx+0ch] ;Flags
;not HEAP_SKIP_VALIDATION_CHECKS
bswap eax
and al, 0efh
;HEAP_GROWABLE
;+ HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
;reversed by bswap
cmp eax, 62000040h
je being_debugged
64-bit code detects 64-bit windows environments (64-bit processes don't have to be bothered by the subsystem
version):
push 60h
pop rsi
gs:lodsq ;Process Environment Block
mov ebx, [rax+30h] ;get process heap base
call GetVersion
cmp al, 6
as rax, rax
and al, 0a4h
;HEAP_GROWABLE
;+ HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp d [rbx+rax+70h], 40000062h ;Flags
je being_debugged
Detect 64-bit windows environment with 32-bit code:
push 30h
pop eax
mov ebx, fs:[eax] ;Process Environment Block
;64-bit Process Environment Block
;follows 32-bit Process Environment Block
mov ah, 10h
mov ebx, [ebx+eax] ;get process heap base
call GetVersion
cmp al, 6
sbb eax, eax
and al, 0a4h
;Flags
;HEAP_GROWABLE
;+ HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp [ebx+eax+70h], 40000062h
je being_debugged
If you get this value directly through the NtMajorVersion
field of the KUSER_SHARED_DATA
structure (located at the offset of 0x7ffe026c
in 2G user space) (this value can be obtained on all 32-bit/64-bit versions of Windows), you can further confuse The GetVersion()
function call operation of kernel32
.
Detecting ForgeFlags field¶
Of course, another method is to detect the ForgeFlags
field. The following is a 32-bit code detection for a 32-bit Windows environment. The subsystem
version is between 3.10-3.50
:
call GetVersion
cmp al, 6
cc
sbb ebx, ebx
and ebx, 34h
mov eax, fs:[30h] ;Process Environment Block
mov eax, [eax+18h] ;get process heap base
mov eax, [eax+ebx+10h] ;ForceFlags
;not HEAP_CREATE_ALIGN_16
btr eax, 10h
;HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp eax, 40000060h
je being_debugged
The 32-bit code detects the 32-bit windows environment, and the subsystem
is 3.51
and higher:
call GetVersion
cmp al, 6
cc
sbb ebx, ebx
and ebx, 34h
mov eax, fs:[30h] ;Process Environment Block
mov eax, [eax+18h] ;get process heap base
;ForceFlags
;HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp [eax+ebx+10h], 40000060h
je being_debugged
64-bit code detects 64-bit windows environments (64-bit processes don't have to be bothered by the subsystem
version):
push 60h
pop rsi
gs:lodsq ;Process Environment Block
mov ebx, [rax+30h] ;get process heap base
call GetVersion
cmp al, 6
as rax, rax
and al, 0a4h
;ForceFlags
;HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp d [rbx+rax+74h], 40000060h
je being_debugged
Detect 64-bit windows environment with 32-bit code:
call GetVersion
cmp al, 6
push 30h
pop eax
mov ebx, fs:[eax] ;Process Environment Block
;64-bit Process Environment Block
;follows 32-bit Process Environment Block
mov ah, 10h
mov ebx, [ebx+eax] ;get process heap base
sbb eax, eax
and al, 0a4h
;ForceFlags
;HEAP_TAIL_CHECKING_ENABLED
;+ HEAP_FREE_CHECKING_ENABLED
;+ HEAP_VALIDATE_PARAMETERS_ENABLED
cmp [ebx+eax+74h], 40000060h
je being_debugged
Reference link¶
本页面的全部内容在 CC BY-NC-SA 4.0 协议之条款下提供,附加条款亦可能应用。