_EOF_
gera@vaiolent:~src/sg/tests$ chmod +x sg1.exp
gera@vaiolent:~src/sg/tests$ ./sg1.exp
In the example we abuse strcpy() to write 20 copies of shellcode’s address
to GOT’s address (0x08049888 from readelf’s output). As we use the same
strcpy() to move our “shellcode” to a known address, we know it will be
located exactly 92 bytes ahead of GOT. That’s what $code addr’s value is. We
are using a pretty simple shellcode that will only do an infinite loop, this way
it’s easy to know when it’s being executed.
On the other hand, if StackShield is used, the program may keep going on
as if nothing has happened, and we’ll need to check if some library functions
are called further in the vulnerable program, use another technique, like chang-
ing “atexit functions”, or simply overwrite the cloned return address saved
in retarray if we have some clue of where in memory it’s located. If the -d
command switch is used, StackShield will just issue a SYS exit system call,
not calling any other code on user space before ending the process. In this
last case, if no library call is made and no function pointer is used after the
write-anything-anywhere operation, we won’t be able to exploit the program,
unless we can overwrite the return address with its original value (effectively
not changing it), thus cheating StackShield’s attack detection code. To use the
same pseudo-exploit, remove Cnry and, if you used -d, replace RET with the
correct value.
If StackShield is used in the “automatic return address recovery” mode,
we can control not only local variables and function arguments for the current
frame, but we can also alter and abuse the control over previous frames, raising
the posibilities for successful exploitation.
3.2 Returning with an altered frame pointer
On standard frame pointer overwrite exploits([11]), on the first return you gain
control over the frame pointer, and right before the second return you gain
control over the stack pointer, hence controling where the function will return.
On StackShielded programs, as return addresses are mantained in a global
array, even if you control the stack pointer, you won’t be able to hook the execu-
tion flow on the second return
8
. If the program is protected with StackGuard,
the thing is a little different.
The default for StackGuard
9
is to use a terminator canary, a fixed value of
0x000aff0d. With common string operations it’s not possible to write past this
canary, but it’s possible to write up to the canary, without altering it, effectively
gaining full control of the frame pointer. For the rest of this section we’ll focus
our analisys on StackGuard using a terminator canary.
8
Of course, if “force exit on attack” (-d) switch is used, you’ll just make the program exit
on the second return, unless, again, you supply the correct return address.
9
StackGuard included in[8] as of February 1, 2002, egcs version 2.91.66-StackGuard, version
2.0.1.
17