反调试系列 | 调试标志寄存器

调试标志寄存器

系统表中的特殊标志寄存器,即停留在进程内存中的、由操作系统设置的标志寄存器,可以用来指示进程正在被调试。这些标志寄存器的状态可以通过使用特定的API函数或检查内存中的系统表来验证。

这些技术是恶意软件最常使用的。

1. 使用Win32 API

以下技术使用现有的API函数(WinAPI或NativeAPI),这些函数检查进程内存中的系统结构,以寻找表明进程现在正在被调试的特定标志寄存器。

1.1. IsDebuggerPresent()

函数kernel32!IsDebuggerPresent()确定当前进程是否被用户模式的调试器如OllyDbg或x64dbg调试。一般来说,该函数只检查进程环境块(PEB)的 BeingDebugged 标志寄存器。

如果正在调试进程,可以使用以下代码终止进程:

汇编代码:

1

2

3

4

5

6

7

    call IsDebuggerPresent    

    test al, al

    jne  being_debugged

    ...

being_debugged:

    push 1

    call ExitProcess

C/C++ 代码:

1

2

if (IsDebuggerPresent())

    ExitProcess(-1);

1.2. CheckRemoteDebuggerPresent()

函数kernel32!CheckRemoteDebuggerPresent()检查一个调试器(在同一台机器的不同进程中)是否连接到当前进程。

C/C++ 代码:

1

2

3

4

BOOL bDebuggerPresent;

if (TRUE == CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebuggerPresent) &&

    TRUE == bDebuggerPresent)

    ExitProcess(-1);

x86 汇编:

1

2

3

4

5

6

7

8

9

10

    lea eax, bDebuggerPresent]

    push eax

    push -1  ; GetCurrentProcess()

    call CheckRemoteDebuggerPresent

    cmp [bDebuggerPresent], 1

    jz being_debugged

    ...

being_debugged:

    push -1

    call ExitProcess

x86-64 汇编:

1

2

3

4

5

6

7

8

9

    lea rdx, [bDebuggerPresent]

    mov rcx, -1 ; GetCurrentProcess()

    call CheckRemoteDebuggerPresent

    cmp [bDebuggerPresent], 1

    jz being_debugged

    ...

being_debugged:

    mov ecx, -1

    call ExitProcess

1.3. NtQueryInformationProcess()

函数ntdll!NtQueryInformationProcess()可以从一个进程中检索不同种类的信息。它接受一个ProcessInformationClass参数,该参数指定了你想得到的信息,并定义了ProcessInformation参数的输出类型。

1.3.1. ProcessDebugPort进程调试端口

可以使用ntdll!NtQueryInformationProcess()来检索进程的调试器端口号。有一个记录在案的类ProcessDebugPort,如果进程正在被调试,它会检索到一个等于0xFFFFFFFF(十进制-1)的DWORD值。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

typedef NTSTATUS (NTAPI *TNtQueryInformationProcess)(

    IN HANDLE           ProcessHandle,

    IN PROCESSINFOCLASS ProcessInformationClass,

    OUT PVOID           ProcessInformation,

    IN ULONG            ProcessInformationLength,

    OUT PULONG          ReturnLength

    );

HMODULE hNtdll = LoadLibraryA("ntdll.dll");

if (hNtdll)

{

    auto pfnNtQueryInformationProcess = (TNtQueryInformationProcess)GetProcAddress(

        hNtdll, "NtQueryInformationProcess");

     

    if (pfnNtQueryInformationProcess)

    {

        DWORD dwProcessDebugPort, dwReturned;

        NTSTATUS status = pfnNtQueryInformationProcess(

            GetCurrentProcess(),

            ProcessDebugPort,

            &dwProcessDebugPort,

            sizeof(DWORD),

            &dwReturned);

        if (NT_SUCCESS(status) && (-1 == dwProcessDebugPort))

            ExitProcess(-1);

    }

}

x86 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea eax, [dwReturned]

    push eax ; ReturnLength

    push 4   ; ProcessInformationLength

    lea ecx, [dwProcessDebugPort]

    push ecx ; ProcessInformation

    push 7   ; ProcessInformationClass

    push -1  ; ProcessHandle

    call NtQueryInformationProcess

    inc dword ptr [dwProcessDebugPort]

    jz being_debugged

    ...

being_debugged:

    push -1

    call ExitProcess

x86-64 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea rcx, [dwReturned]

    push rcx    ; ReturnLength

    mov r9d, 4  ; ProcessInformationLength

    lea r8, [dwProcessDebugPort] 

                ; ProcessInformation

    mov edx, 7  ; ProcessInformationClass

    mov rcx, -1 ; ProcessHandle

    call NtQueryInformationProcess

    cmp dword ptr [dwProcessDebugPort], -1

    jz being_debugged

    ...

being_debugged:

    mov ecx, -1

    call ExitProcess

1.3.2. ProcessDebugFlags进程调试标志寄存器

一个叫做EPROCESS的内核结构代表一个进程对象,它包含NoDebugInherit字段。这个字段的反值可以通过一个无文件记录的类ProcessDebugFlags(0x1f)来检索。因此,如果返回值为0,则说明有调试器存在。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

typedef NTSTATUS(NTAPI *TNtQueryInformationProcess)(

    IN HANDLE           ProcessHandle,

    IN DWORD            ProcessInformationClass,

    OUT PVOID           ProcessInformation,

    IN ULONG            ProcessInformationLength,

    OUT PULONG          ReturnLength

    );

HMODULE hNtdll = LoadLibraryA("ntdll.dll");

if (hNtdll)

{

    auto pfnNtQueryInformationProcess = (TNtQueryInformationProcess)GetProcAddress(

        hNtdll, "NtQueryInformationProcess");

    if (pfnNtQueryInformationProcess)

    {

        DWORD dwProcessDebugFlags, dwReturned;

        const DWORD ProcessDebugFlags = 0x1f;

        NTSTATUS status = pfnNtQueryInformationProcess(

            GetCurrentProcess(),

            ProcessDebugFlags,

            &dwProcessDebugFlags,

            sizeof(DWORD),

            &dwReturned);

        if (NT_SUCCESS(status) && (0 == dwProcessDebugFlags))

            ExitProcess(-1);

    }

}

x86 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea eax, [dwReturned]

    push eax ; ReturnLength

    push 4   ; ProcessInformationLength

    lea ecx, [dwProcessDebugPort]

    push ecx ; ProcessInformation

    push 1Fh ; ProcessInformationClass

    push -1  ; ProcessHandle

    call NtQueryInformationProcess

    cmp dword ptr [dwProcessDebugPort], 0

    jz being_debugged

    ...

being_debugged:

    push -1

    call ExitProcess

x86-64 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea rcx, [dwReturned]

    push rcx     ; ReturnLength

    mov r9d, 4   ; ProcessInformationLength

    lea r8, [dwProcessDebugPort] 

                 ; ProcessInformation

    mov edx, 1Fh ; ProcessInformationClass

    mov rcx, -1  ; ProcessHandle

    call NtQueryInformationProcess

    cmp dword ptr [dwProcessDebugPort], 0

    jz being_debugged

    ...

being_debugged:

    mov ecx, -1

    call ExitProcess

1.3.3. ProcessDebugObjectHandle进程调试对象句柄

当调试开始时,一个叫做 "debug object "的内核对象被创建。可以通过使用无文献记载的ProcessDebugObjectHandle(0x1e)类来查询这个句柄的值。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

typedef NTSTATUS(NTAPI * TNtQueryInformationProcess)(

    IN HANDLE           ProcessHandle,

    IN DWORD            ProcessInformationClass,

    OUT PVOID           ProcessInformation,

    IN ULONG            ProcessInformationLength,

    OUT PULONG          ReturnLength

    );

HMODULE hNtdll = LoadLibraryA("ntdll.dll");

if (hNtdll)

