Hi all, I'm just trying to update my x86 architecture knowledge to be AMD64-relevant. I think I have a handle on almost everything going on WRT segmentation on 64 bit win 7, but I'd like to get a sanity check if possible.
When I look at the GDT and segment selectors in the kernel my VM I see this:
0: kd> dd @gdtr
fffff800`00b95000 00000000 00000000 00000000 00000000
fffff800`00b95010 00000000 00209b00 0000ffff 00cf9300
fffff800`00b95020 0000ffff 00cffa00 0000ffff 00cff300
fffff800`00b95030 00000000 0020fb00 00000000 00000000
fffff800`00b95040 60800067 00008bb9 fffff800 00000000
fffff800`00b95050 e0003c00 ff40f3fa 00000000 00000000
fffff800`00b95060 0000ffff 00cf9a00 00000000 00000000
fffff800`00b95070 00000000 00000000 00000000 00000000
Which interpreted with a slightly updated version of the windbg plugin from http://opensecuritytraining.info/IntermediateX86.html
(because there's no 64 bit version of the class yet) is:
GDT[0x00] = Empty Descriptor.
GDT[0x01] = Empty Descriptor.
GDT[0x02] = 64 bit ring 0 Code: Execute/Read, Accessed
GDT[0x03] = 32 bit ring 0 Data: Read/Write, Accessed
GDT[0x04] = 32 bit ring 3 Code: Execute/Read
GDT[0x05] = 32 bit ring 3 Data: Read/Write, Accessed
GDT[0x06] = 64 bit ring 3 Code: Execute/Read, Accessed
GDT[0x07] = Empty Descriptor.
GDT[0x08] = 64-bit TSS (Busy)
GDT[0x0a] = 32 bit ring 3 Data: Read/Write, Accessed
GDT[0x0b] = Empty Descriptor.
GDT[0x0c] = 32 bit ring 0 Code: Execute/Read
GDT[0x0d] = Empty Descriptor.
GDT[0x0e] = Empty Descriptor.
GDT[0x0f] = Empty Descriptor.
index 2 = kernel 64 bit code segment
index 3 = kernel data segment
index 4 = userspace 32 bit code segment
index 5 = userspace data segment
index 6 = userspace 64 bit code segment (I saw a blog post talking about how 32 bit code far jumps into this segment before calling to kernel, and I confirmed this.)
index 8 = 64 bit TSS (pointed to by task register)
index A = what the FS register (32 bit TEB?) points at
But what is index C used for? I haven't seen anything reference it, but maybe someone else has?
I want to confirm that in userspace GS points at a 64 bit address for the TEB. Because data segments can't actually specify a 64 bit address, that means I should be able to read MSR IA32_GS_BASE (0xC0000101) from a forced userspace context and see the same thing as if I do !teb, right?
So I do
1: kd> !process 0 0 notepad.exe
SessionId: 1 Cid: 0bcc Peb: 7fffffdf000 ParentCid: 0338
DirBase: 173d4000 ObjectTable: fffff8a001c92790 HandleCount: 278.
1: kd> .process /i fffffa8000de27f0
1: kd> g
0: kd> .reload (the .process /r option never works properly for me)
0: kd> u ntdll!NtOpenFile
00000000`777401e0 4c8bd1 mov r10,rcx
00000000`777401e3 b830000000 mov eax,30h
00000000`777401e8 0f05 syscall
00000000`777401ea c3 ret
00000000`777401eb 0f1f440000 nop dword ptr [rax+rax]
So OK, I should be in userspace (this is 64 bit notepad btw) in the kernel debugger at this point. So I do
1: kd> rdmsr 0xC0000101
msr[c0000101] = fffff880`009e8000
1: kd> rdmsr 0xC0000102
msr[c0000102] = 000007ff`fffdd000
1: kd> !teb
TEB at 000007fffffdd000
OK, so the TEB address seems to be in IA32_KERNEL_GS_BASE...so maybe it's just because I'm in the kernel debugger it's doing the swapgs instruction before calling back into the kernel debugger?
But here's the thing which I don't get at all. If I then resume the VM, go into the VM and attach with userspace windbg, and do !teb, I get
TEB at 000007fffffd9000
Anyone know why they show different addresses?
Q3: I've heard that Winodws 7 starts to use the LDT for user-mode scheduling? How would I see evidence of that? Because ? @ldtr shows up as zero for me, and I don't see any LDT entry in the GDT.