0% found this document useful (0 votes)
6 views73 pages

Memory Corruption Buffer-overflow

The document provides an overview of memory corruption, focusing on program memory layout, stack and function invocation, and buffer-overflow attacks. It explains concepts such as little-endian and big-endian memory representation, stack frames, and how function calls manage memory. Additionally, it highlights the risks associated with buffer overflows, particularly in languages like C and C++ that do not automatically detect such errors.

Uploaded by

skewfield1377
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views73 pages

Memory Corruption Buffer-overflow

The document provides an overview of memory corruption, focusing on program memory layout, stack and function invocation, and buffer-overflow attacks. It explains concepts such as little-endian and big-endian memory representation, stack frames, and how function calls manage memory. Additionally, it highlights the risks associated with buffer overflows, particularly in languages like C and C++ that do not automatically detect such errors.

Uploaded by

skewfield1377
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 73

Canadian

Institute for
Cybersecurity

Memory Corruption
Winter 2023

Feb 02 - 2023

Instructor: Saqib Hakak


Canadian
Contents Institute for
Cybersecurity

- Understanding Program Memory Layout


- Stack and Function Invocation
- Buffer-Overflow Attack
- Stack overflow
- Off-by one
Canadian
Institute for
References Cybersecurity

• Mark Dowd, John McDonald, Justin Schuh. The Art of Software Security
Assessment: Identifying and Preventing Software Vulnerabilities. Addison-
Wesley Professional, (2006).

• Wenliang Du. Computer and Internet Security (2019)

• http://etutorials.org/Networking/network+security+assessment/Chapter+13.
+Application-Level+Risks/13.4+Classic+Buffer-Overflow+Vulnerabilities/
Canadian
Institute for
Cybersecurity
Canadian
Institute for
Memory Cybersecurity

Large array of bytes


8 bits
addresses
Canadian
Memory Corruption Institute for
Cybersecurity

int x = 2323231
Canadian
Institute for
Cybersecurity
Canadian
Memory Corruption Institute for
Cybersecurity

int x = 2323231

int x = 0X23731F
Each Hex digit -> 4 bits
Canadian
Memory Corruption Institute for
Cybersecurity

Two different ways in which a sequence of bytes are Smallest addr. highest
stored in computer memory
44 33 22 11
1000 1001……

- Little Endian 11 22 33 44

- the number 0x11223344 will be represented in memory as


- stores the least-significant byte at the smallest address

- Big Endian
- stores the most significant byte of a word at the smallest memory address
- the same number 0x11223344 is represented in memory as

least significant bits: Having the useful property of changing rapidly if the number
changes slightly
Canadian
Institute for
Cybersecurity

Q. Why we need to know about these schemes? Is it really important


Canadian
Institute for
Cybersecurity

https://www.ibm.com/docs/ja/zvm/7.2?topic=domains-network-byte-order-host-byte-order

https://www.ibm.com/docs/en/zos/2.3.0?topic=api-tcpip-network-byte-ordering-convention
Canadian
Institute for
Cybersecurity
Canadian
Institute for
Memory Corruption Cybersecurity

- Memory corruption
- the contents of a memory location are modified
- due to the programmatic behavior that exceeds the intention of the original
program/language constructs

- Cause
- most likely cause is programming error

- Popular approaches
-Stack overflow
Canadian
Institute for
Memory Layout for a typical C program Cybersecurity

Storing local variables defined inside functions, storing data


related to function calls, such as return address, arguments etc.

to provide space for dynamic memory allocation. Managed by


malloc, calloc, realloc, free etc
static int b Stores uninitialized static/global variables.

static int a = 3 Stores initialized static/global variables


Stores the executable code of the program (usually read-only)

static int a = 3
static int b
Canadian
Institute for
Cybersecurity
Canadian
Institute for
Memory Layout Cybersecurity
Canadian
Institute for
Memory Layout Cybersecurity

BSS segment

x = 100
Data segment
Canadian
Institute for
Memory Layout Cybersecurity

main () Stack Frame


( a block of
memory)

BSS segment

x = 100
Data segment
Canadian
Institute for

Memory Layout
Cybersecurity

b = 2.5
a=2
Stack Frame

BSS segment

x = 100
Data segment
Canadian
Institute for
Memory Layout Cybersecurity

bb==2.5
2.5
aa==22
Stack Frame

y BSS segment

x = 100
Data segment
Canadian
Institute for
Memory Layout Cybersecurity

bb==2.5
2.5
aa==22
ptr
ptr Stack Frame

y BSS segment

x = 100
Data segment
Canadian
Institute for
Memory Layout Cybersecurity

ba==2.5
2
ab==22.5
ptr
ptr Stack Frame

Heap

y BSS segment

x = 100
Data segment
Canadian
Institute for
Cybersecurity
Memory Layout

int *ptr = (int *) malloc (2*sizeof(int));


Known at run-time

4 bytes

(typecasting) ptr =
Malloc will
just return 8 bytes of memory
Known at
address ?
compile time
Returns
Hey, it should be address
ptr
int !
Canadian
Institute for
Memory Layout Cybersecurity

ba==2.5
2
ab==22.5
ptr Stack Frame

5
Heap
6

y BSS segment

x = 100
Data segment
Canadian
Institute for
Memory Layout Cybersecurity

ba==2.5
2
ab==22.5
ptr Stack Frame

Heap

y BSS segment

x = 100
Data segment
Canadian
Institute for
Stack Cybersecurity

Storing data in function invocations


stack

X86
source: https://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86
Canadian
Institute for
Cybersecurity
Stack and Function Invocation

• Every time a function is called, the program creates a new stack frame, which is simply a
reserved block of contiguous memory that a function uses for storing local variables and
internal state information.
• This block of memory is reserved for exclusive use by the function until it returns, at which
time it's removed from the stack.
High address void func (int a, int b)

arguments
{
return address int x, y ;
Previous frame pointer
stack frame x = a +b ;
Current frame Local variables y = a – b;
pointer func (int 5, int 8) }
Low address
Canadian
Institute for
Stack and Function Invocation Cybersecurity

The stack pointer (SP) points to the last


Stack frame – main () element on the stack

main()
ESP

foo()

bar()
Canadian
Institute for
Stack and Function Invocation Cybersecurity

The stack pointer (SP) points to the last


Stack frame – main () element on the stack

Stack frame – foo ()


main()

ESP
foo()

bar()
Canadian
Institute for
Stack and Function Invocation Cybersecurity

The stack pointer (SP) points to the last


Stack frame – main () element on the stack

Stack frame – foo ()


main()

Stack frame – bar ()


foo()

ESP Unused memory

bar()
Canadian
Institute for
2. Function Call Stack Cybersecurity

- Once we return from


main() bar(), we will not be able
to know where function
foo()’s stack frame is.
- To solve that, before
entering the callee
foo() function, the caller’s
frame point value is
stored in the “previous
frame pointer” field on
the stack
bar()
Canadian
Institute for
Function Call Stack Cybersecurity

void func (int a, int b) Stack pointer


value of b
{ value of a
int x, y ; Return address
x = a +b ;
y = a – b; Value of X
Value of Y
}
Canadian
Institute for
Function Call Stack Cybersecurity

void func (int a, int b)


value of b
{ value of a
int x, y ; Return address
x = a +b ;
y = a – b; Value of X
Value of Y
}
Stack pointer
(esp)
Canadian
Institute for
Function Call Stack Cybersecurity

void func (int a, int b)


value of b
{ value of a
int x, y ; Return address
x = a +b ; Frame Pointer frame pointer (ebp/rbp)

y = a – b; Value of X Ebp + offset


Value of Y
}

Stack pointer
(esp)
Canadian
Institute for
Function Call Stack Cybersecurity

• The processor usually has a special register that points to the top of the stack, which is modified by
using push() and pop() machine instructions.

• On Intel x86 CPUs, this register is called Extended Stack Pointer (ESP).
Canadian
Institute for
Function Call Stack Cybersecurity

void f(int a, int b)


{
int x;
}
void main()
{
f(1,2);
printf("hello world");
}

- Before jumping to the entrance of the function, the computer pushes the address of the
next instruction
Canadian
Institute for
Cybersecurity
Function Call Stack

- inside func() : need to access


void f(int a, int b) the args and local variables
{ - Compilers cannot determine
int x; addresses during compilation
} time
void main() - Cannot predict where stack
{ frame will be
f(1,2); - A special register is introduced
printf("hello world"); – frame pointer
} - It points to a fixed location on
the stack frame
ESP - So, address of each argument
can be calculated using this
register and an offset.
Frame pointer - starting point to locate the local variables, using offsets.
On x86 architectures, it is stored in the EBP (Extended Base Pointer) register
Canadian
Institute for
Function Call Stack Cybersecurity

• Local variables need to be accessed directly as the function requires them.

• Many programs make use of another register, called the "frame pointer" or "base pointer." On Intel
x86 CPUs, this register is called ِExtended base pointer EBP. This register points to the beginning of
the function's stack frame.

• Each variable in the given frame can be accessed by referencing a memory location that is a fixed
offset from the base pointer.
Canadian
Institute for

Stack and Function Call


Cybersecurity

• Whenever a function is called, some space is allocated for it on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{ Esp
int a;
a=b+c;
return a;
}

Main ()
{
func (5,8)
printf(….)
}
Canadian
Institute for
Cybersecurity
Stack and Function Call

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2)


{
int a; arg2 = 8
a=b+c; arg1 = 5
Esp
return a; Return add
}
Main ()
{
func (5,8)
printf(…..)
}
Canadian
Institute for
Stack and Function Call Cybersecurity

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{
int a; arg1=8
a=b+c; arg2= 5
return a; Return address
} Esp
Main ()
{
func (5,8)
printf(….)
}
Canadian
Institute for
Cybersecurity
Stack and Function Call

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{
int a; arg1=8
a=b+c; arg2=5
return a; Return add
}
Main () Frame pointer
Esp
{ Ebp
func (5,8)
printf(…)
}
Canadian
Institute for
Cybersecurity
2. Stack and Function Call

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{
int a; arg1=8
a=b+c; arg2=5
return a; Return add
}
Main () Frame pointer
{ a Ebp
Esp
func (5,8)
printf(…)
}
Canadian
Institute for
Cybersecurity
2. Stack and Function Call

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{
int a; arg1=8
a=b+c; arg2=5
return a; Return add
}
Main () Frame pointer
{ a Ebp
func (5,8)
Esp …….
printf(…)
}
Canadian
Institute for
Cybersecurity
Stack and Function Call

• Whenever a function is called, some space is allocated for it


on a stack for the execution

Int func (int arg1, int arg2) 4 bytes


{
int a; arg1=8
a=b+c; arg2=5
return a; Return add
}
Main () Frame pointer
{ a Ebp
func (5,8)
Esp …….
printf(…)
}
Canadian
Institute for
Cybersecurity

1. What is the difference between EBP and ESP registers ?

2. What is the purpose of EBP register ?

3. How functions are able to access their local


variables/arguments ?
Canadian
Institute for
Recap
Cybersecurity

- Understanding Program Memory Layout


- Stack and Function Invocation
Canadian
Institute for
Cybersecurity
Canadian
Institute for
Recap
Cybersecurity

- Understanding Program Memory Layout


- Stack and Function Invocation
- Buffer-Overflow Attack
- Stack overflow
- Off-by one
Canadian
Institute for
Cybersecurity
Buffer Overflows (Stack)

• A buffer overflow is a software bug in which data copied to a location


in memory exceeds the size of the reserved destination area.

• When an overflow is triggered, the excess data corrupts program


information adjacent to the target buffer, often with disastrous
consequences.
Canadian
Institute for
Cybersecurity
Buffer Overflows (Stack)

• Memory copying is quite common in programs, where data


from source need to be copied to another place.

• Before copying, a program needs to allocate memory.

• Sometimes, programmers may make mistakes and fail to


allocate sufficient amount of memory for the destination.

• So, more data will be copied to the destination buffer than


the amount of allocated space.
Canadian
Institute for
Buffer Overflows (Stack)
Cybersecurity

- Few languages such as Java can


automatically detect it.

- C and C++ are not able to detect


it.
Canadian
Institute for
Cybersecurity
Canadian
Institute for
3. Buffer Overflows (Stack) Cybersecurity

- Huh – It can only crash my program !

- Why ? Due to corruption of data beyond


the buffer.
Canadian
Institute for
3. Buffer Overflows (Stack) Cybersecurity

- You are wrong !

- It may enable attackers to gain complete


control of a program !
Copy Data to Buffer

#include <string.h> - strcopy() is used to copy strings


#include <stdio.h>
- The function strcopy() stops copying only
void main() when it encounters the terminating
{ character ‘\0’.
char src[40] = “Hello world \0 Extra string”;
char dest[40];

//copy to dest (destination) from the src


(source)
strcopy (dest,src);

}
Canadian
Institute for
#include <string.h> Cybersecurity

void foo(char *str)


{
char buffer[12];
strcpy (buffer,str);
}
int main()
{
Char *str = “This is definitely long day and I want to
sleep”;
Foo (str);

Return 1;
}
Canadian
Institute for
Cybersecurity
3. Buffer Overflows (Stack)

#include <string.h>
- Local array buffer[] in foo() has 12
void foo(char *str)
{
bytes of memory
char buffer[12]; - foo() function uses strcpy() to copy
// the following statement will result in a the string from str to buffer[].
buffer overflow
strcpy (buffer,str);
- Strcpy() function does not stop until
} it sees a zero (‘\0’) in the source
int main() string.
{
- Since the source string is longer than
Char *str = “This is definitely longer than 12”;
Foo (str); 12 bytes, strcpy() will overwrite
some portion of the stack above the
Return 1;
buffer.
}
- This is called buffer overflow.
Canadian
Institute for
3. Buffer Overflows (Stack) Cybersecurity

Q. From this stack figure, what worst


scenario is possible for a program ?
Canadian
Institute for
Consequences of Buffer Overflow Cybersecurity

Overwriting return address

Ø Affects where the program should jump to when the function returns

Ø In case, return address field is modified, when the function returns, it


will return to a new place (changing the logic of the program)
Canadian
Exploiting a Buffer Overflow Vulnerability Institute for
Cybersecurity

- In the previous example, the program does not


take any input from outside (so attackers
cannot take advantage of it).

- In real applications, programs usually get input


from users.

- Program reads 300 bytes of data from a file


(badfile), then copies the data to a buffer of
size 100 – BUFFER OVERFLOW PROBLEM

- This time, the contents come from a user-


provided file ( i.e. users can control what is
copied to the buffer).

- Question ? What to store in “badfile”,


so that after overflowing, we can get
the program to run our code.
Exploiting a Buffer Overflow Vulnerability Canadian
Institute for
Cybersecurity

- We need to get malicious code into the memory


of the running program

- We can simply place our code in “badfile”,so


when the program reads from the file, the code is
loaded into the str[] array.

- When the program copies str to the target buffer,


the code will then be stored on the stack.

- Then, we need to force the program to jump to


our code (which is already in the memory)

- To do that, using the buffer overflow problem in


the code, we can overwrite the return address field

- If we know the address of our malicious code, we


can simply use this address to overwrite the return
address field.
Canadian
Institute for
How to Run Malicious Code Cybersecurity
Canadian
Institute for
Cybersecurity
Improve Chances of Guessing

• To increase the chances of jumping to


the correct address, of the malicious
code, we can fill the badfile with NOP
instructions and place the malicious
code at the end of the buffer.

Note : NOP- Instruction that does nothing.


Canadian
Institute for
Cybersecurity
The Structure of badfile
Canadian
Institute for
Badfile Construction Cybersecurity

Shellcode = [

/sh/bin - Initialize the entire buffer with NOP


] instructions.
- place the malicious code address in
return address.
- Place the malicious at the end of the
- buffer.
Canadian
Creation of The Malicious Input (badfile) Institute for
Cybersecurity

Task A : Find the offset distance between the base of the buffer and return
address.
Task B : Find the address to place the shellcode
Canadian
Institute for
Cybersecurity
Canadian
Institute for
Writing ShellCode Cybersecurity

Shell Program
- Typically, attackers want to inject that command which will allow them
to run more commands.
- If we can inject code to execute a shell program (e.g. /bin/sh), we can
get a shell prompt.

This code will execute a shell program using execve() system call but how to
put this code on the stack.
Canadian
Institute for
Writing ShellCode Cybersecurity

Shell Program

ü compile the above code into binary, and then save it to the input
badfile ?

ü Set the targeted return address field to the address of the main()
function
Canadian
Institute for
Writing ShellCode Cybersecurity

The above C code gives the shell prompt to execute more commands. We can compile the above
C code into binary and store it into the badfile with modified return address field to the address of
main().

But there are issues with this solution :

1) Loader Issue : OS loader is responsible for setting up the memory, copying the program to the
memory and invoking dynamic linker to link libraries etc. to set up the running environment of the
program. After the initialization steps are completed, main() is called. If any of the steps are
missing, program won’t be loaded to the memory. In buffer flow program, code is not loaded by
OS but we are copying the code via memory copy. Therefore, all the initialization steps are
missing and hence, our shell code won’t be executed.

2) Zeros in the code : String copying (strcpy() )stops copying when a zero is found in the source
string. When the C code is compiled into binary, there will be zeros in the binary code which will
stop copying the badfile further.
Canadian
Institute for
Writing ShellCode Cybersecurity

- So , we cannot use the binary generated from a C program as our malicious code
- It is better to write the program using the assembly language.
- The assembly code for launching a shell is referred to as shellcode.

Use disassemble-all Shellcode

Objdump(machine code)

https://www.exploit-db.com/shellcodes
Q. What real challenges are there for an attacker to conduct BO attack.

Q. How can an attacker launch BO attack without knowing all the information
about the target program.

You might also like