Why the gs segment register is address is set to 0x0000000000000000 on visual studio x64(MASM)?

980 Views Asked by At

I am currently reading "The Ultimate Anti Debugging Reference" and I am trying to implement some of the techniques.

To check the Value of the NtglobalFlag they use this code -

 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

I did all the correct adjustments for running x64 code on visual studio 2017 I used this tutorial.

I used this instruction to accesses the NtGlobalFlag

lodsq gs:[rsi]

because their syntax didn't work on Visual studio.

But still, it didn't work.

While debugging I've noticed that the value of the gs register is set to 0x0000000000000000 while the fs register is set to a real value 0x0000007595377000.

I don't understand why the value of GS was zeroed, because it should have its value set on x64.

2

There are 2 best solutions below

4
Cyber_Noob On BEST ANSWER

So I still don't understand why the code posted here caused so many problems, As I said I just copied it from "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

But I've found a simpler solution that works perfectly.

As @"Peter Cordes" said I should be good with just accessing the value without lodsq like so -

mov rax, gs:[60h]

And after further investigation, I found this reference,

Code -

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

And I modified it a little bit for my program -

    .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

Just one thing to note -

When running inside visual studio 2017 the result returned was 0. Meaning no debugger attached which is False (Because I used the Local Windows Debugger).

But when launching the process with WinDBG it did return 1 which means that it works.

0
rcgldr On

64 bit Windows is apparently using fs to point to "per thread" memory, since gs is zero. I don't know what variables are kept in "per thread" memory, other than the seed value for rand(). You could debug a program that used rand(), and step through it in a disassembler window, to see how it is accessed.

The success of adding an anti-debugger feature to a program will depend on how much motivation there is to defeat it. The main issue is Windows remote debugging, and/or using a hacker installed device driver running in kernel mode to defeat an anti-debugger feature.