Ring3 Circus
February 12th, 2008, 05:30
The stack overflow ("http://en.wikipedia.org/wiki/Stack_buffer_overflow") has been discussed to death. If you don’t know the basic principle, then you should check out some of the the sixty-eight thousand hits ("http://www.google.com/search?&hl=en&q=Stack-Overflow&btnG=Google+Search") on Google. Many of these descriptions would have you believe that any overflowable stack buffer will immediately allow the attacker to get root (or whatever the Windows equivalent might be), but if you’ve ever tried to exploit a real-world stack overflow vulnerability you’d realise that it’s a lot harder than it sounds. Here are some of the more common problems:
http://www.ring3circus.com/rce/shellcoding-on-windows-part-ii-stack-overflow-problems/
All of these problems can be appeased to a degree through a variety of techniques. Notably, the use of structured exception handling in the target application can make our job as an attacker considerably easier as we may be able to abuse the SEH records and sidestep several of these problems in one go. Details next time.
A user-modifiable stack buffer is usually designed to hold string data, but even when this isn’t the case, it’s rare to find a situation where arbitrary input is accepted and blindly copied to the stack. It’s not infeasible that your shellcode will be restricted to null-terminated printable ASCII (that’s 0×20-0×7E inclusive), and if you’ve ever tried to write code that assembles into this range you’ll realise that it’s no mean feat. Furthermore, not all strings are ASCII and even a seasoned hacker can have trouble crafting an executable Unicode string.
If you’re able to provide an arbitrary amount of data then overflowing a return-address is easy. But what’s not so straightforward is ensuring that the function actually gets a chance to return - after all, you have just corrupted every stack variable between the buffer and the return-address.
Suppose that your shellcode compiles okay, passes the input filters; no crashes occur and that you now own EIP after the vulnerable function returns. Just where should you make the target return to? Understand that the address from which to commence execution must be known at the time the shellcode is provided, and moreover that - in the paradigm case - your shellcode lies ’somewhere’ on the stack. Inherent in the nature of stack-based function architecture is the fact that the same function can execute many times without ever taking the same value of ESP. This problem of locating your shellcode after injection is one that never seems to go away and has become the bane of many hackers’ lives.
If we weren’t already struggling enough, the recent shift in focus towards security has prompted the Windows kernel developers to take more and more precautions regarding the execution of data buffers. Windows XP SP2 introduced DEP (data-execution prevention) for Windows Services, and Vista/Server 2003 extended this to protect all processes by default. This means that as of Windows Vista, any attempts to execute code on the stack will fail with a warning dialog from the OS, provided the system’s processor supports the NX/XD bit ("http://en.wikipedia.org/wiki/Nx_bit") (Intel and AMD couldn’t agree on nomenclature, apparently).
Because the OS can only do so much, many compilers now ship with support for automatic security code-generation. In particular, Visual Studio 2005 introduced the GS flag, which creates what Microsoft are calling a Security Cookie (but to everyone else, a stack canary ("http://en.wikipedia.org/wiki/Stack-smashing_protection#Random_canaries")) within each function’s stack frame. With this option enabled, each function will push a pseudo-random dword onto the stack in its prologue, and check that it hasn’t been modified by the time the epilogue is reached. This way, any attempts to overflow into the return-address will corrupt the canary and alert the program before the RETN occurs.
http://www.ring3circus.com/rce/shellcoding-on-windows-part-ii-stack-overflow-problems/