Vulnerability Development mailing list archives

Re: Is GOT exploitable in solaris?


From: "Shaun Clowes" <shaun () securereality com au>
Date: Fri, 28 Dec 2001 07:31:30 aest


Hi,

Long post, apologies in advance.

The entry of Global Offset Table in linux is pointer to 
piece of executable code( say printf), so overwrite the 
pointer will force the process run your shellcode or 
whatever..

Not really, there is an important distinction here, under IA32 
the normal ELF Procedure Linkage Table (which is really what is 
being manipulated here) has as its first entry an instruction 
like
   
   call *<addr in GOT>

This allows lazy binding of functions (i.e the dynamic linker 
fills in the correct address in the GOT slot when it works out
where the function is on demand). 

This is clearly not possible on Sparc since there is no way to
do jump to an in memory address. You have two types of pc 
modification instructions, branch and call instructions (which
are PC relative) and the jmpl instruction which is register 
indirect.

Maybe a mistake/illusion after too much beer,  I found 
the Solaris implmentation of GOT entry is actually not 
pointer, but starting point of 3 instructions which 
finally jump to say, printf executable code. 

Exactly, a typical Sparc PLT entry looks like this before 
dynamic binding:

0x207cc <printf>:   sethi  %hi(0x1e000), %g1
0x207d0 <printf+4>: b,a   0x20754 <_PROCEDURE_LINKAGE_TABLE_>
0x207d4 <printf+8>: nop

So it basically sets the high bits of g1 to indicate to the
dynamic linker which symbol needs to be resolved and then
branches relative the start of the PLT which always contains
a binding to the dynamic linker resolution routine.

After dynamic binding (which is what you're seeing):

0x207cc <printf>:   sethi  %hi(0x1e000), %g1
0x207d0 <printf+4>: sethi  %hi(0x50075000), %g1
0x207d4 <printf+8>: jmp  %g1 + 0x1e8        ! 0x500751e8 <printf>

printf has been resolved to 0x500751e8, in order to achieve 
a jump absolute (since a jump absolute with immediate operand
isn't possible, given a instruction width of 32bits, too 
small to contain the complete operand) the high bits of g1 are
set with sethi then a register relative jump is used. 

So 
overwrite the entry with your shell code address 
simply corrupt these instruction but not control the 
process.

Yep, clearly this won't work.

I take it you need to get to your shellcode and have to do it
with one instruction (one 4 byte format string overwrite)? If 
your code is on the stack you're going to be in trouble because 
the best you could do is a CALL instruction with 30 bits of 
displacement which isn't enough to reach from low memory (the 
PLT) to high memory (the stack). If your code is on the heap 
you may be able to reach it (though I guess even that is 
unlikely).

I've never tried what you're attempting to do but if you can
exploit the format string multiple times you could overwrite
a couple of instructions in the PLT and create a JMPL 
instruction. 

Hope this comes in helpful,
Shaun


Current thread: