Hacking: Lecture One Follow-up

March 29th, 2008 by peasleer

On Tuesday I gave the first of a series of lectures following the “hacking” track. I’m staying far, far away from an IT perspective - I’m not teaching nmap or how to use wireshark, nor am I discussing web vulnerabilities. No - I strive for a higher path, focusing the audience on dodging the skiddie [1] bullet and pointing them toward the real stuff. The talk went well, the audience was very engaged, asked great questions, and had good ideas when I asked for them. 98% of the content was in the talk, but as promised, the slides are now available for your viewing pleasure.

View the presentation here (Google docs, no download necessary).

There are varying requests for where to go next in the series. I had originally planned on gradually introducing more complex topics over a set of three lectures, hence the very general nature of the first. However, the group that came seems more interested in jumping directly to application, requesting a live demo of an exploit and accompanied explanation. When this idea was first presented I was a little hesitant - I was hoping to give people the knowledge necessary to be a jumping point, this is a little more direct. While it will take a lot more preparation, I think I’m going to end up using a demonstration to fuel my next lecture, conflating theory and practice.

A couple questions were asked that I think deserve more attention than I could give them on Tuesday:

Q: Are people who use Gentoo and compile everything more secure than someone who uses prepackaged binaries?

A: Absolutely not. The argument provided in conjunction with the question was that some compiler flags may change the layout of the program in memory, thus making new exploits developed for common versions of programs ineffective against the customized versions. Yes, there are a number of cases where this may be true, but that number is likely negligible. Compilers modify logic, unroll loops, and handle other things that have to do with instructions - rarely do they modify data, which is what we care about in the track we are following. Because the stack isn’t modified so heavily that the vulnerable components are removed, a bigger NOP [2] sled is often all that is required to have the same exploit work on your optimized code.

There are exceptions to this, but not in optimization flags. Introducing canaries is an option that is available to use when compiling with certain versions of GCC [3]. Canaries are simply two modifications: the first is introducing a random integer to a variable that gets placed between the rest of the stack frame’s variables and return address, and the second is a simple conditional that checks the value of that number. If the number is overwritten by whatever data we used in overwriting the return address of the stack frame, the conditional check will fail, and the program will exit with an error indicating a failed canary check (usually a reason for an admin to show concern). This is the only current compiler flag option I know of that will stop non-specialized exploits from delivering their payloads to your box.

More important however is the need to address the question’s ignorance. The short and correct answer to the question is “no, in fact you are less secure.” Feeling invulnerable is the most dangerous thing you can do for the security of your systems. It doesn’t matter how your binaries are obtained and compiled - if a vulnerability exists for the version of the program you are using, you are vulnerable. Your intermediate steps may have bought you time, but feeling safe causes complacency, and the second you feel complacent is the same second the security of your system is philosophically compromised.

Q: Isn’t it true that operating systems are running most programs in ring0?

A: No; in fact, the opposite is true. The full question was posed using language and concepts that hadn’t been introduced yet, so for those that were just being introduced to the field it was a bit foreign. Ring0 and Ring1 respectively refer to kernel and user space, which are concepts in operating system design that separate the operating system’s running components from programs the user runs. Without a separation, a user would have the ability to modify the kernel’s components which is a Bad Thing ™.

From the definition above, it should be obvious why the answer to the question is no. It is true that all programs make calls to kernel space functions exposed through an operating system’s API, but at no point does the user’s program enter the kernel itself to execute code. This was not always the case, but it has been for the last several years, and the separation only grows more defined with each new generation of operating systems. Note that there are ways to get code running in kernel space through drivers or kernel hooking (check out rootkits if this line of research interests you), but it requires some trickery and administrative access on the machine - no normal program does it.

And with that, I’ll close. The next couple days will be spent in part preparing the next lecture in the series, where we’ll see a demonstration, some actual shellcode, and a dive into further understanding memory and the mindset of the innovative hackers that develop these techniques.

[1] Script kiddie, a wanna-be hacker that uses the tools and work of others without producing anything of their own.

[2] No operation. Just burns a CPU cycle and increments EIP, the pointer that tells the processor which instruction to execute next.

[3] The GNU C compiler.


0 Responses to “Hacking: Lecture One Follow-up”

Feed for this Entry Trackback Address
  1. No Comments

Leave a Reply