You are on page 1of 20

ABSTRACT

BuIIer overIlows have been the most common Iorm oI security vulnerability Ior the last ten
years. Moreover, buIIer overIlow vulnerabilities dominate the area oI remote network
penetration vulnerabilities, where an anonymous Internet user seeks to gain partial or total
control oI a host. II buIIer overIlow vulnerabilities could be eIIectively eliminated, a very
large portion oI the most serious security threats would also be eliminated. In our report we
present a survey on this critical vulnerability, the buIIer overIlow. The term paper aims to
provide a detailed analysis on the vulnerability and discusses the various types oI buIIer
overIlow exploitation that includes two very diIIerent kind oI that includes two very diIIerent
kind oI buIIer overIlow exploitation namely stack- based buIIer overIlow exploitation and
heap based buIIer overIlow exploitation. We then discuss a procedural approach to buIIer
overIlow attack which gives a step by step procedural way to create a buIIer overIlow attack.
We then discuss several combinations oI the two steps involved in buIIer overIlow attack
which is Iollowed by several buIIer overIlow attack methods under the head exploiting buIIer
overIlow vulnerability.. Next a list oI various environments and platIorms aIIected by buIIer
overIlow attack is presented. And lastly we discuss on various deIensive measures that could
be undertaken to oIIend possible buIIer overIlow attacks. The list however, not being
exhaustive discusses the various general countermeasures. Finally we present our conclusion
with the Iuture scope oI the vulnerability, attack and deIenses.



















1. INTRODUCTION

Throughout the history oI cyber security, buIIer overIlow has been one oI the most serious
and persistent vulnerabilities in computer systems. Moreover, buIIer overIlow vulnerabilities
dominate the area oI remote network penetration vulnerabilities, where an anonymous
Internet user seeks to gain partial or total control oI a host. Because these kinds oI attacks
enable anyone to take total control oI a host, they represent one oI the most sober classes oI
security threats.
BuIIer overIlows account Ior approximately halI oI all security vulnerabilities |1|. Richard
Pethia oI CERT identiIied buIIer overIlow attacks as the single most important security
problem at a recent soItware engineering conIerence |2|; Brian Snow oI the NSA predicted
that buIIer overIlow attacks would still be a problem in twenty years |3|.
The Open Web Application Security Project (OWASP) has stated that buIIer overIlows are
one oI the Top-103 most critical web application security Ilaws. And, buIIer overIlows are a
primary vehicle used to propagate the most notorious viruses and worms in operating systems
Irom MicrosoIt Windows to Linux |4|.
In computer security and programming, a buIIer overIlow, or buIIer overrun, is an anomaly
where a program, while writing data to a buIIer, overruns the buIIer's boundary and
overwrites adjacent memory. This is a special case oI violation oI memory saIety. BuIIer
overIlows can be triggered by inputs that are designed to execute code, or alter the way the
program operates. This may result in erratic program behavior, including memory access
errors, incorrect results, a crash, or a breach oI system security. Cleverly designed buIIer
overIlow exploits are able to take advantage oI this situation by overwriting speciIic pieces oI
memory to execute arbitrary system commands and take over computers. They are thus the
basis oI many soItware vulnerabilities and can be maliciously exploited.
1.1 !ROBLEM STATEMENT
Survey the various types oI buIIer overIlow vulnerabilities and attacks, and the various
deIensive measures that mitigate buIIer overIlow vulnerabilities. The intent is to provide a
logical, detailed, and technical explanation oI the problem and the exploit that can be well
understood by all. We will begin by looking at the 'problem and the problem 'mechanism,
and then investigate the 'means and the 'methods. Consider which combinations oI
techniques can eliminate the problem oI buIIer overIlow vulnerabilities, while preserving the
Iunctionality and perIormance oI existing systems




MOTIVATION

The history oI buIIer overIlow exploits is interesting because oI how long it took Ior
techniques to mature. About 16 years passed Irom awareness to Iirst public exploitation, and
then 8 more years Irom that until they were commonly exploited. Programmers were aware
oI this class oI Ilaw but did little to avoid them Ior 24 years. Moreover, BuIIer overIlow
attacks are an important and persistent security problem. BuIIer overIlows account Ior
approximately halI oI all security vulnerabilities |1|.
The motivation behind the chosen topic is , thereIore , its subtle as well as dangerous nature
and the Iact that it has been persistently a potential attack.



























AN OVERVIEW

BUFFER

A buIIer is a contiguous allocated chunk oI memory, such as an array or a
Pointer in C. In C and C, there are no automatic bounds checking on the
BuIIer, which means it is possible to write past a buIIer.

BUFFER OVERFLOW
A buffer overflow occurs when a program or process tries to store more data in a buffer
than it was intended to hold. Since buffers are created to contain finite amount of data,
the extra information overflows into adjacent buffers, corrupting or overwriting the valid
data held in them.
Most buffer overflows occur accidentally or through programming error. n buffer
overflow attacks, the extra data may contain codes designed to trigger specific actions,
for example, damage the user's files, change data, or gain Privileges. Buffer overflow
attacks are said to have arisen because the C programming language supplied the
framework, and poor programming practices supplied the vulnerability.
The method to exploiting a buffer overflow is to overwrite parts of memory which aren't
supposed to be overwritten by arbitrary input and making the process execute this code.


A process image starts with the program's code and data. Code and data consists oI the
program's instructions and the initialized and uninitialized static and global data, respectively.
AIter that is the run-time heap (created using malloc/calloc), and then at the top is the users
stack. This stack is used whenever a Iunction call is made.


STACK
A stack is an abstract data type commonly reIerred to as last in, Iirst out
queue, LIFO. Several operations are deIined on stacks. Two oI the most
important are PUSH and POP. PUSH adds an element at the top oI the stack.
POP removes the last element at the top oI the stack.
The stack is used to dynamically allocate the local variables used in
Iunctions, to pass parameters to the Iunctions, and to return values Irom the
Iunction. The size oI the stack is dynamically adjusted by the kernel at run time.
Its size is dynamically adjusted by the kernel at run time. The stack consists oI
logical stack Irames that are pushed when calling a Iunction and popped when
returning. A stack Irame contains the parameters to a Iunction, its local variables,
and the data necessary to recover the previous stack Irame, including the value
oI the instruction pointer at the time oI the Iunction call.
The stack pointer (SP) points to the top oI the stack. And the Frame
Pointer (FP) points to a Iixed location within a Irame.
When a procedure call is made the previous FP is pushed into the stack
so it can be restored when the procedure completes and the program is restored
to its previous state. Then it copies SP into FP to create the new FP, and
advances SP to reserve space Ior the local variables.
Getting the return address to point to the right location is one part oI the
'art oI buIIer overIlow exploits.

ATTACK SCENARIO

Figure 1 shows a typical stack structure aIter a Iunction is called. The
stack pointer points at the top oI stack, which is at the bottom in the Iigure. The
programming language C uses the area Irom the top oI the stack in the Iollowing
order: local variables, the previous Irame pointer, the return address, and
arguments oI the Iunction. This data is called the Irame oI the Iunction, which
represents the status oI the Iunction. The Irame pointer locates the current Irame
and the previous Irame pointer stores the Irame pointer oI the caller Iunction.


Fig Stack Structure

Figure 2 illustrates the operation oI the memory stack Ior the example program shown in
Figure 3. The memory stack consists oI a set oI stack Irames; a single Irame is allocated Ior
each procedure (e.g., g) that has yet to return control to anancestor procedure. The stack
pointer (SP) points to the top oI the stack Irame oI the procedure that is currently executing,
and the Irame pointer (FP) points to the base oI the stack Irame Ior the currently executing
procedure.
When Iunction I() calls g(), a new stack Irame is pushed onto the stack. The stack on the leIt
oI Figure 1 shows the state oI the memory stack immediately Iollowing the call to g(). The
new Irame includes the input pointers x and y, the procedure return address, the Irame
pointer, and the local variables a and b. Upon completing g(), the program should return to
the return address stored in g`s stack Irame; this address should equal the location oI the
instruction immediately Iollowing the call to g() in the Iunction I(). The SP and the FP should
also be restored to their Iormer values, and the stack Irame belonging to g() should be
eIIectively popped Irom the stack. A security vulnerability exists in the code shown in Figure
2 because strcpy() does not perIorm bounds checking. In the Iunction g(), iI the string to
which x points exceeds the size oI b, strcpy() will overwrite data located adjacent to b in the
memory stack. A malicious party can exploit this situation by strategically constructing a
string that contains malicious code and a corrupted return address. II x points to such a
string, strcpy() will copy malicious code into the stack, and the return address in
g()`s stack Irame will be set to the initial instruction oI the malicious exploit
code. This is illustrated in Figure 1. Consequently, once g() completes, the
program will jump to and execute the exploit code instead oI returning control
to I(). There are many variations oI this Iorm oI attack , but the majority relies
on the ability to modiIy the return address. For example, rather than the attacker
injecting his own exploit code, the return address may be modiIied to point to
legitimate, preexisting code that can be used Ior malicious purposes.


Higher
Addresses Stack stack

frame of frame of

1 1

P

P




$9,.


#eturn
strcpy()
.4rrup9

r49h

Address ,ddress

expI4i9



Saved

Stack

P

rame

2,Ii.i4us A

of g


.4de




B

I4er SP
SP
,ddresses



FIGURE 2. BUFFER OVERFLOW ATTACK














3t f()


(x, y);

<

3t (char * x, char * y)

3t a; char b[64];

strcpy(b, x);

retur3;
<



FIGURE 3. VULNERABLE CODE EXAMPLE

4TY!ES OF BUFFER OVERFLOW EX!LOITATION

The techniques to exploit a buIIer overIlow vulnerability vary per architecture, operating
system and memory region. For example, exploitation on the heap (used Ior dynamically
allocated memory), is very diIIerent Irom exploitation on the call stack.
4Stack-based exploitation

A technically inclined and malicious user may exploit stack-based buIIer overIlows to
manipulate the program in one oI several ways:

O By overwriting a local variable that is near the buIIer in memory on the stack to change the
behavior oI the program which may beneIit the attacker.
O By overwriting the return address in a stack Irame. Once the Iunction returns, execution will
resume at the return address as speciIied by the attacker, usually a user input Iilled buIIer.
O By overwriting a Iunction pointer, or exception handler, which is subsequently executed.

With a method called "trampolining", iI the address oI the user-supplied data is unknown, but
the location is stored in a register, then the return address can be overwritten with the address
oI an opcode which will cause execution to jump to the user supplied data. II the location is
stored in a register R, then a jump to the location containing the opcode Ior a jump R, call R
or similar instruction, will cause execution oI user supplied data. The locations oI suitable
opcodes, or bytes in memory, can be Iound in DLLs or the executable itselI. However the
address oI the opcode typically cannot contain any null characters and the locations oI these
opcodes can vary between applications and versions oI the operating system. The Metasploit
Project is one such database oI suitable opcodes, though only those Iound in the Windows
operating system are listed |7|.
Stack-based buIIer overIlows are not to be conIused with stack overIlows.
Programs written in languages like C are particularly susceptible to this type oI attack as C
provides direct low-level memory access and pointer arithmetic without bounds checking.
Worse, the standard C library provides unsaIe Iunctions (such as gets) that write an
unbounded amount oI user input into a Iixed size buIIer without any bounds checking .
BuIIers stored on the stack are oIten passed to these Iunctions. To exploit such
vulnerabilities, an attacker
merely has to enter an input larger than the size oI the buIIer and encode an attack program
binary in that input. The Internet Worm oI 1988 |SpaIIord88, RE89| exploited this type oI
buIIer overIlow vulnerability in Iingerd.
As an example look at the Iollowing C code:













vold funcLlon(char*sLr)

char buffer16
sLrcpy(buffersLr)

lnL maln()

char large_sLrlng236
lnL l
for(l0l233l++)
large_sLrlngl'A'

funcLlon(large_sLrlng)



When the above program is run it results in a segmentation violation as shown in Iigure 7.


FIGURE 4

The return address is overwritten with AAAA`(0x41414141)
Function exits and goes to execute instructions at 0x41414141.

4 Heap-based exploitation

A buIIer overIlow occurring in the heap data area is reIerred to as a heap overIlow and is
exploitable in a diIIerent manner to that oI stack-based overIlows. Memory on the heap is
dynamically allocated by the application at run-time and typically contains program data.
Exploitation is perIormed by corrupting this data in speciIic ways to cause the application to
overwrite internal structures such as linked list pointers. The canonical heap overIlow
technique overwrites dynamic memory allocation linkage (such as malloc meta data) and uses
the resulting pointer exchange to overwrite a program Iunction pointer.
MicrosoIt's GDI vulnerability in handling JPEGs is an example oI the danger a heap
overIlow can present |7|.
Exploiting unsaIe buIIer usage on the heap requires more sophisticated buIIer overIlow
attacks than that on the stack . This is harder than the stack based buIIer overIlow attack since
most programs do not jump to addresses loaded Irom the heap or to code that is stored in the
heap.


How to Locate the !otentially Vulnerable Code

In locating potentially vulnerable code Irom a buIIer overIlow standpoint, one should look Ior
particular signatures such as:
Arrays
int x|20|;
int y|20||5|;
int x|20||5||3|;

Format Strings
printI() ,IprintI(), sprintI(), snprintI().
x, s, n, d, u, c, I

Over flows
strcpy (), strcat (), sprintI (), vsprintI ()

5 Buffer Overflow Vulnerabilities and Attacks
BuIIer overIlow attack is an attack in computer science that exploits the buIIer overIlow
vulnerability.
BuIIer overIlow is probably the best known Iorm oI soItware security vulnerability. The
overall goal oI a buIIer overIlow attack is to subvert the Iunction oI a privileged program so
that the attacker can take control oI that program, and iI the program is suIIiciently
privileged, thence control the host. To achieve this goal, the attacker must achieve two sub-
goals:
1. Arrange Ior suitable code to be available in the program's address space.
2. Get the program to jump to that code, with suitable parameters loaded into registers &
memory.
We categorize buIIer overIlow attacks in terms oI achieving these two sub-goals:
5WAYS TO ARRANGE FOR SUITABLE CODE TO BE IN !ROGRAM`S
ADDRESS S!ACE

There are two ways to arrange Ior the attack code to be in the victim program`s address
space: either inject it, or use what is already there.
IN1ECT IT
The attacker provides a string as input to the program, which the program stores in a buIIer.
The string contains bytes that are actually native CPU instructions Ior the platIorm being
attacked. Here the attacker is using the victim program`s buIIers to store the attack code.
Some nuances on this method:
The attacker does not have to overIlow any buIIers to do this; suIIicient payload can be
injected into perIectly reasonable buIIers.
The buIIer can be located anywhere:
o on the stack (automatic variables)
o on the heap (malloc`d variables)
o in the static data area (initialized or uninitialized)

IT IS ALREADY THERE
OIten, the .4/0 to do what the attacker wants is already present in the program`s address
space. The attacker need only parameterize the code, and then cause the program to jump to
it. For instance, iI the attack code needs to execute 'exec('/bin/sh), and there exists code in
libc that executes 'exec(arg) where 'arg is a string pointer argument, then the attacker need
only change a pointer to point to '/bin/sh and jump to the appropriate instructions in the libc
library
5 WAYS TO CAUSE THE !ROGRAM TO 1UM! TO THE ATTACKER`S
CODE

All oI these methods seek to alter the program`s control Ilow so that the program will jump to
the attack code. The basic method is to overIlow a buIIer that has weak or non-existent
bounds checking on its input with a goal oI corrupting the state oI an adjacent part oI the
program`s state, e.g. adjacent pointers, etc. By overIlowing the buIIer, the attacker can
overwrite the adjacent program state with a near-arbitrary sequence oI bytes, resulting in an
arbitrary bypass oI C`s type system and the victim program`s logic. The classiIication here
is the kind oI program state that the attacker`s buIIer overIlow seeks to corrupt. In principle,
the corrupted state can be any kind oI state. For instance, the original Morris Worm used a
buIIer overIlow against the Iingerd program to corrupt the name oI a Iile that Iingerd would
execute. In practice, most buIIer overIlows Iound in 'the wild seek to corrupt code pointers:
program state that points at code. The distinguishing Iactors among buIIer overIlow attacks
is the kind oI state corrupted, and where in the memory layout the state is located:


5 ACTIVATION RECORDS

Each time a Iunction is called, it lays down an activation record on the stack that includes,
among other things, the return address that the program should jump to when the Iunction
exits. Attacks that corrupt activation record return addresses overIlow automatic variables,
i.e. buIIers local to the Iunction, as shown in Figure 8 by corrupting the return address in the
activation record, the attacker causes the program to jump to attack code when the victim
Iunction returns and dereIerences the return address. This Iorm oI buIIer overIlow is called a
'stack smashing attack and constitute a majority oI current buIIer overIlow attacks.
5.2.2 FUNCTION !OINTERS

'void (* Ioo)() declares the variable Ioo which is oI type 'pointer to Iunction returning
void. Function pointers can be allocated anywhere (stack, heap, static data area) and so the
attacker need only Iind an overIlowable buIIer adjacent to a Iunction pointer in any oI these
areas and overIlow it to change the Iunction pointer. Some time later, when the program
makes a call through this Iunction pointer, it will instead jump to the attacker's desired
location. An example oI this kind oI attack appeared in an attack against the superprobe
program Ior Linux.







Figure


5 Longjmp BUFFER
C includes a simple checkpoint/rollback system called setjmp/longjmp. The idiom is to say
'setjmp(buIIer) to checkpoint, and say 'longjmp(buIIer) to go back to the checkpoint.
However, iI the attacker can corrupt the state oI the buIIer, then 'longjmp(buIIer) will jump
to the attacker's code instead. Like Iunction pointers, longjmp buIIers can be allocated
anywhere, so the attacker need only Iind an adjacent overIlowable buIIer. An example oI this
Iorm oI attack appeared against Perl 5.003. The attack Iirst corrupted a longjmp buIIer used
to recover when buIIer overIlows are detected, and then induces the recovery mode, causing
the Perl interpreter to jump to the attack code.

ATTACK CODE

RETURN ADDRESS
LOCAL VARIABLES

BUFFER
0000
S18lnC
C8CW1P
S1ACk C8CW1P

5 Combining Code Injection and Control Flow Corruption Techniques

Here we discuss some issues in combining the attack code injection and control Ilow
corruption techniques. The simplest and most common Iorm oI buIIer overIlow attack
combines an injection technique with an activation record corruption in a single string. The
attacker locates an overIlowable automatic variable, Ieeds the program a large string that
simultaneously overIlows the buIIer to change the activation record, and contains the injected
attack code. This is the template Ior an attack outlined by Levy . Because the C idiom oI
allocating a small local buIIer to get user or parameter input is so common, there are a lot oI
instances oI code vulnerable to this Iorm oI attack. The injection and the corruption do not
have to happen in one action. The attacker can inject code into one buIIer without
overIlowing it, and overIlow a diIIerent buIIer to corrupt a code pointer. This is typically
done iI the overIlowable buIIer does have bounds checking on it, but gets it wrong, so the
buIIer is only overIlowable up to a certain number oI bytes. The attacker does not have room
to place code in the vulnerable buIIer, so the code is simply inserted into a diIIerent buIIer oI
suIIicient size. II the attacker is trying to use already-resident code instead oI injecting it, they
typically need to parameterize parameterize the code. For instance, there are code Iragments
in libc (linked to virtually every C program) that do 'exec(something) where 'something is
a parameter. The attacker then uses buIIer overIlows to corrupt the argument, and another
buIIer overIlow to corrupt a code pointer to point into libc at the appropriate code Iragment.


6 BUFFER OVERFLOW DEFENSES

As we have seen, a buIIer overIlow attack requires two things. First, a buIIer overIlow must
occur in the program. Second, the attacker must be able to use the buIIer overIlow to
overwrite a security sensitive piece oI data (a security Ilag, Iunction pointer, return address,
etc).
II we want to prevent buIIer overIlows completely we must stop one oI these two things, i. e.
either:
1. Prevent all buIIer overIlows or
2. Prevent all sensitive inIormation Irom being overwritten
Both these solutions are costly in terms oI eIIiciency and many programs thereIore settle Ior a
partial goal, such as:
O Prevent use oI dangerous Iunctions: gets, strcpy, etc.
O Prevent return addresses Irom being overwritten
O Prevent data supplied by the attacker Irom being executed (stops the attacker Irom jumping
into his own buIIer)
There are several possible levels where a deIense mechanism can be inserted. At the language
level we can make changes to the C language itselI to reduce the risk oI buIIer overIlows. At
the source code level we can use static or dynamic source code analyzers to check our code
Ior buIIer overIlow problems. At the compiler level we can change the compiler so that it
does bounds checking or protects certain addresses Irom overwriting. At the operating system
level we can change the rules Ior which memory pages that should be allowed to hold
executable content.
In the Iollowing sections, we will look at each oI these options in turn.
6 Type-Safe Languages

The simplest solution at the language level is to switch to a language that provides automatic
bounds checking oI buIIers, such as Java, Perl or Python. However, in most projects this is
not an option.
A better solution is to use a library module that implements "saIe", bounds-checked buIIers,
such as the standard C string module or libmib . There are two problems with this
solution. First, it requires a complete rewrite oI all the source code Ior the project. This alone
makes the solution improper Ior anything but recently started projects. Second, most
programs have to interIace with prewritten library code. Since this code will use the ordinary
"unsaIe" buIIers, the program will not be able to completely avoid them. Instead it will
constantly have to convert between "saIe" and "unsaIe" buIIers. Whenever a buIIer is in the
"unsaIe" mode, buIIer overIlow problems can occur. There is also a risk that programmer's
will Iorget to convert buIIers back to the "saIe" mode.
An alternative to making every buIIer access saIe is to target only those speciIic Iunctions in
C which are known to be dangerous, e. g. strcp, strcat, gets and sprint1. This takes
care oI buIIer overIlows caused by these Iunctions, but doesn't handle buIIer overIlows
caused by other code, such as user written Iunctions.
The simplest solution to securing the dangerous Iunction is to disallow them. They all have
"saIe" counterparts that can be substituted, such as strncp and snprint1, which in addition
to the buIIers also take a size parameter. (OI course, these Iunctions are only "saIe" iI the size
parameter is speciIied correctly.) Replacing the Iunctions with saIe calls is probably the best
solution provided that the source code to the program is available. To make sure that the
unsaIe versions are not used by mistake, their prototypes can be removed Irom the header
Iiles.
6.2 Source Code Tools
A source code tool analyzes the source code oI a program and tries to determine whether it
contains any dangerous constructions that could lead to buIIer overIlows.
We cannot expect a source code tool to be able to detect all possible instances oI buIIer
overIlow while at the same time yielding no Ialse positives, since that is a task oI the same
diIIiculty as solving the halting problem. Constructing good source code tools will thereIore
always be a heuristic task.
The source code tools available today make only a limited, local analysis oI the code and are
thereIore heavily restricted in the types oI buIIer overIlow problems that they can detect.
its4 is a source code tool that checks Ior the use oI dangerous Iunction. It is a bit smarter than
a plain rep search in that it can rule out some cases where the use oI a dangerous Iunction
usually does not pose a problem.
L0pht Heavy Industries have a web page advertising slint, a source code analyzer capable oI
detecting some buIIer overIlow problems. However, it seems to be vaporware. L0pht does
not give any inIormation about what the program does or what classes oI errors it is able to
detect and people who have tried to order the product have been told that it is not ready yet .
An analyzer that could perIorm more extensive, cross-Iunction analysis would be a valuable
tool in a security audit. Constructing such a tool would however be a major undertaking. The
tool would have to try to keep track oI the size oI all buIIers and the possible ranges oI
variables to be able to detect when a buIIer overIlow might occur.
Dynamic analysis tools such as puriIy are an alternative to static analysis tools. A dynamic
analysis tool analyzes the memory use oI a program as it is run. Dynamic analysis tools can
detect buIIer overIlow problems iI they occur in a test run oI a program. However, errors that
occur in test runs can usually be detected even without an analysis tools, since they typically
cause the program to crash. The main advantage oI dynamic analyzers is that they allow Ior
the error to be swiItly located once it has been detected.
6.3 Compiler Tools
A compiler tool changes the way a program is compiled, so that protection against buIIer
overIlow is automatically compiled in with the program. No changes to the program's source
code are thus necessary.
The various compiler based approaches are discussed below:
6 Array Bounds Checking
While injecting code is optional Ior a buIIer overIlow attack, the corruption oI control Ilow is
essential.Thus unlike non-executable buIIers, array bounds checking completely stops buIIer
overIlow vulnerabilities and attacks. II arrays cannot be overIlowed at all, then array
overIlows cannot be used to corrupt adjacent program state.
To implement array bounds checking, then all readsand writes to arrays need to be checked to
ensure that they are within range. The direct approach is to checkall array reIerences, but it is
oIten possible to employ optimization techniques to eliminate many oI these checks. There
are several approaches to implementing array bounds checking, as exempliIied by the
Iollowing projects.

6 1ones & Kelly Array Bounds Checking for
C Richard Jones and Paul Kelly developed a gcc patch that does Iull array bounds checking
Ior C programs. Compiled programs are compatible with other gcc modules, because they
have not changed the representation oI pointers. Rather, they derive a 'base
pointer Irom each pointer expression, and check the attributes oI that pointer to determine
whether the expression is within bounds.
The perIormance costs are substantial: a pointer intensive program (ijk matrix multiply)
experienced 30 slowdown, Since slowdown is proportionate to pointer usage, which is quite
common in privileged programs, this perIormance penalty is particularly unIortunate.
The compiler did not appear to be mature; complex programs such as elm Iailed to execute
when compiled with this compiler. However, an updated version oI the compiler is being
maintained |39|, and it can compile and run at least portions oI the SSH soItware encryption
package. Throughput experiments with the updated compiler and soItware encryption using
SSH showed a 12 slowdown |32| .

6 !urify Memory Access Checking PuriIy is a memory usage debugging tool Ior C
programs. PuriIy uses 'object code insertion to instrument all memory accesses. AIter
linking with the PuriIy linker and libraries, one gets a standard native executable program
that checks all oI its array reIerences to ensure that they are legitimate. While PuriIy-
protected programs run normally without any special environment,
PuriIy is not actually intended as a production security tool: PuriIy protection imposes a 3 to
5 times slowdown.
PuriIy also was laborious to construct, as evidenced by a purchase price oI approximately
$5000 per copy.

64 Operating System Approach
Some people have tried to solve the buIIer overIlow problem at the level oI the operating
system. The OS can impose some restrictions which make buIIer overIlow attacks harder.
64 Non-Executable Buffers

The general concept is to make the /ata segment oI the victim program`s address space non-
executable, making it impossible Ior attackers to execute the code they inject into the victim
program`s input buIIers. This is actually the way that many older computer systems were
designed, but more recent UNIX and MS Windows systems have come to depend on the
ability to emit dynamic code into program data segments to support various perIormance
optimizations. Thus one cannot make all program data segments non-executable without
sacriIicing substantial program compatibility. However, one can make the stack segment non-
executable and preserve most program compatibility. Kernel patches are available Ior both
Linux and Solaris |18, 19| that make the stack segment oI the program's address space non-
executable. Since virtually no legitimate programs have code in the stack segment, this
causes Iew compatibility problems. There are two exceptional cases in Linux where
executable code must be placed on the stack:
Signal Delivery Linux delivers UNIX signals to processes by emitting code to deliver the
signal onto the process`s stack and then inducing an interrupt that jumps to the delivery code
on the stack. The non-executable stack patch addresses this by making the stack executable
during signal delivery.
GCC Trampolines There are indications that gcc places executable code on the stack Ior
'trampolines. However, in practice disabling trampolines has never been Iound to be a
problem; that portion oI gcc appears to have Iallen into disuse. The protection oIIered by non-
executable stack segments is highly eIIective against attacks that depend on injecting attack
code into automatic variables but provides no protection against other Iorms oI attack (see
Section 2.1). Attacks exist that bypass this Iorm oI deIense by pointing a code pointer at
code already resident in the program. Other attacks could be constructed that inject attack
code into buIIers allocated in the heap or static data segments.

7 Modern Defenses

7 NX and Exec Shield
Modern architectures provide a "No eXecute" bit, which allows you to mark certain regions
oI memory as non-executable. II the stack is marked in this way, it is impossible to run
shellcode that has been injected into a buIIer on the stack. That said, you may be able to get
around this by overIlowing a heap buIIer (but heaps are almost always non-executable now
too) or by using a return-to-libc-style attack.
On older architectures that do not provide the NX bit, there is something called "exec shield,"
Iound on many Red Hat systems. It emulates the NX bit on systems that do not have
hardware support Ior it. Other systems accomplish the same thing, just with a diIIerent name.
Even newer versions oI windoze have support Ior soItware emulation oI the NX bit, called
"Data Execution Prevention" (DEP).
II you recall Irom earlier, we actually turned this oII Ior our programs. This can be
accomplished by setting a Ilag in the actual binary (we can also shut it oII system-wide, but
there's really no reason to). You can use "execstack" to set the Ilag on existing binaries, or, iI
you're compiling a new binary you can pass the "-z execstack" Ilag on to gcc.
7 gcc StackGuard
gcc by deIault also adds extra code to programs to protect against buIIer overIlows in general.
This extra code adds "special" values called canaries beIore and aIter the return address and
checks to make sure they haven't been overwritten beIore proceeding to execute a return. We
disable it by including the "-Ino-stack-protection" when compiling.























CONCLUSION
We have presented a detailed categorization and analysis oI buIIer overIlow vulnerabilities,
attacks, and deIenses. BuIIer overIlows are worthy oI this degree oI analysis because they
constitute a majority oI security vulnerability issues, and a substantial majority oI remote
penetration security vulnerability issues. From our survey we can conclude that no tool can
completely solve the buIIer overIlow problem, but tools can increase the probability that a
buIIer overIlow is detected and reduce the attacker's chance oI successIully exploiting a
vulnerability.

9 References
|1| John P. McGregor, David K. Karig, Zhijie Shi, and Ruby B. Lee 'A !rocessor
Architecture Defense against Buffer Overflow Attacks
( Crispin Cowan, Perry Wagle, Calton Pu, Steve Beattie, and Jonathan Walpole ' Buffer
Overflows Attacks and Defenses for the Vulnerability of the Decade`

( Karthikeyan Karunanidhi "Buffer overflows & avoidance CS 644: operating
systems ii,research paper.

[4] David Larochelle , David Evans
Statically Detecting Likely Buffer Overflow Julnerabilities
University oI Virginia, Department oI Computer Science

|5| Sandeep Grover
Buffer Overflow Attacks an/ Their Countermeasures
LINUX JOURNAL Mar 10, 2003
|6| Wikipedia
http://www.enwlklpedlaorg/wlkl/8uffer_overflow

|7|. OWASP
https://www.owasp.org/index.php/BuIIerOverIlow

8 SPAPLLn !ast, !resent, Future of Win/ows Exploitation
Abysssec Security Research

You might also like