Adding GDT/LDT entries in Windows XP/2003 (for AMD64)

What’s the proper DDK API and procedure to add entries in
descriptor table? I need to add a descriptor for a 32-bit segment.

Background:
I want to load 32-bit image with a 64-bit loader in user mode.
The image does not directly use any APIs from OS and I want
it to be loaded and run in the same process as the 64-bit loader.
According to the AMD manuals, far call to a 32-bit segment
can switch the processor from 64-bit to 32-bit mode. But it
seems that there’s no 32-bit descriptor (in a 64-bit process)
that I can use to make the switch. Hence the question above.

Strangely, I could do the reverse: load and run 64-bit image
with a 32-bit loader! In a 32-bit process, there is a descriptor
(GDT: 0x30) for 64-bit segment, and a descriptor (GDT: 0x20)
for 32-bit segment. I make a far call from my 32-bit loader
and the 64-bit image run and return (with retf) to the loader
successfully.

In a 64-bit process, however, there seems no descriptor for
32-bit segment.

Thank you.

Isaac Chen

> What’s the proper DDK API and procedure to add entries in

descriptor table? I need to add a descriptor for a 32-bit segment.
Background:
I want to load 32-bit image with a 64-bit loader in user mode.

There is no a “proper” way to do modify LDT/GDT, all ways are
not documented/not supported by Microsoft.

For LDT entries on x86 Windows google for ZwSetLdtEntries and
NtSetLdtEntries.
These functions are also documented in Gary Nebbett’s
book “Windows NT/2000 Native API Reference”.

I have no idea about these functions on x64 Windows.

Loading a 32 bit binary in 64 bit process is a bad idea.
If it works now it can stop working with any patch.
Spawn a 32-bit process form 64-bit process, load the 32-bit binary
in 32-bit process context and do IPC/shared memory/etc. communications
between
the two processes. It is the right way.

Dmitriy Budko, VMware

NtSetLdtEntries returned 0xc0000002. Not implemented?

I’m wondering why there’s no 32-bit descriptor in the GDT of my 64-bit
process even when the system has other 32-bit processes running.
I’ve checked, in 32-bit process, the selector is 0x20, which selects
an entry in GDT. Isn’t GDT supposed to be global? Or maybe the
32-bit selector is there in my 64-bit process, but something wrong
in my mode switching process?

In WinDBG, I could see the exception occur at the far call instruction.
If I modify the selector for that far call to 0x30 (0x33) the program
could continue. That’s why I suspect 0x20 is not setup for the 32-bit
code segment. Any way to check the GDT entries of my process
in WinDBG (or other API)?

BTW, I’m OK with undocumented/unsupported methods. I’m not
developing products. Just an exercise on AMD 64-bit box. :sunglasses:

Thank you.

Isaac Chen

“Dmitriy Budko” wrote in message news:xxxxx@ntdev…
> What’s the proper DDK API and procedure to add entries in
> descriptor table? I need to add a descriptor for a 32-bit segment.
> Background:
> I want to load 32-bit image with a 64-bit loader in user mode.

There is no a “proper” way to do modify LDT/GDT, all ways are
not documented/not supported by Microsoft.

For LDT entries on x86 Windows google for ZwSetLdtEntries and
NtSetLdtEntries.
These functions are also documented in Gary Nebbett’s
book “Windows NT/2000 Native API Reference”.

I have no idea about these functions on x64 Windows.

Loading a 32 bit binary in 64 bit process is a bad idea.
If it works now it can stop working with any patch.
Spawn a 32-bit process form 64-bit process, load the 32-bit binary
in 32-bit process context and do IPC/shared memory/etc. communications
between
the two processes. It is the right way.

Dmitriy Budko, VMware

Isaac,

regardless of whether you can modify the LDT/GDT, you’ll have other
problems using this method.

The OS will still think that your task is running in 64-bit mode, so any
interrupt or trap may well ignore to do “things” that are necessary for a
32-bit application when the OS sees the context as being 64-bit. Interrupts
can cause this to happen without any control from your side.

I think it would be a much better solution to load the image into a new
context created as a 32-bit context, so that the OS is fully aware of the
transition from 64- to 32-bit.


Mats
xxxxx@lists.osr.com wrote on 01/21/2005 03:36:39 AM:

What’s the proper DDK API and procedure to add entries in
descriptor table? I need to add a descriptor for a 32-bit segment.

Background:
I want to load 32-bit image with a 64-bit loader in user mode.
The image does not directly use any APIs from OS and I want
it to be loaded and run in the same process as the 64-bit loader.
According to the AMD manuals, far call to a 32-bit segment
can switch the processor from 64-bit to 32-bit mode. But it
seems that there’s no 32-bit descriptor (in a 64-bit process)
that I can use to make the switch. Hence the question above.

