Memory Architecture

 < Day Day Up > 

The two common types of buffers used in computing today are stacks and heaps. You can use both for buffer overflows, although stack overflows are more common. The sections that follow cover stacks and heaps in greater detail and introduce the technique of using no operation instructions to help you in exploiting buffer overflows.

Stacks

Stacks are contiguous areas of memory that are dynamically allocated at runtime to store variables. Stacks grow and shrink as you add and remove data from the stack in a last-in, first-out (LIFO) fashion. When you add data to the stack, you push, or place it onto the stack. When you remove data from the stack, you pop, or remove it from the stack. Stack memory addresses go down as you add data. For example, if the memory address ends in 0x8 before data is added to the stack, the memory address may be 0x4. Therefore, when an item is pushed to the stack, the processor decrements the register, moving it to a lower memory address. Figure 14-1 illustrates a stack buffer.

Figure 14-1. Stack Buffer


80x86 processors control the stack by using extended stack pointer (ESP) registers that point to the top of the stack (which is a lower memory address than the base of the stack). Pointing to the bottom of the stack, at a higher memory address, is the base pointer. Your processor decrements the ESP register by the size of the data you are pushing in 4-byte increments. For example, if the memory address is 0x14216 before you place data onto a stack, pushing eight bytes onto the stack decrements the register to 0x14208 (8 bytes).

Registers are where programmers store their variables. They are manipulated by assembly language. ESP registers are one type of register. Registers fall into four different categories:

  • General purpose

  • Special-purpose application-accessible

  • Segment

  • Special-purpose kernel mode

General-purpose registers are what you need to be concerned with regarding buffer overflows because you can use them to overflow a buffer and inject code into a vulnerable program. General-purpose registers commonly store variables and are used for mathematical instructions. Registers are 32 bit, 16 bit, or 8 bit. The eight 32-bit registers are EAX, EBX, ECX, EDX, ESI, EDI, EBP, and ESP. (The "E" indicates that it is an extended pointer used in 32-bit systems.) The general-purpose registers EAX, EBX, ECX, and EDX store variables. Although the ESI and EDI registers can also store variables, some instructions use them as source and destination pointers. EBP is the extended base pointer, and ESP is the extended stack pointer. The eight 16-bit registers include AX, BX, CX, DX, SI, DI, BP, and SP. Eight 8-bit registers are available, too. These are AL, AH, BL, BH, CL, CH, DL, and DH. Table 14-1 lists the different general-purpose registers.

Table 14-1. General-Purpose Registers

Type of General-Purpose Register

Name

Description

32-bit

EAX

Accumulator Register.

Stores variables.

EBX

Base Register.

Stores variables.

ECX

Counter Register.

Stores variables.

EDX

Data Register.

Stores variables.

ESI

Source Register.

Stores variables. Used by some instructions as a source pointer.

EDI

Destination Register.

Stores variables. Used by some instructions as a destination pointer.

EBP

Extended Base Pointer.

Points to the base of the stack.

ESP

Extended Stack Pointer.

Holds the top stack address.

16-bit

AX

 

BX

 

CX

 

DX

 

DI

 

SI

 

BP

 

SP

 

8-bit

AL

 

AH

 

BL

 

BH

 

CL

 

CH

 

DL

 

DH

 


There is one special-purpose application register that is noteworthy for discussion here. The extended instruction pointer (EIP) is used to contain the return address of the next machine instruction that is to be executed. A buffer overflow attack is concerned not only with flooding the stack or heap, but also with injecting code. By changing the value of the EIP register, you can control what code is executed and even insert your own code to execute.

When data is popped from the stack, it is not deleted from the stack. Rather, pop instructions move the pointer down. For example, look at Figure 14-2. Suppose you had data stored in the EAX register at memory address $00FF_FF04. When the pop (EAX) instruction is called, the data is not removed from memory; instead, the ESP points to a higher memory address ($00FF_FF08) before the EAX.

Figure 14-2. ESP Pointer


Heaps

Some applications need a larger buffer than what stack buffers provide. This is where a heap buffer comes in. Heaps are used when you need a larger buffer or when you do not know the size of the objects contained in the buffer.

Heap overflows work almost identically to those of stack-based overflows. You are attempting to overwrite the buffer and execute your own shell code.

Instead of push and pop operations, however, heaps allocate and unallocate memory. The C programming language does this through the malloc() and free() functions, whereas the C++ programming language does this through the new() and delete() functions.

NOPs

It is often difficult for programmers to determine the exact memory address of the return pointer. To help in discovering this address, some programmers put No Operation (NOPs) commands into their code. NOPs instruct the program to move to the next line of instruction. The most common representation for a NOP code is 0x90.

When you are attempting to exploit a buffer overflow vulnerability, it is likewise difficult to ascertain the exact location of the return pointer. By stringing together a number of NOP codes, you can extend the size of the exploit with code that can be executed but not accomplish anything.

     < Day Day Up > 


    Penetration Testing and Network Defense
    Penetration Testing and Network Defense
    ISBN: 1587052083
    EAN: 2147483647
    Year: 2005
    Pages: 209

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net