为什么在Visual Studio x64MASM上将gs段寄存器的地址设置为0x0000000000000000?

问题描述

我目前正在阅读"The Ultimate Anti Debugging Reference",并且正在尝试实现某些技巧。

要检查NtglobalFlag的值,他们使用此代码-

 push 60h
 pop rsi
 gs:lodsq ;Process Environment Block
 mov al,[rsi*2+rax-14h] ;NtGlobalFlag
 and al,70h
 cmp al,70h
 je being_debugged

我使用this教程对在Visual Studio 2017上运行x64代码进行了所有正确的调整。

我使用此指令来访问NtGlobalFlag

lodsq gs:[rsi]

因为它们的语法在Visual Studio上不起作用。

但是仍然没有用。

在调试时,我注意到 gs 寄存器的值设置为0x0000000000000000,而 fs 寄存器的值设置为实际值0x0000007595377000。

我不明白为什么 GS 的值归零,因为应该在x64上设置其值。

解决方法

所以我仍然不明白为什么这里发布的代码会导致这么多问题,正如我所说的,我只是从“ The Ultimate”Anti-Debugging Reference”中复制了它。

 push 60h
 pop rsi
 gs:lodsq ;Process Environment Block
 mov al,[rsi*2+rax-14h] ;NtGlobalFlag
 and al,70h
 cmp al,70h
 je being_debugged

但是我发现了一个更简单的解决方案,可以很好地发挥作用。

就像@“ Peter Cordes”所说的那样,只要不使用lodsq就可以访问值,我应该很好-

mov rax,gs:[60h]

经过进一步调查,我发现了这个reference

代码-

mov rax,gs:[60h]
mov al,[rax+BCh]
and al,70h
cmp al,70h
jz  being_debugged

我为程序做了一些修改-

    .code
GetValueFromASM proc
    
    mov rax,gs:[60h]
    mov al,[rax+0BCh]
    and al,70h
    cmp al,70h
    jz  being_debugged
    mov rax,0
    ret

    being_debugged:
    mov rax,1

    ret

GetValueFromASM endp
end

仅需注意一件事-

在Visual Studio 2017中运行时,返回的结果为0。这意味着没有附加调试器,它为False(因为我使用了本地Windows调试器)。

但是当使用WinDBG启动该进程时,它确实返回了1,这意味着它可以正常工作。

,

64位Windows显然使用fs指向“每个线程”的内存,因为gs为零。除了rand()的种子值之外,我不知道什么变量保留在“每个线程”的内存中。您可以调试使用rand()的程序,并在反汇编窗口中逐步查看它的访问方式。

向程序添加反调试器功能的成功与否取决于击败它的动机。主要问题是Windows远程调试,和/或使用在内核模式下运行的黑客安装的设备驱动程序来破坏反调试器功能。