I'm trying to understand how to resolve segment addressing (specifically the GS register in X64).
My toy program:
int main()
{
unsigned long long x;
__debugbreak();
x = __readgsqword(0x30);
printf("0x%I64X", x);
}
which compiles to:
kd> u
00007ff6`10201074 cc int 3
00007ff6`10201075 65488b142530000000 mov rdx,qword ptr gs:[30h]
...
Then I step once to reach the instruction which reads memory using the GS
register, and I retrieve the value of the GS
register, the content of the GDT, etc.
kd> r @gs
gs=002b
kd> r @gdtr
gdtr=fffff80105471fb0
kd> .formats @gs
Evaluate expression:
Hex: 00000000`0000002b
...
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00101011
kd> dq (@gdtr + (5 * 8)) L1
fffff801`05471fd8 00cff300`0000ffff
kd> .formats poi(@gdtr + (5 * 8))
Evaluate expression:
Hex: 00cff300`0000ffff
...
Binary: 00000000 11001111 11110011 00000000 00000000 00000000 11111111 11111111
kd> dg gs
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
002B 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3
So from dg gs
, I can see that the GS
segment is at offset 0x0
, which is consistent with the entry retrieved from the GDT using the GS
register value.
Observe that at this point, offset 0x0
is not "valid" memory:
kd> dq gs:[30]
002b:00000000`00000030 ????????`???????? ????????`????????
kd> dq 30
00000000`00000030 ????????`???????? ????????`????????
Also note that the value of RDX
at this point (before storing the QWORD retrieved from memory):
kd> r @rdx
rdx=000001dfbf892d40
Then I step once, expecting a bug check as I am retrieving invalid memory.
But surprisingly, it doesn't, and RDX
appeared to have gotten assigned a value from somewhere:
kd> r @rdx
rdx=00000035ed53f000
Even more surprising, the GS
register still resolves to offset 0x0
which still contains "invalid" memory!
kd> r @gs
gs=002b
kd> r @gdtr
gdtr=fffff80105471fb0
kd> dq (@gdtr + (5 * 8)) L1
fffff801`05471fd8 00cff300`0000ffff
kd> dg gs
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
002B 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3
kd> dq gs:[30]
002b:00000000`00000030 ????????`???????? ????????`????????
So...
Why does my
GS
register resolve to offset 0x0?And where/how does the
mov rdx,qword ptr gs:[30h]
read memory from?