February 12th, 2008 Greg
The stack 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 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:
- 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 (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) 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.
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.
Posted in Hacking, RCE | No Comments »
January 29th, 2008 Greg
If you were wondering why things have been so quiet for the past month, it’s because I’ve been spending my every waking hour learning to hack. This explains the presence of a new category here on the site, and the motivation behind some of the upcoming topics. It would be a shame to let January pass us by, so here comes an introductory post on the exciting science of shellcoding. First, some formalities:
Shellcode (shĕl’kōd)
n.
A relocatable piece of executable code used as the payload in a software exploit, typically having the purpose of providing the attacker with unauthorised access to the system at which it is directed.
v. [shellcod•ing, shellcod•er]
The process of developing shellcode and tailoring it to a particular target.
A piece of software is said to be vulnerable (to exploitation) if it contains a bug which allows a user to cause it to behave in a way unintended by the developers, by supplying appropriately crafted data to one of its normal input mechanisms. The faulty processing of this input is the vulnerability, and any operation that takes advantage of this is an exploit. The data used in such an exploit is the payload, and the executable component of this payload is the shellcode. While a distinction exists between an exploit’s payload and its shellcode, the two terms are often used interchangeably. The name ’shellcode’ derives from the fact that many Unix exploits would work toward the goal of delivering a shell to the attacker, but this is not a necessary criterion under today’s usage.
Not all exploits will require shellcode, as certain goals may be achieved without it, but we’ll primarily concern ourselves with vulnerabilities that lead to execution of arbitrary code (i.e. the shellcode), as that’s the holy grail of the hacker. While vulnerabilities can fall into many categories, there are a few of particular interest, and these are the ones I’ll concentrate on. Putting the theory into practice is the real stumbling-block, and so along the way I’ll discuss common problems the average Windows shellcoder will run into. Here’s the battle-plan:
- Stack overflows
- Heap overflows
- Format-string vulnerabilities
- String filters, shellcode-location and other technical problems
- Non-executable stacks and stack-canaries
I appreciate that this is a lot of material to cover, and that you may be best off buying a book (The Shellcoder’s Handbook handles this vast subject magnificently), but I aim to spend as little time as possible on the bread-and-butter material that can be found just about everywhere, while putting far more focus on the practical side of things. See you next week.
Posted in Hacking, RCE | No Comments »