Strangely, I could do the reverse: load and run 64-bit image
with a 32-bit loader! In a 32-bit process, there is a descriptor
(GDT: 0x30) for 64-bit segment, and a descriptor (GDT: 0x20)
for 32-bit segment. I make a far call from my 32-bit loader
and the 64-bit image run and return (with retf) to the loader
successfully.

In a 64-bit process, however, there seems no descriptor for
32-bit segment.

Thank you.

Isaac Chen


Questions? First check the Kernel Driver FAQ at http://www.
osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@3dlabs.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

ForwardSourceID:NT0000B44A

Mats,

I didn’t really think it through. As I said in another post, I did this just
as an exercise in an AMD 64-bit box.

I was even considering 16-bit mode. I know Windows for AMD 64
doesn’t support 16-bit code. But since my 16-bit code won’t need
support from Windows (directly), I thought maybe it’s not that hard.

Thank you for your input.

Isaac Chen

“Mats PETERSSON” wrote in message
news:xxxxx@ntdev…
>
> Isaac,
>
> regardless of whether you can modify the LDT/GDT, you’ll have other
> problems using this method.
>
> The OS will still think that your task is running in 64-bit mode, so any
> interrupt or trap may well ignore to do “things” that are necessary for a
> 32-bit application when the OS sees the context as being 64-bit.
Interrupts
> can cause this to happen without any control from your side.
>
> I think it would be a much better solution to load the image into a new
> context created as a 32-bit context, so that the OS is fully aware of the
> transition from 64- to 32-bit.
>
> –
> Mats
> xxxxx@lists.osr.com wrote on 01/21/2005 03:36:39 AM:
>
> > What’s the proper DDK API and procedure to add entries in
> > descriptor table? I need to add a descriptor for a 32-bit segment.
> >
> > Background:
> > I want to load 32-bit image with a 64-bit loader in user mode.
> > The image does not directly use any APIs from OS and I want
> > it to be loaded and run in the same process as the 64-bit loader.

Isaac,

What are you ACTUALLY trying to achieve here… If you explain what it is
you’re trying to do, it is quite possible that I or someone else on this
list can suggest a suitable solution. But trying to “reverse engineer” your
idea so that we can figure out what’s the best solution for your situation
isn’t that easy, and trying to suggest solutions to unknown problems isn’t
a good plan.

“messing” with the descriptor table is definitely not something you should
do unless there is ABSOLUTELY no other way.

Of course, if you’re just trying to prove a concept, why not just use a
kernel driver to modify your LDT or GDT, just pick a selector somewhere
around the middle (far from either end), and use that. But that obviously
won’t work for a commercial product. Don’t need a system call do modify the
GDT, just do “store GDT” and modify the address that it points to [you may
have to map that address, I can’t remember if the GDT is physical or
logical addresses].


Mats

xxxxx@lists.osr.com wrote on 01/21/2005 12:05:13 PM:

Mats,

I didn’t really think it through. As I said in another post, I did this
just
as an exercise in an AMD 64-bit box.

I was even considering 16-bit mode. I know Windows for AMD 64
doesn’t support 16-bit code. But since my 16-bit code won’t need
support from Windows (directly), I thought maybe it’s not that hard.

Thank you for your input.

Isaac Chen

“Mats PETERSSON” wrote in message
> news:xxxxx@ntdev…
> >
> > Isaac,
> >
> > regardless of whether you can modify the LDT/GDT, you’ll have other
> > problems using this method.
> >
> > The OS will still think that your task is running in 64-bit mode, so
any
> > interrupt or trap may well ignore to do “things” that are necessary for
a
> > 32-bit application when the OS sees the context as being 64-bit.
> Interrupts
> > can cause this to happen without any control from your side.
> >
> > I think it would be a much better solution to load the image into a new
> > context created as a 32-bit context, so that the OS is fully aware of
the
> > transition from 64- to 32-bit.
> >
> > –
> > Mats
> > xxxxx@lists.osr.com wrote on 01/21/2005 03:36:39 AM:
> >
> > > What’s the proper DDK API and procedure to add entries in
> > > descriptor table? I need to add a descriptor for a 32-bit segment.
> > >
> > > Background:
> > > I want to load 32-bit image with a 64-bit loader in user mode.
> > > The image does not directly use any APIs from OS and I want
> > > it to be loaded and run in the same process as the 64-bit loader.
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.
> osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@3dlabs.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

> ForwardSourceID:NT0000B492

I’m only trying to “load and run a 32-bit code in a 64-bit process”.
Or “to prove a concept” after skim through a few pages of AMD’s
manuals. Really appreciate that you want to know “my true
intention” and offer help. :sunglasses:

I asked for an API because I don’t know where in the descriptor
table I can touch. I’m afraid I mess it up and crash the system.
Moreover, inline assembly doesn’t work in (AMD) 64-bit compiler.
It’s kind of inconvenient even if I want to touch LDT/GDT directly.
BTW, “#pragma code_seg(.text)” doesn’t seem to work, either.
So I started to think there must be better ways.

Maybe I can try to modify the DT “around the middle” in a kernel
mode driver. To determine the middle, I’ll need to know its
length first 8-(. Anyway, I’ll give it a try.

Thank you.

Isaac Chen

“Mats PETERSSON” wrote in message
news:xxxxx@ntdev…
>
> Isaac,
>
> What are you ACTUALLY trying to achieve here… If you explain what it is
> you’re trying to do, it is quite possible that I or someone else on this
> list can suggest a suitable solution. But trying to “reverse engineer”
your
> idea so that we can figure out what’s the best solution for your situation
> isn’t that easy, and trying to suggest solutions to unknown problems isn’t
> a good plan.
>
> “messing” with the descriptor table is definitely not something you should
> do unless there is ABSOLUTELY no other way.
>
> Of course, if you’re just trying to prove a concept, why not just use a
> kernel driver to modify your LDT or GDT, just pick a selector somewhere
> around the middle (far from either end), and use that. But that obviously
> won’t work for a commercial product. Don’t need a system call do modify
the
> GDT, just do “store GDT” and modify the address that it points to [you may
> have to map that address, I can’t remember if the GDT is physical or
> logical addresses].
>
> –
> Mats

You should be able to write assembler, even if you can’t do it inline. You
just have to make it an external routine and use MASM. The DDK contains a
64-bit version of MASM, and if you put a SOURCES file inside a AMD64
directory, and place a .asm file in this directory (and add it to the
sources file, of course), you should be able to build the code as part of a
normal DDK build.

If you use SLDT or SGDT, it shoul store a base-address and size [called
LIMIT by Intels documentation] (the first being 64-bit and the second being
16-bit). Then examine the address and size that comes out and see where
“the middle” is.


Mats

-------- Notice --------
The information in this message is confidential and may be legally
privileged. It is intended solely for the addressee. Access to this
message by anyone else is unauthorized. If you are not the intended
recipient, any disclosure, copying or distribution of the message, or any
action taken by you in reliance on it, is prohibited and may be unlawful.
If you have received this message in error, please delete it and contact
the sender immediately. Thank you.

xxxxx@lists.osr.com wrote on 01/21/2005 12:56:46 PM:

I’m only trying to “load and run a 32-bit code in a 64-bit process”.
Or “to prove a concept” after skim through a few pages of AMD’s
manuals. Really appreciate that you want to know “my true
intention” and offer help. :sunglasses:

I asked for an API because I don’t know where in the descriptor
table I can touch. I’m afraid I mess it up and crash the system.
Moreover, inline assembly doesn’t work in (AMD) 64-bit compiler.
It’s kind of inconvenient even if I want to touch LDT/GDT directly.
BTW, “#pragma code_seg(.text)” doesn’t seem to work, either.
So I started to think there must be better ways.

Maybe I can try to modify the DT “around the middle” in a kernel
mode driver. To determine the middle, I’ll need to know its
length first 8-(. Anyway, I’ll give it a try.

Thank you.

Isaac Chen

“Mats PETERSSON” wrote in message
> news:xxxxx@ntdev…
> >
> > Isaac,
> >
> > What are you ACTUALLY trying to achieve here… If you explain what it
is
> > you’re trying to do, it is quite possible that I or someone else on
this
> > list can suggest a suitable solution. But trying to “reverse engineer”
> your
> > idea so that we can figure out what’s the best solution for your
situation
> > isn’t that easy, and trying to suggest solutions to unknown problems
isn’t
> > a good plan.
> >
> > “messing” with the descriptor table is definitely not something you
should
> > do unless there is ABSOLUTELY no other way.
> >
> > Of course, if you’re just trying to prove a concept, why not just use a
> > kernel driver to modify your LDT or GDT, just pick a selector somewhere
> > around the middle (far from either end), and use that. But that
obviously
> > won’t work for a commercial product. Don’t need a system call do modify
> the
> > GDT, just do “store GDT” and modify the address that it points to [you
may
> > have to map that address, I can’t remember if the GDT is physical or
> > logical addresses].
> >
> > –
> > Mats
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.
> osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@3dlabs.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

> ForwardSourceID:NT0000B49E