Vulnerability Development mailing list archives

Re: GetPC code (was: Shellcode from ASCII)


From: noir <noir () gsu linux org tr>
Date: Thu, 20 Nov 2003 00:12:15 +0200 (EET)


hey Aaron,

thanks for enlighting us about the internals of all this FPU stuff.
highly appreciated. i did actually take it from the FPU exception handler 
and to be honest never looked into the intel manuals for what it really 
does ;>

i can think of yet another getPC technique for some Unixes (at least on 
Solaris x86 and sparc), i will leave it as a challenge to the list.

hint: involves a kernel service ;)

best luck,
- noir



On Tue, 18 Nov 2003, Aaron Adams wrote:

Hey Noir,

I've been looking into FPU stuff a bit lately and decided to look into
what you described a little deeper. I decided I'd give you and the list
the details of what the deal is with this.

Basically, you can do a GetPC procedure without simulating any exception.
In fact, the data stored by fnstenv isn't influenced by the exception nor
is it actually an exception record. fstenv/fnstenv is commonly used by FPU
exception handler code though, to analyze the state of the FPU environment
that an exception occured within.

Although you are triggering an exception, all of the exception bits in the
control word are masked by default when the environment is initialized. As
such, if an exception occurs the only result will be the appropriate
exception flag being set within the status word.

So, keeping this in mind we'll see what actually allows the GetPC to be
possible. Basically, the state of the FPU environment, following the first
floating point instruction, is always maintained. The fnstenv/fstenv
instructions can be used to save the state of the environment to the
location pointed to by it's operand. So the only requirement to actually
using fstenv/fnstenv is to have previously executed an FP instruction.

The structure stored by fnstenv is defined as user_fpregs_struct in
sys/user.h and is saved as so:

0  | Control Word
4  | Status Word
8  | Tag Word
12 | FPU Instruction Pointer Offset
...
...

As you explained, the FPU Instruction Pointer will be the address of the
previously executed FP instruction. And as seen above it's located at
offset 12 within the structure.

Because we can specify the location that fnstenv stores the structure
I came up with something that can kind of simplify obtaining the PC. It
can be seen in the following code, which is the smallest way I could come
up with to do a GetPC procedure.

fldz
fnstenv -12(%esp)
popl %ecx
addb 10, %cl
nop

So, when this is executed you'll have the current pc in ecx when you hit
nop. It's pretty similar to what you did, but hopefully it clarifies some
stuff.

ttyl.

Aaron Adams


On Fri, 27 Jun 2003, noir wrote:

"""
First thoughts on the second challenge: You can't use any of the call
opcodes, but you might be able to setup a quick exception handler in
the known mapped space. Cause a fault, and then find the address of
your fault causing instruction in the structure that's passed. (Again
I'm talking NT).

    I'm not sure this could be done (same problem) but, keep this in mind
anyway :-
) [hint]

    gera
"""

i have spend good 20 minutes on this, i don't have the solution yet due to
lack of time but i thought this might be interesting for the list.

basicly, i'm simulating a floating point exception (division by zero) and
then grabbing the EIP(pc) from the exception record. PC is the location of
the fdivs instruction since that instruction created the exception
condition so we add 11 on top to make %eax point to the nop instruction.
(ATT syntax)

        xor     %eax, %eax
        push    %eax
        fdivs   (%esp)
        fnstenv (%esp)
        mov     0xc(%esp), %eax
        add     $0xd, %eax
        nop


- noir

sup mate ? ;)











Current thread: