0% found this document useful (0 votes)
31 views

CNIT 127: Exploit Development CH 2: Stack Overflows in Linux

This chapter discusses stack-based buffer overflow vulnerabilities in C/C++ programs. It explains how buffer overflows occur when a program writes past the end of an array due to a lack of bounds checking. The chapter demonstrates how to use the GNU debugger gdb to analyze crashes caused by buffer overflows. It also provides an overview of how functions and the stack work, and how a stack-based buffer overflow can be used to overwrite return addresses and gain control of the instruction pointer to hijack program execution.

Uploaded by

dunstanpinto
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views

CNIT 127: Exploit Development CH 2: Stack Overflows in Linux

This chapter discusses stack-based buffer overflow vulnerabilities in C/C++ programs. It explains how buffer overflows occur when a program writes past the end of an array due to a lack of bounds checking. The chapter demonstrates how to use the GNU debugger gdb to analyze crashes caused by buffer overflows. It also provides an overview of how functions and the stack work, and how a stack-based buffer overflow can be used to overwrite return addresses and gain control of the instruction pointer to hijack program execution.

Uploaded by

dunstanpinto
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 54

CNIT 127: Exploit Development

Ch 2: Stack Overflows in Linux


Stack-based Buffer Overflows
• Most popular and best understood
exploitation method
• Aleph One's "Smashing the Stack for Fun and
Profit" (1996)
– Link Ch 2a
• Buffer
– A limited, contiguously allocated set of memory
– In C, usually an array
C and C++ Lack Bounds-Checking
• It is the programmer's responsibility to ensure
that array indices remain in the valid range

#include <stdio.h>
#include <string.h>

int main() {
int array[5] = {1, 2, 3, 4, 5};
printf("%d\n", array[5]);
}
Using gdb (GNU Debugger)
• Compile with symbols
– gcc -g -o ch2a ch2a.c
• Run program in debugger
– gdb ch2a
• Show code, place breakpoint, run to it
– list
– break 7
– run
• Examine the memory storing "array"
– x/10x &array
Reading Past End of Array
Reading Past End of Array

• array[5] = 0xb7fb63c4
Writing Past End of Array
Compile and Run, Crash
Debug
• Open in debugger
– gdb ch2b
• Run
– run
• Examine the memory storing "array"
– x/50x &array
Buffer Overflow
• Many RAM locations now contain 0xa
• But why, precisely, did that cause a crash?
Debug
• Examine registers
– info registers
• Examine assembly code near eip
– x/10i $eip-10
10 (0xa) is not in any register
Last Command Writes $0xa to RAM
• Evidently we went so far we exited the RAM
allocated to the program
Intel v. AT&T Format
• gdb uses AT&T format by default, which is
popular with Linux users
– mov source, destination
• Windows users more commonly use Intel
format
– MOV DESTINATION, SOURCE
Jasmin

Assembly Language Simulator


The Stack
LIFO (Last-In, First-Out)
• ESP (Extended Stack Pointer) register points to
the top of the stack
• PUSH puts items on the stack
– push 1
– push addr var
Stack
• POP takes items off the stack
– pop eax
– pop ebx
EBP (Extended Base Pointer)
• EBP is typically used for calculated addresses
on the stack
– mov eax, [ebp+10h]
• Copies the data 16 bytes down the stack into
the EAX register
Functions and the Stack
Purpose
• The stack's primary purpose is to make the
use of functions more efficient
• When a function is called, these things occur:
– Calling routine stops processing its instructions
– Saves its current state
– Transfers control to the function
– Function processes its instructions
– Function exits
– State of the calling function is restored
– Calling routine's execution resumes
Example
Using gdb (GNU Debugger)
• Compile with symbols
– gcc -g -o ch2d ch2d.c
• Run program in debugger
– gdb ch2d
• Show code, place breakpoint, run to it
– list 1,12
– break 9
– break 11
– break 4
Using gdb (GNU Debugger)
• Run to breakpoint after line 9
• run
• Examine registers
– info reg
• Run to breakpoint after line 4
• continue
• Examine registers
– info reg
In main() before calling function()
• esp 0xbffff460
• ebp 0xbffff468 (start of stack frame)
• eip 0x8048414 <main+17>
In function()
• esp 0xbffff430
• ebp 0xbffff450 (start of stack frame)
• eip 0x8048401 <function+6>
Examine the Stack
– x/12x $esp
• Highlight is function()'s stack frame
• Outlined area shows these items
– Return address
– Arguments of function(1,2)
• Next to the left is the original value of $ebp
Using gdb (GNU Debugger)
• Run to breakpoint after line 11
• continue
• Examine registers
– info reg
In main() after calling function()
• esp 0xbffff460
• ebp 0xbffff468
• eip 0x8048420 <main+29>
Functions and the Stack
• Primary purpose of the stack
– To make functions more efficient
• When a function is called
– Push function's arguments onto the stack
– Call function, which pushes the return address RET
onto the stack, which is the EIP at the time the
function is called
Functions and the Stack
– Before function starts, a prolog executes, pushing
EBP onto the stack
– It then copies ESP into EBP
– Calculates size of local variables
– Reserves that space on the stack, by subtracting
the size from ESP
– Pushes local variables onto stack
Functions and the Stack
#include <stdio.h>

void function(int a, int b)


{
int array[5];
}

main()
{
function(1,2);
printf("This is where the
return address points\n");
}
• <main+3> puts a's value, 1, onto the stack
• <main+5> puts b's value, 2, onto the stack
• <main+7> calls function, which implicitly
pushes RET (EIP) onto the stack
• Prolog
– Push EBP onto stack
– Move ESP into EBP
– Subtract 0x14 from stack to reserve space for
array
• leave restores the original stack, same as
– mov esp, ebp
– pop ebp
Stack Buffer Overflow Vulnerability
Compile and Run
Disassemble return_input
Set Breakpoints
• At call to gets
• And at ret
Disassemble main

• Next instruction after the call to return_input


is 0x08048453
Run Till First Breakpoint

• Highlighted values are the saved EBP and the


RET address
Continue and Input 40 Characters

• 30 characters are stored correctly


• Next four overwrite stored EBP with
0x44444444 ('DDDD')
• Next four overwrite RET
Examine $eip, Step One Instruction

• x/1i means "Examine one instruction"


• stepi executes one machine language
instruction
Observe Overwritten Registers

• ebp and eip are 0x44444444 = 'DDDD'


Stack Overflow
Controlling eip
• 0x44444444 is invalid and causes the program
to halt
• We can put any valid memory address there
• However, at the point of the crash we have
returned to main() so we should choose an
instruction in main()
Call to return_input
• 0x0804844e
– stored backwards in a string
– "\x4e\x84\x04\x08"
Python Exploit Code
• sys.stdout.write doesn't put a space or
linefeed at end
How to Debug with Arguments

You might also like