25

I read a book about buffer overflow, and it suggest the next to deal with:

Making the stack (and heap) non-executable provides a high degree of protection against many types of buffer overflow attacks for existing programs.

But I don't understand how we can do it - where the execute would take place, if not on the heap or on the stack?

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
Adam Sh
  • 8,137
  • 22
  • 60
  • 75

7 Answers7

31

If I understand your question correctly, none of the other answers address it. The answer is that execution occurs in the code section, which is neither stack nor heap. In a typical paged memory system, the code from a program file (e.g., a .exe in Windows) is loaded into executable but read-only pages. Additional writable (and executable) pages are allocated to the process for the stack and heap. The suggestion here is that the operating system and hardware should cooperate to mark those pages writable but not executable (rgngl's answer explains how to do that in Windows).

Even with non-executable heap and stack, exploits are still possible that use the return-oriented programming mentioned in Alexey Frunze's answer, but there are protection techniques that stymie even those, such as stack-smashing protection and address space layout randomization -- see http://en.wikipedia.org/wiki/Return-to-libc_attack#Protection_from_return-to-libc_attacks

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
  • 1
    Great answer. However, one minor comment -- (Blind) ROP actually defeats ASLR http://ieeexplore.ieee.org/xpl/login.jsp?tp=&arnumber=6956567&url=http%3A%2F%2Fieeexplore.ieee.org%2Fxpls%2Fabs_all.jsp%3Farnumber%3D6956567 – Hack-R Mar 15 '15 at 20:23
11

There's what's called "return-oriented programming" (AKA ROP) type of exploits.

The attacker finds how to make his evil code out of different pieces of the program that's being exploited.

He finds usable byte sequences (instructions) before the return instruction byte(s) that can do useful operations on registers or memory like move a value to a location, add values, compare values, etc etc. Those are micro subroutines that the exploit gets built of.

Then by exploiting a code bug the attacker forces the program to start executing the chain of those micro subroutines that does all the evil work.

So, now good code turns into evil code. Nothing's executed on the stack or in the heap.

It's also noteworthy that on CPUs where instructions span multiple bytes and are of variable length, even the immediate instruction operands (IOW, numerical constants) that are part of instructions can become code, and so the chances of finding usable byte sequences are higher there than on "simpler" CPUs.

It's also often possible to construct malicious code that will change memory protection and the exploit will no longer be constrained by the existing application's code.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
4

Very concrete example: Arrange for the return address to point to system and the next slot on the stack (or the first argument register on pass-by-register archs) to be a pointer to the string "/bin/sh".

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

That kind of protection is provided by the OS and cannot be done in the application layer.

See the wikipedia article, which also tells how to enable it under Windows: http://en.wikipedia.org/wiki/Data_Execution_Prevention

rgngl
  • 5,353
  • 3
  • 30
  • 34
  • 1
    In theory, you can do it yourself, it's essentially just a bunch of calls to mprotect(2). – tbert Jul 14 '12 at 07:47
  • No problem :) Just remember that the most important thing to do is to make sure that memory is not both writable and executable at the same time. – tbert Jul 14 '12 at 07:58
1

Your code runs in the text segment, not in the stack or the heap (both of which are for data storage). So the organization is:

<highest addresses>
stack
...
heap
data section (initialized data & bss - uninitialized data) 
code section (text)
<lowest addresses> 

The code section is executable but immutable. This wikipedia article has more details: https://en.wikipedia.org/wiki/Data_segment

Scott C Wilson
  • 19,102
  • 10
  • 61
  • 83
0

you can jump to any other place which is executable segment and run your evil code...

After all, All the data on any storage, memory is bits and bits can be instructions to the cpu to execute.

0x90
  • 39,472
  • 36
  • 165
  • 245
  • The question appears to be about the case when everything except the program's code is in non-executable memory. How do you load your code into executable memory then? Jumping to it may be easy. – Alexey Frunze Jul 14 '12 at 07:57
0

You can use your overflow to overwrite the return address of a function, which can jump to some known address with your code on it. But then OS writers responded by randomizing the address code is executed on...

argentage
  • 2,758
  • 1
  • 19
  • 28
  • To begin with, how do you load your code into executable locations if everything but the program's code is in non-executable memory? Address space randomization alone doesn't prevent ROP-based exploits. See my answer. – Alexey Frunze Jul 14 '12 at 07:55