Understanding Win 7 x64 GDT/LDT

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.

Q1 Setup:
When I look at the GDT and segment selectors in the kernel my VM I see this:

0: kd> dd @gdtr
fffff80000b95000 00000000 00000000 00000000 00000000 fffff80000b95010 00000000 00209b00 0000ffff 00cf9300
fffff80000b95020 0000ffff 00cffa00 0000ffff 00cff300 fffff80000b95030 00000000 0020fb00 00000000 00000000
fffff80000b95040 60800067 00008bb9 fffff800 00000000 fffff80000b95050 e0003c00 ff40f3fa 00000000 00000000
fffff80000b95060 0000ffff 00cf9a00 00000000 00000000 fffff80000b95070 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.

So
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

Q1:
But what is index C used for? I haven’t seen anything reference it, but maybe someone else has?

Q2 setup:
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
PROCESS fffffa8000de27f0
SessionId: 1 Cid: 0bcc Peb: 7fffffdf000 ParentCid: 0338
DirBase: 173d4000 ObjectTable: fffff8a001c92790 HandleCount: 278.
Image: notepad.exe

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
ntdll!NtOpenFile:
00000000777401e0 4c8bd1 mov r10,rcx 00000000777401e3 b830000000 mov eax,30h
00000000777401e8 0f05 syscall 00000000777401ea 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] = fffff880009e8000 1: kd\> rdmsr 0xC0000102 msr[c0000102] = 000007fffffdd000
1: kd> !teb
TEB at 000007fffffdd000

Q2:
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.

thks

JB

Who cares all of this? GDT and LDT, together with the whole segmentation stuff - far pointers etc - are obsolete remnant of 80286 era. For something like 20-25 years for now.

Traditionally, GDT was only used in WinNT to implement TLS in user mode and PCR in kernel mode, but I will not be surprised if Intel invented some new opcodes to do the same.

LDT was not used by WinNT at all except for Win16 NTVDM emulation.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> 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.
>
> Q1 Setup:
> When I look at the GDT and segment selectors in the kernel my VM I see this:
>
> 0: kd> dd @gdtr
> fffff80000b95000 00000000 00000000 00000000 00000000<br>&gt; fffff80000b95010 00000000 00209b00 0000ffff 00cf9300
> fffff80000b95020 0000ffff 00cffa00 0000ffff 00cff300<br>&gt; fffff80000b95030 00000000 0020fb00 00000000 00000000
> fffff80000b95040 60800067 00008bb9 fffff800 00000000<br>&gt; fffff80000b95050 e0003c00 ff40f3fa 00000000 00000000
> fffff80000b95060 0000ffff 00cf9a00 00000000 00000000<br>&gt; fffff80000b95070 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.
>
> So
> 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
>
> Q1:
> But what is index C used for? I haven’t seen anything reference it, but maybe someone else has?
>
> Q2 setup:
> 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
> PROCESS fffffa8000de27f0
> SessionId: 1 Cid: 0bcc Peb: 7fffffdf000 ParentCid: 0338
> DirBase: 173d4000 ObjectTable: fffff8a001c92790 HandleCount: 278.
> Image: notepad.exe
>
> 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
> ntdll!NtOpenFile:
> 00000000777401e0 4c8bd1 mov r10,rcx<br>&gt; 00000000777401e3 b830000000 mov eax,30h
> 00000000777401e8 0f05 syscall<br>&gt; 00000000777401ea c3 ret
> 00000000777401eb 0f1f440000 nop dword ptr [rax+rax]<br>&gt; <br>&gt; So OK, I should be in userspace (this is 64 bit notepad btw) in the kernel debugger at this point. So I do<br>&gt; <br>&gt; 1: kd&gt; rdmsr 0xC0000101<br>&gt; msr[c0000101] = fffff880009e8000
> 1: kd> rdmsr 0xC0000102
> msr[c0000102] = 000007ff`fffdd000
> 1: kd> !teb
> TEB at 000007fffffdd000
>
> Q2:
> 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.
>
> thks
>
> JB
>
>

I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
reason enough for this list? :slight_smile:

Security people care about it because while Windows may have added KPP to
protect its GDT, other OSes haven’t. I know windbg way better than I know
kernel debugging for linux, so I’d rather learn how it’s working on Windows
with WinDbg before I struggle with gdb or kdb or whatever.

And it’s clearly not obsolete, as OSes and hypervisors still have to deal
with it to a minimum degree or they can’t get their code running.
Similarly, if you’re trying to do any trusted coding (like using Intel
Trusted Execution Technology, ala the open source project tboot) you need
to know how to set up segmentation/paging in your trusted environment.
Obviously you can do it however you want, but I think it’s good to learn
from existing implementations.

So yeah, it’s obscure, but some people somewhere still have to care or else
OSes/VMMs can’t run. Usually though the best practice is if you don’t care,
you don’t need to spend time replying :wink:

JB

p.s. MS patented using the LDT for user mode scheduling, so it’s
baaaaacccckkkk :wink: http://www.faqs.org/patents/app/20080320475 “Each user
mode thread block in a process has a descriptor in a local descriptor
table.”

On Thu, Aug 8, 2013 at 12:54 PM, Maxim S. Shatskih
wrote:

> Who cares all of this? GDT and LDT, together with the whole
> segmentation stuff - far pointers etc - are obsolete remnant of 80286 era.
> For something like 20-25 years for now.
>
> Traditionally, GDT was only used in WinNT to implement TLS in user
> mode and PCR in kernel mode, but I will not be surprised if Intel invented
> some new opcodes to do the same.
>
> LDT was not used by WinNT at all except for Win16 NTVDM emulation.
>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
> wrote in message news:xxxxx@ntdev…
> > 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.
> >
> > Q1 Setup:
> > When I look at the GDT and segment selectors in the kernel my VM I see
> this:
> >
> > 0: kd> dd @gdtr
> > fffff80000b95000 00000000 00000000 00000000 00000000<br>&gt; &gt; fffff80000b95010 00000000 00209b00 0000ffff 00cf9300
> > fffff80000b95020 0000ffff 00cffa00 0000ffff 00cff300<br>&gt; &gt; fffff80000b95030 00000000 0020fb00 00000000 00000000
> > fffff80000b95040 60800067 00008bb9 fffff800 00000000<br>&gt; &gt; fffff80000b95050 e0003c00 ff40f3fa 00000000 00000000
> > fffff80000b95060 0000ffff 00cf9a00 00000000 00000000<br>&gt; &gt; fffff80000b95070 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.
> >
> > So
> > 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
> >
> > Q1:
> > But what is index C used for? I haven’t seen anything reference it, but
> maybe someone else has?
> >
> > Q2 setup:
> > 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
> > PROCESS fffffa8000de27f0
> > SessionId: 1 Cid: 0bcc Peb: 7fffffdf000 ParentCid: 0338
> > DirBase: 173d4000 ObjectTable: fffff8a001c92790 HandleCount: 278.
> > Image: notepad.exe
> >
> > 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
> > ntdll!NtOpenFile:
> > 00000000777401e0 4c8bd1 mov r10,rcx<br>&gt; &gt; 00000000777401e3 b830000000 mov eax,30h
> > 00000000777401e8 0f05 syscall<br>&gt; &gt; 00000000777401ea c3 ret
> > 00000000777401eb 0f1f440000 nop dword ptr [rax+rax]<br>&gt; &gt;<br>&gt; &gt; So OK, I should be in userspace (this is 64 bit notepad btw) in the<br>&gt; kernel debugger at this point. So I do<br>&gt; &gt;<br>&gt; &gt; 1: kd&gt; rdmsr 0xC0000101<br>&gt; &gt; msr[c0000101] = fffff880009e8000
> > 1: kd> rdmsr 0xC0000102
> > msr[c0000102] = 000007ff`fffdd000
> > 1: kd> !teb
> > TEB at 000007fffffdd000
> >
> > Q2:
> > 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.
> >
> > thks
> >
> > JB
> >
> >
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

>I cares, because I like to know how stuff works :slight_smile: Isn’t that usually reason enough for this list? :slight_smile:

This is a tiny undocumented detail, which can change even from SP to SP, not to say from version to version.

If you have a practical need to implement some functionality in Windows - then you do not need segments and selectors anyway.

For instance, at some older times (NT4/w2k), when I was interested in this, Windows was not using LDT at all and just nearly ignored its existence (except NTVDM’s Win16 emulation).

If you never ever use LDT selectors - then you can ignore the very fact LDT exists.

It is not so with GDT, which is mandatory for some stuff like the TSS, and TSS is mandatory for user/kernel stack switching.