{

    auto pfnNtQueryInformationProcess = (TNtQueryInformationProcess)GetProcAddress(

        hNtdll, "NtQueryInformationProcess");

    if (pfnNtQueryInformationProcess)

    {

        DWORD dwReturned;

        HANDLE hProcessDebugObject = 0;

        const DWORD ProcessDebugObjectHandle = 0x1e;

        NTSTATUS status = pfnNtQueryInformationProcess(

            GetCurrentProcess(),

            ProcessDebugObjectHandle,

            &hProcessDebugObject,

            sizeof(HANDLE),

            &dwReturned);

        if (NT_SUCCESS(status) && (0 != hProcessDebugObject))

            ExitProcess(-1);

    }

}

x86 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea eax, [dwReturned]

    push eax ; ReturnLength

    push 4   ; ProcessInformationLength

    lea ecx, [hProcessDebugObject]

    push ecx ; ProcessInformation

    push 1Eh ; ProcessInformationClass

    push -1  ; ProcessHandle

    call NtQueryInformationProcess

    cmp dword ptr [hProcessDebugObject], 0

    jnz being_debugged

    ...

being_debugged:

    push -1

    call ExitProcess

x86-64 汇编:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

    lea rcx, [dwReturned]

    push rcx     ; ReturnLength

    mov r9d, 4   ; ProcessInformationLength

    lea r8, [hProcessDebugObject] 

                 ; ProcessInformation

    mov edx, 1Fh ; ProcessInformationClass

    mov rcx, -1  ; ProcessHandle

    call NtQueryInformationProcess

    cmp dword ptr [hProcessDebugObject], 0

    jnz being_debugged

    ...

being_debugged:

    mov ecx, -1

    call ExitProcess

1.4. RtlQueryProcessHeapInformation()

ntdll!RtlQueryProcessHeapInformation()函数可以用来从当前进程的进程内存中读取堆标志寄存器。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

bool Check()

{

    ntdll::PDEBUG_BUFFER pDebugBuffer = ntdll::RtlCreateQueryDebugBuffer(0, FALSE);

    if (!SUCCEEDED(ntdll::RtlQueryProcessHeapInformation((ntdll::PRTL_DEBUG_INFORMATION)pDebugBuffer)))

        return false;

    ULONG dwFlags = ((ntdll::PRTL_PROCESS_HEAPS)pDebugBuffer->HeapInformation)->Heaps[0].Flags;

    return dwFlags & ~HEAP_GROWABLE;

}

1.5. RtlQueryProcessDebugInformation()

ntdll!RtlQueryProcessDebugInformation()函数可用于从被请求进程的进程内存中读取某些字段,包括堆标志寄存器。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

bool Check()

{

    ntdll::PDEBUG_BUFFER pDebugBuffer = ntdll::RtlCreateQueryDebugBuffer(0, FALSE);

    if (!SUCCEEDED(ntdll::RtlQueryProcessDebugInformation(GetCurrentProcessId(), ntdll::PDI_HEAPS | ntdll::PDI_HEAP_BLOCKS, pDebugBuffer)))

        return false;

    ULONG dwFlags = ((ntdll::PRTL_PROCESS_HEAPS)pDebugBuffer->HeapInformation)->Heaps[0].Flags;

    return dwFlags & ~HEAP_GROWABLE;

}

1.6. NtQuerySystemInformation()

ntdll!NtQuerySystemInformation()函数接受一个参数,即要查询的信息类别。大多数类都没有被记录下来。这包括SystemKernelDebuggerInformation(0x23)类,它从Windows NT开始就存在了。SystemKernelDebuggerInformation类返回两个标志寄存器的值。al中的KdDebuggerEnabled,和ah中的KdDebuggerNotPresent。因此,如果内核调试器存在,ah中的返回值为零。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

enum { SystemKernelDebuggerInformation = 0x23 };

typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { 

    BOOLEAN DebuggerEnabled; 

    BOOLEAN DebuggerNotPresent; 

} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; 

bool Check()

