Visual Studio x64(MASM)中GS段寄存器为何被设为0x0000000000000000?
解决x64环境下GS寄存器为0及NtGlobalFlag反调试失效问题
嘿,我之前折腾反调试技术的时候也碰到过一模一样的问题,来给你掰扯清楚:
首先得纠正一个关键误解:**x64 Windows的用户态程序里,GS寄存器默认就是0!**这完全不是异常情况——GS段在内核态才用来访问KPCR(内核处理器控制区),而用户态下我们要获取PEB(进程环境块),靠的是FS段寄存器,你看到FS有有效值才是正常的,之前把FS和GS的用户态用途搞混啦。
回到你的代码问题:书中的写法大概率是针对NASM这类汇编器的语法,而VS2017用的MASM语法有差异,再加上x64下PEB的访问路径不对,才导致失效。咱们一步步修正:
适配VS2017 MASM的x64 NtGlobalFlag检测代码
; 获取PEB指针:x64用户态下,FS:[0x30] 直接指向PEB的地址 mov rax, qword ptr fs:[0x30] ; 读取NtGlobalFlag字段(PEB的偏移量在Win10/11 x64下通常是0xBC,你也可以通过调试器确认) mov al, byte ptr [rax + 0xBC] ; 检测调试标记组合:0x70对应三个调试相关的Flag位 and al, 0x70 cmp al, 0x70 je being_debugged ; 如果匹配,说明正在被调试
你的原代码失效的核心原因
- GS寄存器的认知错误:用户态x64程序里GS=0是标准行为,别把它和内核态的GS用法混淆,用户态访问PEB只能靠FS段。
- MASM语法不兼容:书中的
gs:lodsq是NASM风格的段前缀写法,MASM里的段前缀应该写在括号前,比如fs:[...],你改成lodsq gs:[rsi]既不符合MASM语法,还选错了段寄存器。
最后补个小tip:不同Windows版本的PEB结构可能有微小偏移变化,你可以用x64dbg加载程序后,查看fs:[0x30]指向的内存,手动确认NtGlobalFlag的准确偏移,确保万无一失。
内容的提问来源于stack exchange,提问作者Cyber_Noob