From what I remember, there is per-CPU GDT, with some pre-defined selector value describing the PCR in kernel mode (and this value is loaded to FS in kernel mode), and with some pre-defined selector value for TEB in user mode, this value is loaded to FS in user mode. The “TEB descriptor” in the GDT was updated each time on a thread switch in the kernel.

Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top of __try/__except handler list.

I don’t think there were more then “kernel data, kernel code, user data, user code, TSS, TLS and PCR” descriptors in the GDT.

Note that this feature is peculiar to particular CPU, i.e. x86, and there is a major possibility that, in last 10 years, Intel have introduced some new CPU features to replace this obsolete stuff (like SYSENTER to replace INT 2EH). Probably modern Windows use these new features.

Hypervisors do not need to virtualize GDT/LDT, they work at lower level of paging (all addresses in the descriptors are linear ones).

x86/MS-DOS emulators surely need to emulate GDT/LDT.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

I appreciate you contributing what you know, but that’s also the stuff I
already know since it’s already in that security class I linked to. And
you’re correct, I don’t need to know about this to implement any features,
just to satisfy my curiosity (I emailed the instructor and he said he’s
going to make an x64 class in maybe 6 months but he doesn’t currently know
the answers.)

What I’m trying to learn is the Win 7 x64 stuff specifically. E.g. I’ve
already learned about the use of GS instead of FS to point at the TEB/KPCR,
the use of the swapgs instruction when combined with syscall (the x64
successor of sysetner) or how the GDT is much smaller than it used to be.
It’s just those last little bits of knowledge I asked about in the original
post which still ellude me (and which this infodump unfortunately didn’t
sate.)

JB

On Thu, Aug 8, 2013 at 3:18 PM, Maxim S. Shatskih wrote:

> >I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
> reason enough for this list? :slight_smile:
>
> This is a tiny undocumented detail, which can change even from SP to SP,
> not to say from version to version.
>
> If you have a practical need to implement some functionality in Windows
> - then you do not need segments and selectors anyway.
>
> For instance, at some older times (NT4/w2k), when I was interested in
> this, Windows was not using LDT at all and just nearly ignored its
> existence (except NTVDM’s Win16 emulation).
>
> If you never ever use LDT selectors - then you can ignore the very fact
> LDT exists.
>
> It is not so with GDT, which is mandatory for some stuff like the TSS, and
> TSS is mandatory for user/kernel stack switching.
>
> From what I remember, there is per-CPU GDT, with some pre-defined selector
> value describing the PCR in kernel mode (and this value is loaded to FS in
> kernel mode), and with some pre-defined selector value for TEB in user
> mode, this value is loaded to FS in user mode. The “TEB descriptor” in the
> GDT was updated each time on a thread switch in the kernel.
>
> Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
> of try/ except handler list.
>
> I don’t think there were more then “kernel data, kernel code, user data,
> user code, TSS, TLS and PCR” descriptors in the GDT.
>
> Note that this feature is peculiar to particular CPU, i.e. x86, and there
> is a major possibility that, in last 10 years, Intel have introduced some
> new CPU features to replace this obsolete stuff (like SYSENTER to replace
> INT 2EH). Probably modern Windows use these new features.
>
> Hypervisors do not need to virtualize GDT/LDT, they work at lower level of
> paging (all addresses in the descriptors are linear ones).
>
> x86/MS-DOS emulators surely need to emulate GDT/LDT.
>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Virtual CPU (virtual machine control structure for intel and something
similar for amd) has fields for segment selectors , base addresses for
segment descriptor and segment limits. Also it has such fields as gdt and
ldt base and limits.

To op - if you really want to know that stuff you should download intel or
amd developer manual: volume 3 for intel and volume 2 for amd

On Thursday, August 8, 2013, Maxim S. Shatskih wrote:

>I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
reason enough for this list? :slight_smile:

This is a tiny undocumented detail, which can change even from SP to SP,
not to say from version to version.

If you have a practical need to implement some functionality in Windows

  • then you do not need segments and selectors anyway.

For instance, at some older times (NT4/w2k), when I was interested in
this, Windows was not using LDT at all and just nearly ignored its
existence (except NTVDM’s Win16 emulation).

If you never ever use LDT selectors - then you can ignore the very fact
LDT exists.

It is not so with GDT, which is mandatory for some stuff like the TSS, and
TSS is mandatory for user/kernel stack switching.

From what I remember, there is per-CPU GDT, with some pre-defined selector
value describing the PCR in kernel mode (and this value is loaded to FS in
kernel mode), and with some pre-defined selector value for TEB in user
mode, this value is loaded to FS in user mode. The “TEB descriptor” in the
GDT was updated each time on a thread switch in the kernel.

Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
of __try/__except handler list.

I don’t think there were more then “kernel data, kernel code, user data,
user code, TSS, TLS and PCR” descriptors in the GDT.

Note that this feature is peculiar to particular CPU, i.e. x86, and there
is a major possibility that, in last 10 years, Intel have introduced some
new CPU features to replace this obsolete stuff (like SYSENTER to replace
INT 2EH). Probably modern Windows use these new features.

Hypervisors do not need to virtualize GDT/LDT, they work at lower level of
paging (all addresses in the descriptors are linear ones).

x86/MS-DOS emulators surely need to emulate GDT/LDT.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com <javascript:>
> http://www.storagecraft.com
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
></javascript:>

Also you can read “rootkit arsenal” book

On Friday, August 9, 2013, Sergey Pisarev wrote:

Virtual CPU (virtual machine control structure for intel and something
similar for amd) has fields for segment selectors , base addresses for
segment descriptor and segment limits. Also it has such fields as gdt and
ldt base and limits.

To op - if you really want to know that stuff you should download intel or
amd developer manual: volume 3 for intel and volume 2 for amd

On Thursday, August 8, 2013, Maxim S. Shatskih wrote:

> >I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
> reason enough for this list? :slight_smile:
>
> This is a tiny undocumented detail, which can change even from SP to SP,
> not to say from version to version.
>
> If you have a practical need to implement some functionality in Windows
> - then you do not need segments and selectors anyway.
>
> For instance, at some older times (NT4/w2k), when I was interested in
> this, Windows was not using LDT at all and just nearly ignored its
> existence (except NTVDM’s Win16 emulation).
>
> If you never ever use LDT selectors - then you can ignore the very fact
> LDT exists.
>
> It is not so with GDT, which is mandatory for some stuff like the TSS,
> and TSS is mandatory for user/kernel stack switching.
>
> From what I remember, there is per-CPU GDT, with some pre-defined
> selector value describing the PCR in kernel mode (and this value is loaded
> to FS in kernel mode), and with some pre-defined selector value for TEB in
> user mode, this value is loaded to FS in user mode. The “TEB descriptor” in
> the GDT was updated each time on a thread switch in the kernel.
>
> Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
> of __try/__except handler list.
>
> I don’t think there were more then “kernel data, kernel code, user data,
> user code, TSS, TLS and PCR” descriptors in the GDT.
>
> Note that this feature is peculiar to particular CPU, i.e. x86, and there
> is a major possibility that, in last 10 years, Intel have introduced some
> new CPU features to replace this obsolete stuff (like SYSENTER to replace
> INT 2EH). Probably modern Windows use these new features.
>
> Hypervisors do not need to virtualize GDT/LDT, they work at lower level
> of paging (all addresses in the descriptors are linear ones).
>
> x86/MS-DOS emulators surely need to emulate GDT/LDT.
>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

IIRC there was also some brief description of how LDT is used in VDM
environment in SoftICE manuals.

Kris

On Fri, Aug 9, 2013 at 10:07 AM, Sergey Pisarev
wrote:
> Also you can read “rootkit arsenal” book
>
>
> On Friday, August 9, 2013, Sergey Pisarev wrote:
>>
>> Virtual CPU (virtual machine control structure for intel and something
>> similar for amd) has fields for segment selectors , base addresses for
>> segment descriptor and segment limits. Also it has such fields as gdt and
>> ldt base and limits.
>>
>> To op - if you really want to know that stuff you should download intel or
>> amd developer manual: volume 3 for intel and volume 2 for amd
>>
>> On Thursday, August 8, 2013, Maxim S. Shatskih wrote:
>>>
>>> >I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
>>> > reason enough for this list? :slight_smile:
>>>
>>> This is a tiny undocumented detail, which can change even from SP to SP,
>>> not to say from version to version.
>>>
>>> If you have a practical need to implement some functionality in Windows
>>> - then you do not need segments and selectors anyway.
>>>
>>> For instance, at some older times (NT4/w2k), when I was interested in
>>> this, Windows was not using LDT at all and just nearly ignored its existence
>>> (except NTVDM’s Win16 emulation).
>>>
>>> If you never ever use LDT selectors - then you can ignore the very fact
>>> LDT exists.
>>>
>>> It is not so with GDT, which is mandatory for some stuff like the TSS,
>>> and TSS is mandatory for user/kernel stack switching.
>>>
>>> From what I remember, there is per-CPU GDT, with some pre-defined
>>> selector value describing the PCR in kernel mode (and this value is loaded
>>> to FS in kernel mode), and with some pre-defined selector value for TEB in
>>> user mode, this value is loaded to FS in user mode. The “TEB descriptor” in
>>> the GDT was updated each time on a thread switch in the kernel.
>>>
>>> Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
>>> of try/ except handler list.
>>>
>>> I don’t think there were more then “kernel data, kernel code, user data,
>>> user code, TSS, TLS and PCR” descriptors in the GDT.
>>>
>>> Note that this feature is peculiar to particular CPU, i.e. x86, and there
>>> is a major possibility that, in last 10 years, Intel have introduced some
>>> new CPU features to replace this obsolete stuff (like SYSENTER to replace
>>> INT 2EH). Probably modern Windows use these new features.
>>>
>>> Hypervisors do not need to virtualize GDT/LDT, they work at lower level
>>> of paging (all addresses in the descriptors are linear ones).
>>>
>>> x86/MS-DOS emulators surely need to emulate GDT/LDT.
>>>
>>> –
>>> Maxim S. Shatskih
>>> Microsoft MVP on File System And Storage
>>> xxxxx@storagecraft.com
>>> http://www.storagecraft.com
>>>
>>>
>>> —
>>> NTDEV is sponsored by OSR
>>>
>>> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>>>
>>> OSR is HIRING!! See http://www.osr.com/careers
>>>
>>> For our schedule of WDF, WDM, debugging and other seminars visit:
>>> http://www.osr.com/seminars
>>>
>>> To unsubscribe, visit the List Server section of OSR Online at
>>> http://www.osronline.com/page.cfm?name=ListServer
>
> — NTDEV is sponsored by OSR Visit the list at:
> http://www.osronline.com/showlists.cfm?list=ntdev OSR is HIRING!! See
> http://www.osr.com/careers For our schedule of WDF, WDM, debugging and other
> seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List
> Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer


Kris

I’ve read all of Intel Vol 3 Ch 1-10 & Ch 35 (MSRs) backwards and forwards.
I would hope that already showed in my original post. The manuals tell you
how something can be used, not how an OS vendor chose to use it. Hence, the
manuals can’t tell me what MS is using GDT index 0xC for, or how they’re
using the LDT for win 7 user mode scheduling. I know this is not common
knowledge, as typically it’s only people like the Windows Internals authors
or Miller/Johnson (both now at MS and probably prevented from talking, but
I know they lurk on this list) who bother to dig this deep into how stuff
works. But I do appreciate all atempts to help.

JB
p.s. Rootkits Arsenal is pretty bad. 2nd edition somehow managed to be even
worse than the first by cutting out more of the OS stuff (which the author
clearly doesn’t know well) in favor of the forensics stuff (which the
author does know, but which I don’t care about). But if you like reading
books by people who don’t know how to use the -> C operator, it’s great.
On Fri, Aug 9, 2013 at 5:04 AM, Sergey Pisarev wrote:

> Virtual CPU (virtual machine control structure for intel and something
> similar for amd) has fields for segment selectors , base addresses for
> segment descriptor and segment limits. Also it has such fields as gdt and
> ldt base and limits.
>
> To op - if you really want to know that stuff you should download intel or
> amd developer manual: volume 3 for intel and volume 2 for amd
>
>
> On Thursday, August 8, 2013, Maxim S. Shatskih wrote:
>
>> >I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
>> reason enough for this list? :slight_smile:
>>
>> This is a tiny undocumented detail, which can change even from SP to SP,
>> not to say from version to version.
>>
>> If you have a practical need to implement some functionality in Windows
>> - then you do not need segments and selectors anyway.
>>
>> For instance, at some older times (NT4/w2k), when I was interested in
>> this, Windows was not using LDT at all and just nearly ignored its
>> existence (except NTVDM’s Win16 emulation).
>>
>> If you never ever use LDT selectors - then you can ignore the very fact
>> LDT exists.
>>
>> It is not so with GDT, which is mandatory for some stuff like the TSS,
>> and TSS is mandatory for user/kernel stack switching.
>>
>> From what I remember, there is per-CPU GDT, with some pre-defined
>> selector value describing the PCR in kernel mode (and this value is loaded
>> to FS in kernel mode), and with some pre-defined selector value for TEB in
>> user mode, this value is loaded to FS in user mode. The “TEB descriptor” in
>> the GDT was updated each time on a thread switch in the kernel.
>>
>> Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
>> of try/ except handler list.
>>
>> I don’t think there were more then “kernel data, kernel code, user data,
>> user code, TSS, TLS and PCR” descriptors in the GDT.
>>
>> Note that this feature is peculiar to particular CPU, i.e. x86, and there
>> is a major possibility that, in last 10 years, Intel have introduced some
>> new CPU features to replace this obsolete stuff (like SYSENTER to replace
>> INT 2EH). Probably modern Windows use these new features.
>>
>> Hypervisors do not need to virtualize GDT/LDT, they work at lower level
>> of paging (all addresses in the descriptors are linear ones).
>>
>> x86/MS-DOS emulators surely need to emulate GDT/LDT.
>>
>> –
>> Maxim S. Shatskih
>> Microsoft MVP on File System And Storage
>> xxxxx@storagecraft.com
>> http://www.storagecraft.com
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>>
>> OSR is HIRING!! See http://www.osr.com/careers
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
> — NTDEV is sponsored by OSR Visit the list at:
> http://www.osronline.com/showlists.cfm?list=ntdev OSR is HIRING!! See
> http://www.osr.com/careers For our schedule of WDF, WDM, debugging and
> other seminars visit: http://www.osr.com/seminars To unsubscribe, visit
> the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Then I guess you out of luck on this list. People with access to windows
sources present here but it is not likely they would share that type
of knowledge
about windows internals.

I am sorry if my post insulted you, that wasn’t my intention at all.

On Friday, August 9, 2013, Jimbo Bob wrote:

I’ve read all of Intel Vol 3 Ch 1-10 & Ch 35 (MSRs) backwards and
forwards. I would hope that already showed in my original post. The manuals
tell you how something can be used, not how an OS vendor chose to use it.
Hence, the manuals can’t tell me what MS is using GDT index 0xC for, or how
they’re using the LDT for win 7 user mode scheduling. I know this is not
common knowledge, as typically it’s only people like the Windows Internals
authors or Miller/Johnson (both now at MS and probably prevented from
talking, but I know they lurk on this list) who bother to dig this deep
into how stuff works. But I do appreciate all atempts to help.

