What does it all mean?

It was probably mid 2003 after the effects of Sapphire, Nimda and Code Red that Intel and AMD both started working with Microsoft to patch the x86 architecture itself. The inherent flaw is two fold; for one, malicious code should not write past the end of an array like line from fingerd, and second the computer should not continue to happily execute the machine code on the stack.

For those not familiar with the stack, here is a quick illustration of how memory looks to an x86 based machine. All memory is divided up into several segments; the stack, heap, and code (or text). Segments are then further divided into pages. Generally, a program executes and runs from the "code" segment. The heap stores dynamically loaded memory, static variables, global variables - anything that need exist during the duration of the program's executable life. The stack is the wild west of memory; function parameters, general variables and arrays end up here. Memory on the stack is reused; once we have processed a function whatever junk it left over in memory resides there.


In the fingerd example from the previous page, writing more than 512 characters to the array begins to overwrite components of the program. When a program begins to load an array, a special byte after the array (called a return address) tells the computer to go back to the code segment and continue to run the program. Unfortunately if a malicious input overwrites the return address with an address in the stack, the computer will execute the code at the location designated, rather than the code the return address pointed to.

NX attempts to correct the buffer overflow issue by disallowing the computer from executing memory in specific pages of the stack. Thus if a malicious input overwrites the portion of the stack and the return address with a clever piece of machine code, NX signals the kernel to panic and the program is terminated.

Thus, some issues are addressed with buffer overflows. It makes it much harder for a malicious input to load a payload into memory with any astounding effects, since we cannot execute some pages of memory on the stack. What NX doesn't stop are buffer overflows that do not rely on their own payload. A malicious input can still overwrite the return address and direct exectution to some other code segment that can cause nefarious deeds - such as a function that creates a file before the user is correctly identified as having the rights to do so. The program might also utilize shared libraries and external system functions like execve, which would give the input identical privileges to the user executing the program. A clever return address combined with initialization of some parameters on the stack would result in execve replicating a payload without machine code.

This is not to say that NX protection is not a step in the right direction. In fact, NX/XD is a good first step to locking down the x86 architecture, as long as it's adopted correctly. OpenBSD and the Execshield projects have made the largest progress with implementing non-executable writable pages and other features, if only in software. However, NX does not completely eliminate buffer overflow exploits, and thus far it has only caused more problems than it has solved with Windows SP2.

Special thanks to D.J. Bernstein, who provided the technical background for the majority of this primer.

Index
Comments Locked

17 Comments

View All Comments

  • bobbozzo - Saturday, October 16, 2004 - link

    Do the 32-bit versions Windows Server 2003 support this on AMD Opterons?

    Thanks!
  • WarcraftIII - Friday, October 15, 2004 - link

    "Well, maybe not. In fact it seems that NX provides several layers of false security, particularly since it only stops some buffer overflows and whether or not it stops any viruses has yet to be seen yet."
    Why start off by questioning whether NX will even be able to stop any exploits? You only have to look back at what viruses rely on executable stack memory to see how useful this can be, not wait around to see if anyone ever comes up with one.
    Of course it doesn't stop all buffer overflow exploits. It could be as simple as entering machine code into an input that will be placed on the heap. At a later point in the program a stack-based buffer overflow could overwrite a return address or a function pointer variable with the appropriate address. You could conceivably avoid the stack altogether where a buffer on the heap overflows onto a function pointer variable stored on the heap. It doesn't change the fact that this can stop a lot of exploits, and probably the simplest and most successful exploits because positioning of items on the stack is a lot more predictable and you are a lot more likely to guess a close enough to correct return address (you can guess an offset from other addresses obtained off the stack).

    Why does this article try to present buffer overflow exploits as being due to inherent problems with x86? The usual calling conventions on pretty much any architecture involve storing return addresses on the stack which makes exactly the type of exploit the NX bit stops a possibility. Where one is provided, the contents of the return address register need to be saved to memory if you're doing calls more than one level deep.

    "in reality NX behaves more like an emergency patch for an easily exploitable architecture"
    Is x86 really any more exploitable than anything else? The memory model you described is not x86-specific.
    Why do so many other architectures support an NX bit?

    "both started working with Microsoft to patch the x86 architecture itself. The inherent flaw is two fold; for one, malicious code should not write past the end of an array like line from fingerd, and second the computer should not continue to happily execute the machine code on the stack."
    The computer is doing exactly what it has been asked, and it will do exactly the same thing whether you're using an x86 or not. This code SHOULD write past the end of the array if the user enters a lot of characters because that is what the programmer has written. This is due to the design of C, not x86. If this is not supposed to happen (as it obviously isn't in the example) it is solely due to programmer error, it is not the fault of x86. If you want bounds checking use Java, if you want speed write decent C/C++ code whether you're using x86 or not.

    I'm sorry if I sound overly critical and I guess I may be wrong in some of my assertions since I haven't done much assembly programming for a fair while. However, it seems to me that the point of the whole article was to criticise the NX bit as a relatively useless hack (or "emergency patch") useful more for marketing than for security purposes, and I believe this to be incorrect.
  • Foxbat121 - Friday, October 15, 2004 - link

    NX bit is nothing new. It existed in Intel 80286 processor and no body liked it back then. So Intel took it out.

    On the other hand, the NX protection is XP SP2 is only limited to stack memory only. In WinXP 64bit extention for x86-64, Microsoft extends protection to all memory segments that is marked for NX, not only stack memory.
  • KristopherKubicki - Friday, October 15, 2004 - link

    Fixed.

    Kristopher
  • reever - Thursday, October 14, 2004 - link

    Typo: All memory is divided up into several SEGEMENTS;
  • Pythias - Wednesday, October 13, 2004 - link

    No kidding! Our surfing/email habits have as much to do with our security as any piece of software in the world.
  • TrogdorJW - Tuesday, October 12, 2004 - link

    Of course, this is to say nothing of the difficulty of stopping dumb people from launching any number of Trojan horse type applications. "Hey, pictures of [insert celebrity name]! I gotta see this!" We need an NM bit: No Morons. ;)

Log in

Don't have an account? Sign up now