On Tuesday 06 May 2003 06:50 pm, Ove Kaaven wrote:
> Maybe this particular implementation, but C++ has other mechanisms that
> can be exploited. It might even be possible to bolt it on C++ native
> exceptions.
good point. For example, if we create a local object with a destructor that
can call finally, we just implemented magical return-notification, since the
language is guaranteed to call our destructor during unwinds due to an
exception or a return... of course, the devil is most assuredly in the
details ;)
> Apart from the ugliness, what was wrong with hijacking the return
> address? It might be possible to put into the TEB any data you need that
> you expect will go out of scope by the time the hijacker-function gets
> invoked, I think.
Well, we could just memorize the stack between the frame pointer and the stack
pointer, for example, and just put things back the way they were at some
prior time,... this "remembering" trick would have to go at the beginning of
the try block, however, which puts us in pretty dicey territory, a lot could
change between the beginning of the try block and the exception, so now our
frame is out-of-date, and the expected results are not achieved, i.e., local
integers time-warp back to what they were at the beginning of the try block
before the finally executes.
The only solution along this path that occurs to me is a frightening one: we
assume (actually, we know, since this will only happen due to a return in the
try block), upon invocation of our "interceptor" code, what happened: we were
exeucting the try block, and the bastard returned. So we just act on the
assumption that the stack frame is still sitting there, intact; we
immediately restore frame-pointer, stack-pointer, registers, etc., say, from
a setjmp() (not sure longjmp would do quite the right thing here, but
maybe...), and branch to the finally clause or some perversion thereof.
Then, when finally's done, we need to tear down everything back to what it
was before we intercepted. (setjmp/longjmp should be fine for this second
branch, into a secondary(?) JMP_BUF in the TEB), and continue on our merry
way by magically returning the correct value to the caller... easy ;)
Seriously, I dunno, sounds pretty darn sketchy... we would need to be able to
rest assured that the act of returning will not somehow mangle the stack on
the way out, and that doesn't seem so clear to me...
Worth a shot, I guess....
--
"Security is mostly superstition. It does not exist in nature,
nor do the children of men as a whole experience it. Avoiding
danger is no safer in the long run than outright exposure. Life is
either a daring adventure, or nothing. To keep our faces toward
change and behave like free spirits in the presence of fate is
strength undefeatable." --Helen Keller
gmt