Discussion:
lea with fs override
(too old to reply)
JC
2006-04-26 14:42:16 UTC
Permalink
I'd like to know, from userland, what base linear address my OS
(Windows XP) has set the FS segment (or GS, for that matter) to point
to.

I thought I could be clever, and do something like this (intel
syntax):

lea eax, fs:[0]

To figure this out. Unfortunately, LEA ignores segment overrides, and
I get back 0. Not helpful.

Is there another way to figure this out?

Thanks,
JC
[Jongware]
2006-04-27 11:30:23 UTC
Permalink
Post by JC
I'd like to know, from userland, what base linear address my OS
(Windows XP) has set the FS segment (or GS, for that matter) to point
to.
I thought I could be clever, and do something like this (intel
lea eax, fs:[0]
To figure this out. Unfortunately, LEA ignores segment overrides, and
I get back 0. Not helpful.
Is there another way to figure this out?
why not use
push fs
pop eax?

[jongware]
JC
2006-04-27 03:46:55 UTC
Permalink
Post by [Jongware]
why not use
push fs
pop eax?
Okay, that'd be great if my OS (Windows XP) ran in real mode.

Thankfully, though, it doesn't. In protected mode, this just gives me
a segment selector. I am interested in the base linear address that
the descriptor points to. AFAIK, there's nothing useful (from
userland) I can do to figure out the base address just from the
selector.

Thanks,
JC
Tim Roberts
2006-04-29 06:06:45 UTC
Permalink
JC <***@crayne.org> wrote:
?
Post by JC
Post by [Jongware]
why not use
push fs
pop eax?
Okay, that'd be great if my OS (Windows XP) ran in real mode.
Thankfully, though, it doesn't. In protected mode, this just gives me
a segment selector. I am interested in the base linear address that
the descriptor points to. AFAIK, there's nothing useful (from
userland) I can do to figure out the base address just from the
selector.
On XP, FS points to somewhere in the range of 7FFD0000 to 7FFE0000. I'm
not sure how that helps you.

GS is set to 0. I don't mean it's a selector with a base at 0 (like DS), I
mean it is the null selector. Trying to do
mov ax, gs:[0]
will result in a GPF.
--
- Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
robertwessel2@yahoo.com
2006-04-27 19:47:21 UTC
Permalink
Post by JC
I'd like to know, from userland, what base linear address my OS
(Windows XP) has set the FS segment (or GS, for that matter) to point
to.
I thought I could be clever, and do something like this (intel
lea eax, fs:[0]
To figure this out. Unfortunately, LEA ignores segment overrides, and
I get back 0. Not helpful.
Is there another way to figure this out?
In user mode, FS will always point to the current thread's TIB.
There's a pointer in there (at FS:0x18) that points to the linear
address of the TIB. It does something similar in the kernel.

While not particularly documented, the GDT itself isn't that hard to
find (although it's moved around in different versions of Windows), and
you can usually search from there. Try 0x80036000, it might still be
there (that was correct for at least some versions of 2GB Win2K).

Also, you could just search your address space for a block of memory
matching what's at FS:0. To make that simpler, TIBs are always page
aligned, and on a system with 2GB of user address space, are allocated
starting a little below the 2GB line and going down (there's something
like 128KB of other stuff first, then the PEB, then the TIBs). Or at
least those were the locations for Win2K.

A kernel debugger like SoftIce will also let you get to that stuff.

The first option (the FS:0x18 pointer) is the only thing approximating
a stable interface.

The question is what you're trying to accomplish.
JC
2006-04-28 00:54:56 UTC
Permalink
Post by ***@yahoo.com
The question is what you're trying to accomplish.
Fair enough. Just for kicks, I thought I'd write an interpreter for
x86 user programs. One of the things I thought would be interesting
would be to identify when particular linear addresses were read or
written.

Of course, to do this, I need to identify what linear addresses an
instruction is touching, which is generally easy except for these FS
segment overrides (and potentially GS too --- although, I don't know
that GS is used for anything special in WinXP).

I was hoping there might be a reasonably generic way to handle this
that didn't rely on baking in special knowledge about FS (like this
FS:0x18 business you mention).

But AFAIK, it doesn't seem like you can do this without kernel-level
help.

Ultimately, I think I'll just have to bite the bullet and go with the
FS:0x18 solution you mention. I didn't know about that before, thanks
for the tip.

Thanks,
JC
Charles Marslett
2006-05-14 03:50:30 UTC
Permalink
Post by JC
Post by ***@yahoo.com
The question is what you're trying to accomplish.
Fair enough. Just for kicks, I thought I'd write an interpreter for
x86 user programs. One of the things I thought would be interesting
would be to identify when particular linear addresses were read or
written.
Of course, to do this, I need to identify what linear addresses an
instruction is touching, which is generally easy except for these FS
segment overrides (and potentially GS too --- although, I don't know
that GS is used for anything special in WinXP).
I was hoping there might be a reasonably generic way to handle this
that didn't rely on baking in special knowledge about FS (like this
FS:0x18 business you mention).
But AFAIK, it doesn't seem like you can do this without kernel-level
help.
Ultimately, I think I'll just have to bite the bullet and go with the
FS:0x18 solution you mention. I didn't know about that before, thanks
for the tip.
Thanks,
JC
You could execute the SGDT to get the linear (or physical?) address of
the GDT, then you can take the segment selector and use it to index
into the GDT to find the segment base address. If the selector has
bit 2 set, then you need to execute an SLDT instruction to get the
selector of the LDT (in the SGT) and use the selector as an index into
the specific table. The instructions can be executed in user mode,
but the memory where the tables exist may or may not be readable.

And of course there are a good half dozen descriptor table entry
formats as well....

--Charles

Rod Pemberton
2006-04-28 00:36:15 UTC
Permalink
Post by JC
I'd like to know, from userland, what base linear address my OS
(Windows XP) has set the FS segment (or GS, for that matter) to point
to.
I thought I could be clever, and do something like this (intel
lea eax, fs:[0]
To figure this out. Unfortunately, LEA ignores segment overrides, and
I get back 0. Not helpful.
Is there another way to figure this out?
There is an instruction to get access rights, lar, and one to get the
segment limit, lsl. But, there isn't one to get the base address. You need
to locate the GDT (This is environment specific, i.e., I don't know how
to...). Once you've located the GDT, index into the GDT array by the
selector. Each selector should be a multiple of 8 which corresponds to it's
offset from the start of the GDT. (if FS is 0x18, descriptor is at address
of GDT plus 0x18). Copy your descriptor (8 bytes that your selector point
to). Extract the base address from the copied descriptor (you'll need the
Intel manuals for the layout, or it might be on www.sandpile.org). It's
possible that you'll need to locate a descriptor which points to the GDT to
give you access to the GDT which could be in it's own segment. The number
of selectors in the GDT can be determined from the segment limit of this
'GDT access' selector divided by eight.

That's all I've got...


Rod Pemberton
Loading...