JB
p.s. Rootkits Arsenal is pretty bad. 2nd edition somehow managed to be
even worse than the first by cutting out more of the OS stuff (which the
author clearly doesn’t know well) in favor of the forensics stuff (which
the author does know, but which I don’t care about). But if you like
reading books by people who don’t know how to use the -> C operator, it’s
great.
On Fri, Aug 9, 2013 at 5:04 AM, Sergey Pisarev wrote:
>
> Virtual CPU (virtual machine control structure for intel and something
> similar for amd) has fields for segment selectors , base addresses for
> segment descriptor and segment limits. Also it has such fields as gdt and
> ldt base and limits.
>
> To op - if you really want to know that stuff you should download intel or
> amd developer manual: volume 3 for intel and volume 2 for amd
>
>
> On Thursday, August 8, 2013, Maxim S. Shatskih wrote:
>
> >I cares, because I like to know how stuff works :slight_smile: Isn’t that usually
> reason enough for this list? :slight_smile:
>
> This is a tiny undocumented detail, which can change even from SP to SP,
> not to say from version to version.
>
> If you have a practical need to implement some functionality in Windows
> - then you do not need segments and selectors anyway.
>
> For instance, at some older times (NT4/w2k), when I was interested in
> this, Windows was not using LDT at all and just nearly ignored its
> existence (except NTVDM’s Win16 emulation).
>
> If you never ever use LDT selectors - then you can ignore the very fact
> LDT exists.
>
> It is not so with GDT, which is mandatory for some stuff like the TSS, and
> TSS is mandatory for user/kernel stack switching.
>
> From what I remember, there is per-CPU GDT, with some pre-defined selector
> value describing the PCR in kernel mode (and this value is loaded to FS in
> kernel mode), and with some pre-defined selector value for TEB in user
> mode, this value is loaded to FS in user mode. The “TEB descriptor” in the
> GDT was updated each time on a thread switch in the kernel.
>
> Offset 0 in both PCR and TEB - aka fs:[0000000] - is IIRC the current top
> of try/ except handler list.
>
> I don’t think there were more then “kernel data, kernel code, user data,
> user code, TSS, TLS and PCR” descriptors in the GDT.
>
> Note that this feature is peculiar to particular CPU, i.e. x86, and there
> is a major possibility that, in last 10 years, Intel have introduced some
> new CPU features to replace this obsolete stuff (like SYSENTER to replace
> INT 2EH). Probably modern Windows use these new features.
>
> Hypervisors do not need to virtualize GDT/LDT, they work at lower level of
> paging (all addresses in the descriptors are linear ones).
>
> x86/MS-DOS emulators surely need to emulate GDT/LDT.
>
> –
> Maxim S. Shatskih
> Microsoft MVP on File System And Storage
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> — NTDEV is sponsored by OSR Visit the list at:
> http://www.osronline.com/showlists.cfm?list=ntdev OSR is HIRING!! See
> http://www.osr.com/careers For our schedule of WDF, WDM, debugging and
> other seminars visit: http://www.osr.com/seminars To unsubscribe, visit
> the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
>
> — NTDEV is sponsored by OSR Visit the list at:
> http://www.osronline.com/showlists.cfm?list=ntdev OSR is HIRING!! See
> http://www.osr.com/careers For our schedule of WDF, WDM, debugging and
> other seminars visit: http://www.osr.com/seminars To unsubscribe, visit
> the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer&lt;http:</http:>

Jimbo, why do you need the plugin? GDT entry format has changed in 64bit mode, if the plugin wasn’t updated, then the information it dumps is wrong. There is a command ‘dg’ in WinDbg, it dumps a GDT entry. You can see its output here: http://www.osronline.com/showthread.cfm?link=176667

The dg command is broken for x64 (it says in the manual tho that it only
supports x86, so it’s expected. I’m using WinDbg 6.2.9200 which I think is
the latest). That’s why I updated that other 3rd party plugin to show me
valid x64 GDT information.

JB

On Fri, Aug 9, 2013 at 7:39 PM, wrote:

> Jimbo, why do you need the plugin? GDT entry format has changed in 64bit
> mode, if the plugin wasn’t updated, then the information it dumps is wrong.
> There is a command ‘dg’ in WinDbg, it dumps a GDT entry. You can see its
> output here: http://www.osronline.com/showthread.cfm?link=176667
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

When you do a .process /i, the target machine attaches a kernel worker
thread to the specified process (KeStackAttachProcess) and then breaks into
the host. Thus, when you break in you’re not in the context of a Notepad
thread, you’re in the context of a System thread attached to the Notepad
process. I suspect that this explains your different TEB values. For
example:

0: kd> !process 0 2 notepad.exe
PROCESS fffffa800e2d55c0
SessionId: 1 Cid: 08bc Peb: 7f7da78e000 ParentCid: 08e8
DirBase: 11a08000 ObjectTable: fffff8a004505940 HandleCount: Accessible>
Image: notepad.exe

THREAD fffffa800ee00180 Cid 08bc.0974 Teb: 000007f7da78c000
Win32Thread: fffff901022cfb90

0: kd> bp /t fffffa800ee00180 nt!ntcreatefile
0: kd> g
Breakpoint 0 hit
nt!NtCreateFile:
fffff800a4063590 4881ec88000000 sub rsp,88h<br>0: kd&gt; !process -1 0<br>PROCESS fffffa800e2d55c0<br> SessionId: 1 Cid: 08bc Peb: 7f7da78e000 ParentCid: 08e8<br> DirBase: 11a08000 ObjectTable: fffff8a004505940 HandleCount: <data not>Accessible&gt;<br> Image: notepad.exe<br><br>0: kd&gt; rdmsr 0xC0000101<br>msr[c0000101] = fffff800a3efa000
0: kd> rdmsr 0xC0000102
msr[c0000102] = 000007f7da78c000<br>0: kd&gt; r @$teb<br>$teb=000007f7da78c000<br>0: kd&gt; !teb<br>TEB at 000007f7da78c000<br><br>-scott<br>OSR<br><br>wrote in message news:xxxxx@ntdev...<br><br>Hi all, I'm just trying to update my x86 architecture knowledge to be <br>AMD64-relevant. I think I have a handle on almost everything going on WRT <br>segmentation on 64 bit win 7, but I'd like to get a sanity check if <br>possible.<br><br>Q1 Setup:<br>When I look at the GDT and segment selectors in the kernel my VM I see this:<br><br>0: kd&gt; dd @gdtr<br>fffff80000b95000 00000000 00000000 00000000 00000000
fffff80000b95010 00000000 00209b00 0000ffff 00cf9300<br>fffff80000b95020 0000ffff 00cffa00 0000ffff 00cff300
fffff80000b95030 00000000 0020fb00 00000000 00000000<br>fffff80000b95040 60800067 00008bb9 fffff800 00000000
fffff80000b95050 e0003c00 ff40f3fa 00000000 00000000<br>fffff80000b95060 0000ffff 00cf9a00 00000000 00000000
fffff80000b95070 00000000 00000000 00000000 00000000<br><br>Which interpreted with a slightly updated version of the windbg plugin from <br>http://opensecuritytraining.info/IntermediateX86.html (because there's no 64 <br>bit version of the class yet) is:<br><br>GDT[0x00] = Empty Descriptor.<br>GDT[0x01] = Empty Descriptor.<br>GDT[0x02] = 64 bit ring 0 Code: Execute/Read, Accessed<br>GDT[0x03] = 32 bit ring 0 Data: Read/Write, Accessed<br>GDT[0x04] = 32 bit ring 3 Code: Execute/Read<br>GDT[0x05] = 32 bit ring 3 Data: Read/Write, Accessed<br>GDT[0x06] = 64 bit ring 3 Code: Execute/Read, Accessed<br>GDT[0x07] = Empty Descriptor.<br>GDT[0x08] = 64-bit TSS (Busy)<br>GDT[0x0a] = 32 bit ring 3 Data: Read/Write, Accessed<br>GDT[0x0b] = Empty Descriptor.<br>GDT[0x0c] = 32 bit ring 0 Code: Execute/Read<br>GDT[0x0d] = Empty Descriptor.<br>GDT[0x0e] = Empty Descriptor.<br>GDT[0x0f] = Empty Descriptor.<br><br>So<br>index 2 = kernel 64 bit code segment<br>index 3 = kernel data segment<br>index 4 = userspace 32 bit code segment<br>index 5 = userspace data segment<br>index 6 = userspace 64 bit code segment (I saw a blog post talking about how <br>32 bit code far jumps into this segment before calling to kernel, and I <br>confirmed this.)<br>index 8 = 64 bit TSS (pointed to by task register)<br>index A = what the FS register (32 bit TEB?) points at<br><br>Q1:<br>But what is index C used for? I haven't seen anything reference it, but <br>maybe someone else has?<br><br>Q2 setup:<br>I want to confirm that in userspace GS points at a 64 bit address for the <br>TEB. Because data segments can't actually specify a 64 bit address, that <br>means I should be able to read MSR IA32_GS_BASE (0xC0000101) from a forced <br>userspace context and see the same thing as if I do !teb, right?<br>So I do<br>1: kd&gt; !process 0 0 notepad.exe<br>PROCESS fffffa8000de27f0<br> SessionId: 1 Cid: 0bcc Peb: 7fffffdf000 ParentCid: 0338<br> DirBase: 173d4000 ObjectTable: fffff8a001c92790 HandleCount: 278.<br> Image: notepad.exe<br><br>1: kd&gt; .process /i fffffa8000de27f0<br>1: kd&gt; g<br>0: kd&gt; .reload (the .process /r option never works properly for me)<br>0: kd&gt; u ntdll!NtOpenFile<br>ntdll!NtOpenFile:<br>00000000777401e0 4c8bd1 mov r10,rcx
00000000777401e3 b830000000 mov eax,30h<br>00000000777401e8 0f05 syscall
00000000777401ea c3 ret<br>00000000777401eb 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] = fffff880009e8000<br>1: kd&gt; rdmsr 0xC0000102<br>msr[c0000102] = 000007fffffdd000
1: kd> !teb
TEB at 000007fffffdd000

Q2:
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.

thks

JB