{

    NTSTATUS status;

    SYSTEM_KERNEL_DEBUGGER_INFORMATION SystemInfo;

     

    status = NtQuerySystemInformation(

        (SYSTEM_INFORMATION_CLASS)SystemKernelDebuggerInformation,

        &SystemInfo,

        sizeof(SystemInfo),

        NULL);

    return SUCCEEDED(status)

        ? (SystemInfo.DebuggerEnabled && !SystemInfo.DebuggerNotPresent)

        : false;

}

反制措施

  • 对于IsDebuggerPresent()。将进程环境块(PEB)的BeingDebugged标志设置为0。 更多信息请参见BeingDebugged 标志寄存器反制措施。

  • 对于CheckRemoteDebuggerPresent()和NtQueryInformationProcess():
    由于CheckRemoteDebuggerPresent()调用NtQueryInformationProcess(),唯一的方法是拦截NtQueryInformationProcess()并在返回缓冲区设置以下值。

    • 如果是ProcessDebugPort查询,则为0(或除-1外的任何值)。

    • 如果是ProcessDebugFlags查询,则为非零值。

    • 在ProcessDebugObjectHandle查询的情况下为0。

  • 用RtlQueryProcessHeapInformation()、RtlQueryProcessDebugInformation()和NtQuerySystemInformation()函数反制这些检查的唯一方法是拦截它们并修改返回值:

    • RTL_PROCESS_HEAPS::HeapInformation::Heaps[0]:标志寄存器改为HEAP_GROWABLE,用于RtlQueryProcessHeapInformation()和RtlQueryProcessDebugInformation()。

SYSTEM_KERNEL_DEBUGGER_INFORMATION::DebuggerEnabled为0和系统_KERNEL_DEBUGGER_INFORMATION::DebuggerNotPresent为1。NtQuerySystemInformation()函数在查询SystemKernelDebuggerInformation的情况下。

2. 手工检查

以下方法用于验证系统结构中的调试标志。他们手工检查进程的内存,而不使用特殊的调试API函数。

2.1. PEB!正在调试标志寄存器

这个方法只是检查PEB的BeingDebugged标志寄存器[的另一种方法,而不需要调用IsDebuggerPresent()。

32位进程:

1

2

3

mov eax, fs:[30h]

cmp byte ptr [eax+2], 0

jne being_debugged

64位进程:

1

2

3

mov rax, gs:[60h]

cmp byte ptr [rax+2], 0

jne being_debugged

WOW64 进程:

1

2

mov eax, fs:[30h]

cmp byte ptr [eax+1002h], 0

C/C++ 代码:

1

2

3

4

5

6

7

8

#ifndef _WIN64

PPEB pPeb = (PPEB)__readfsdword(0x30);

#else

PPEB pPeb = (PPEB)__readgsqword(0x60);

#endif // _WIN64

  

if (pPeb->BeingDebugged)

    goto being_debugged;

2.2. NtGlobalFlag

进程环境块的NtGlobalFlag字段(32位Windows的0x68偏移,64位Windows的0xBC)默认为0。附加一个调试器并不改变NtGlobalFlag的值。但是,如果进程是由调试器创建的,则将设置以下标志寄存器:

  • FLG_HEAP_ENABLE_TAIL_CHECK (0x10)

  • FLG_HEAP_ENABLE_FREE_CHECK (0x20)

  • FLG_HEAP_VALIDATE_PARAMETERS (0x40)

调试器的存在可以通过检查这些标志寄存器的组合来检测。

32位进程:

1

2

3

4

5

mov eax, fs:[30h]

mov al, [eax+68h]

and al, 70h

cmp al, 70h

jz  being_debugged

64位进程:

1

2

3

4

5

mov rax, gs:[60h]

mov al, [rax+BCh]

and al, 70h

cmp al, 70h

jz  being_debugged

WOW64 进程:

1

2

3

4

5

mov eax, fs:[30h]

mov al, [eax+10BCh]

and al, 70h

cmp al, 70h

jz  being_debugged

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#define FLG_HEAP_ENABLE_TAIL_CHECK   0x10

#define FLG_HEAP_ENABLE_FREE_CHECK   0x20

#define FLG_HEAP_VALIDATE_PARAMETERS 0x40

#define NT_GLOBAL_FLAG_DEBUGGED (FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS)

#ifndef _WIN64

PPEB pPeb = (PPEB)__readfsdword(0x30);

DWORD dwNtGlobalFlag = *(PDWORD)((PBYTE)pPeb + 0x68);

#else

PPEB pPeb = (PPEB)__readgsqword(0x60);

DWORD dwNtGlobalFlag = *(PDWORD)((PBYTE)pPeb + 0xBC);

#endif // _WIN64

  

if (dwNtGlobalFlag & NT_GLOBAL_FLAG_DEBUGGED)

    goto being_debugged;

2.3. 堆标志寄存器

堆包含两个字段,它们会受到调试器存在的影响。具体如何影响,取决于Windows的版本。这些字段是标志寄存器(Flags)和强标志寄存器(ForceFlags)。

标志寄存器和强标志寄存器的值通常分别设置为HEAP_GROWABLE和0。

当调试器出现时,在Windows NT、Windows 2000和32位Windows XP上,标志寄存器字段被设置为这些标志寄存器的组合。

  • HEAP_GROWABLE (2)

  • HEAP_TAIL_CHECKING_ENABLED (0x20)

  • HEAP_FREE_CHECKING_ENABLED (0x40)

  • HEAP_SKIP_VALIDATION_CHECKS (0x10000000)

  • HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)

在64位的Windows XP和Windows Vista及更高版本中,如果有调试器存在,Flags字段会被设置为这些标志寄存器组合:

  • HEAP_GROWABLE (2)

  • HEAP_TAIL_CHECKING_ENABLED (0x20)

  • HEAP_FREE_CHECKING_ENABLED (0x40)

  • HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)

当调试器出现时,ForceFlags字段被设置为这些标志寄存器的组合:

  • HEAP_TAIL_CHECKING_ENABLED (0x20)

  • HEAP_FREE_CHECKING_ENABLED (0x40)

  • HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

bool Check()

{

#ifndef _WIN64

    PPEB pPeb = (PPEB)__readfsdword(0x30);

    PVOID pHeapBase = !m_bIsWow64

        ? (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x18))

        : (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x1030));

    DWORD dwHeapFlagsOffset = IsWindowsVistaOrGreater()

        ? 0x40

        : 0x0C;

    DWORD dwHeapForceFlagsOffset = IsWindowsVistaOrGreater()

        ? 0x44 

        : 0x10;

#else

    PPEB pPeb = (PPEB)__readgsqword(0x60);

    PVOID pHeapBase = (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x30));

    DWORD dwHeapFlagsOffset = IsWindowsVistaOrGreater()

        ? 0x70 

        : 0x14;

    DWORD dwHeapForceFlagsOffset = IsWindowsVistaOrGreater()

        ? 0x74 

        : 0x18;

#endif // _WIN64

    PDWORD pdwHeapFlags = (PDWORD)((PBYTE)pHeapBase + dwHeapFlagsOffset);

    PDWORD pdwHeapForceFlags = (PDWORD)((PBYTE)pHeapBase + dwHeapForceFlagsOffset);

    return (*pdwHeapFlags & ~HEAP_GROWABLE) || (*pdwHeapForceFlags != 0);

}

2.3.堆保护

如果在NtGlobalFlag中设置了HEAP_TAIL_CHECKING_ENABLED标志寄存器,序列0xABABABAB将被附加在所分配的堆块的末端(在32位Windows中为2次,在64位Windows中为4次)。

如果在NtGlobalFlag中设置了HEAP_FREE_CHECKING_ENABLED标志寄存器,如果需要额外的字节来填充空的空间,直到下一个内存块,那么将附加序列0xFEEEFEEE。

C/C++ 代码:

1

2

3

4

5

6

7

8

9

10

11

12

bool Check()

{

    PROCESS_HEAP_ENTRY HeapEntry = { 0 };

    do

    {

        if (!HeapWalk(GetProcessHeap(), &HeapEntry))

            return false;

    } while (HeapEntry.wFlags != PROCESS_HEAP_ENTRY_BUSY);

    PVOID pOverlapped = (PBYTE)HeapEntry.lpData + HeapEntry.cbData;

    return ((DWORD)(*(PDWORD)pOverlapped) == 0xABABABAB);

}

反制措施

对于PEB!BeingDebugged标志寄存器:

将BeingDebugged标志设置为0,这可以通过DLL注入完成。如果你使用OllyDbg或x32/64dbg作为调试器,你可以选择各种反调试插件,如ScyllaHide。

1

2

3

4

5

6

#ifndef _WIN64

PPEB pPeb = (PPEB)__readfsdword(0x30);

#else

PPEB pPeb = (PPEB)__readgsqword(0x60);

#endif // _WIN64

pPeb->BeingDebugged = 0;

对于NtGlobalFlag:

将NtGlobalFlag设置为0,这可以通过DLL注入完成。如果你使用OllyDbg或x32/64dbg作为调试器,你可以选择各种反调试插件,如ScyllaHide。

1

2

3

4

5

6

7

#ifndef _WIN64

PPEB pPeb = (PPEB)__readfsdword(0x30);

*(PDWORD)((PBYTE)pPeb + 0x68) = 0;

#else

PPEB pPeb = (PPEB)__readgsqword(0x60);

*(PDWORD)((PBYTE)pPeb + 0xBC); = 0;

#endif // _WIN64

对于堆标志寄存器:

设置标志寄存器值为HEAP_GROWABLE,ForceFlags值为0,这可以通过DLL注入完成。如果你使用OllyDbg或x32/64dbg作为调试器,你可以选择各种反调试插件,如ScyllaHide。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#ifndef _WIN64

PPEB pPeb = (PPEB)__readfsdword(0x30);

PVOID pHeapBase = !m_bIsWow64

    ? (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x18))

    : (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x1030));

DWORD dwHeapFlagsOffset = IsWindowsVistaOrGreater()

    ? 0x40

    : 0x0C;

DWORD dwHeapForceFlagsOffset = IsWindowsVistaOrGreater()

    ? 0x44 

    : 0x10;

#else

PPEB pPeb = (PPEB)__readgsqword(0x60);

PVOID pHeapBase = (PVOID)(*(PDWORD_PTR)((PBYTE)pPeb + 0x30));

DWORD dwHeapFlagsOffset = IsWindowsVistaOrGreater()

    ? 0x70 

    : 0x14;

DWORD dwHeapForceFlagsOffset = IsWindowsVistaOrGreater()

    ? 0x74 

    : 0x18;

#endif // _WIN64

*(PDWORD)((PBYTE)pHeapBase + dwHeapFlagsOffset) = HEAP_GROWABLE;

*(PDWORD)((PBYTE)pHeapBase + dwHeapForceFlagsOffset) = 0;

对于堆保护:

手工修补32位的12字节和64位环境下的20字节的堆。拦截kernel32!HeapAlloc()并在其分配后修补堆。

1

2

3

4

5

6

7

8

9

#ifndef _WIN64

SIZE_T nBytesToPatch = 12;

#else

SIZE_T nBytesToPatch = 20;

#endif // _WIN64

SIZE_T nDwordsToPatch = nBytesToPatch / sizeof(DWORD);

PVOID pHeapEnd = (PBYTE)HeapEntry.lpData + HeapEntry.cbData;

for (SIZE_T offset = 0; offset < nDwordsToPatch; offset++)

    *((PDWORD)pHeapEnd + offset) = 0;

备注:

本文投稿来自:作者王建达

原文地址:https://anti-debug.checkpoint.com/techniques/debug-flags.html

原文标题:Anti-Debug: DebugFlags

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值