0% found this document useful (0 votes)
3 views23 pages

Module 3

Uploaded by

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

Module 3

Uploaded by

Arnav Nigam
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Module 3 –

🧠 Buffer Overflows – Memory Layout Basics


Before understanding buffer overflow, you need to know how memory is organized in a program.

A running program is mainly divided into 3 parts:

1️⃣ Program Code (Text Segment)

👉 This is where your actual program instructions are stored.

📌 Contains:

 Compiled code (.exe instructions)

 Functions

 Library code (like printf, etc.)

💡 Key Point:

 This part is usually read-only

 It tells the CPU what to do

👉 Think of it as:
🧾 Recipe (instructions)

2️⃣ Program Data (Data + Heap)

👉 This is where variables are stored

📌 Includes:

 Global variables (declared outside functions)

 Static variables

 Heap (dynamic memory)

🔹 Heap (Important)

👉 Used when you do:

malloc(), new

 Memory is allocated at runtime

 You control it manually

💡 Example:
int *ptr = malloc(10 * sizeof(int));

👉 Memory is taken from heap

👉 Think of it as:
📦 Storage area where you can request space anytime

3️⃣ Program Stack

👉 Used for function execution

📌 Contains:

 Local variables

 Function parameters

 Return addresses

💡 Example:

void func() {

int x = 10; // stored in stack

🔹 How stack works:

 Follows LIFO (Last In First Out)

 Each function call creates a stack frame

👉 Think of it as:
📚 Stack of plates (last added → first removed)

💣 Now: Where Buffer Overflow Happens?

👉 Buffer overflow usually happens in:

 Stack (stack overflow)

 Heap (heap overflow)

🔥 Example:

char buffer[10];

gets(buffer); // no size check ❌

If user enters:
"This is a very long input"
👉 It will overflow buffer and overwrite:

 Other variables

 Return address

💥 Result:

 Crash OR

 Attacker can run malicious code

⚠️Why Understanding Memory is Important

Because attackers:

 Target stack → overwrite return address

 Target heap → corrupt memory

🔑 Final Quick Summary:

👉 Program Code → instructions


👉 Program Data (Heap) → global + dynamic memory
👉 Stack → function calls + local variables

👉 Buffer Overflow = writing more data than memory can hold → corrupts these regions

Heap
🧠 Step-by-step Simple Explanation
🔹 1. malloc() – Taking memory from heap

char *ptr = (char*) malloc(10);

👉 You ask for 10 bytes


👉 System gives you memory from heap

🔹 2. Hidden thing (IMPORTANT)

When memory is given, it is not just 10 bytes.

Internally it looks like:

[ HEADER | YOUR DATA ]

ptr

👉 HEADER (hidden) stores:

 Size of memory

 Whether it’s free/used

 Info about nearby blocks

🔹 3. free() – Releasing memory

free(ptr);

👉 System:

 Uses header info

 Marks that block as free

 So it can reuse it later

🔹 4. Why header is needed

👉 Because system must:

 Know how much memory was given

 Track which blocks are free or used

 Manage heap efficiently

💥 Where Heap Overflow comes in

If you do:
char *ptr = malloc(10);

strcpy(ptr, "this is a very long string"); // ❌

👉 You write more than 10 bytes

👉 Result:

 Data spills outside your block

 Header or next block gets corrupted

💣 Why dangerous

 System loses track of memory

 Program may crash

 Attacker can manipulate memory

🔑 One-line takeaway:

👉 Heap memory has hidden headers for management, and overflowing data can corrupt these
headers, causing serious issues.

🧠 Glibc Heap Structure (Simple Explanation)


When you use malloc() in C/C++, glibc (the standard C library) manages heap memory using blocks.

Each block has a hidden header (metadata) before your actual data.

📦 Structure of a Heap Block

[ HEADER | USER DATA ]

ptr

👉 You only see USER DATA


👉 But system uses HEADER to manage memory

🔍 What the Header Stores

1️⃣ Size of Current Block

👉 How big this memory block is

 Needed when freeing memory


 Helps system know how much space to manage

2️⃣ Size of Previous Block

👉 Size of the block just before this one

 Helps in merging adjacent free blocks

 Improves memory efficiency

3️⃣ Free or In Use

👉 Whether this block is:

 ✅ Allocated (in use)

 ❌ Free (available)

👉 Used by system to decide:

 Where to give memory next

 Which blocks can be reused

4️⃣ Additional Flags

👉 Extra info like:

 Special conditions

 Memory alignment

 Status bits

💡 Why this is important

👉 All memory management depends on this header

If this gets corrupted (heap overflow):

 System gets wrong info

 Memory handling breaks

 Can lead to crashes or exploits

💣 Simple Idea

👉 Think of each block like:

[Label: size=10, status=used | your data]


If label gets damaged ❌
👉 System gets confused

🔑 One-line takeaway:

👉 Glibc heap uses hidden headers (size, status, etc.) to manage memory, and corrupting them leads
to serious vulnerabilities.

🧠 Global & Static Data Overflows (Simple


Explanation)
🔹 1. What are Global & Static variables?

✅ Global variables

int count = 0; // global

✅ Static variables

static int x = 10;

👉 These:

 Exist for the entire program lifetime

 Stored in a separate memory area (data segment)


(not stack, not heap)

🔹 2. Where are they stored?

Memory layout:

[ Code ]

[ Global / Static Data ] ← THIS PART

[ Heap ]

[ Stack ]

👉 So they are permanent variables

🔹 3. What is Global/Static Overflow?

👉 If a buffer is stored in this region:

char buffer[10]; // global

and you do:


strcpy(buffer, "this is a very long string"); // ❌

👉 It will overflow and overwrite nearby global/static variables

💥 What gets affected?

👉 Nearby variables in memory, like:

char buffer[10];

int isAdmin = 0;

Overflow:

strcpy(buffer, "AAAAAAAAAAAA");

👉 Can overwrite:

isAdmin = 1; // 💣 attacker gains admin access

🔥 Why exploitation is harder here

👉 Unlike heap/stack:

 No return addresses

 No complex structures

👉 So attacker depends on:

 What variables are nearby

 How they are used

💣 When it becomes dangerous

👉 VERY dangerous if attacker overwrites:

 Pointer variables

 Flags (like isAdmin)

 Function pointers

Example (Pointer corruption)

char buffer[10];

int *ptr;

strcpy(buffer, "AAAAAAAABBBB"); // overflow


// ptr gets corrupted → points anywhere

*ptr = 100; // writes to random memory 💣

🔑 Key Idea

👉 Exploit depends on:

 Which variable gets corrupted

 How that variable is used

🧾 Simple Real-Life Analogy

👉 Think of global memory like:

 A fixed storage shelf

If you overflow one box:

 You overwrite items in neighboring boxes

🔑 Final One-Line

👉 Global/Static overflow = overwriting nearby persistent variables, which can lead to control if
important variables (like pointers) are corrupted.

If you want next, I can explain:


👉 Stack vs Heap vs Global overflow (full comparison — very important for exams)

🧠 Stack vs Heap vs Global Overflow (Full


Comparison)
🔹 1. STACK OVERFLOW

📌 Where?

 Stack memory (function calls, local variables)

📌 Example:

void func() {
char buf[10];

gets(buf); // ❌ overflow

💥 What gets corrupted?

 Local variables

 Return address (VERY IMPORTANT)

💣 Impact:

 Attacker can control execution flow

 Can run malicious code

🔥 Exploit level:

👉 Very High (most dangerous & common)

🔹 2. HEAP OVERFLOW

📌 Where?

 Heap memory (malloc, new)

📌 Example:

char *ptr = malloc(10);

strcpy(ptr, "very long input"); // ❌

💥 What gets corrupted?

 Adjacent memory blocks

 Heap metadata (headers)

 Pointers

💣 Impact:

 Memory corruption

 Pointer overwrite

 Control execution indirectly

🔥 Exploit level:

👉 High (complex but powerful)

🔹 3. GLOBAL / STATIC OVERFLOW

📌 Where?
 Data segment (global & static variables)

📌 Example:

char buf[10];

int isAdmin = 0;

strcpy(buf, "AAAAAAAAAAAA"); // ❌

💥 What gets corrupted?

 Nearby global/static variables

💣 Impact:

 Change program logic

 Modify flags (like isAdmin)

 Pointer corruption (if present)

🔥 Exploit level:

👉 Medium (depends on variables nearby)

📊 🔥 FINAL COMPARISON TABLE

Feature Stack Overflow Heap Overflow Global Overflow

Memory Area Stack Heap Data Segment

Variables Local Dynamic (malloc) Global/Static

Main Target Return address Metadata & pointers Variables

Exploit Type Direct control Indirect control Logic manipulation

Difficulty Medium Hard Easy

Impact 🚨 Very High 🚨 High ⚠️Medium

🎯 Key Differences (Easy Way to Remember)

 Stack → controls execution (return address) 💣

 Heap → controls memory management (pointers) ⚙️

 Global → controls program logic (variables) 🧠

🔑 Final One-Line (Exam Gold)


👉 Stack overflow hijacks execution directly, heap overflow corrupts memory structures to gain
control, and global overflow manipulates program variables and logic.

If you want, I can give you:


👉 Real attack examples + diagrams (very helpful for viva/interviews)

🧠 Language-Based Vulnerabilities (C Data Types)


🔹 Definition (Write this in exam)

👉 Language-based vulnerabilities arise due to improper use or misunderstanding of programming


language features such as data types, leading to unexpected behavior, overflows, or security
issues.

🔍 Basic Idea

👉 In C, different data types store data differently:

 Size (how many bytes)

 Range (min–max values)

 Signed/Unsigned behavior

👉 If used incorrectly ❌
👉 It can cause:

 Overflow

 Wrong calculations

 Security bugs

📦 Types of Data Types in C


1️⃣ Character Types

char

signed char

unsigned char

📌 Difference:

 char → may be signed/unsigned (depends on system)

 signed char → -128 to 127

 unsigned char → 0 to 255

⚠️Vulnerability:

unsigned char x = 255;

x = x + 1; // becomes 0 ❌ overflow

💥 Result:

 Unexpected behavior

2️⃣ Integer Types

short int

int

long int

long long int

📌 Difference:

 Different sizes (2, 4, 8 bytes etc.)

⚠️Vulnerability:

int x = 2147483647;

x = x + 1; // overflow ❌

💥 Result:

 Becomes negative

 Logic errors

3️⃣ Floating Types

float
double

long double

Also:

float _Complex

double _Complex

⚠️Vulnerability:

 Precision errors

 Rounding issues

float x = 0.1 + 0.2;

printf("%f", x); // may not be exactly 0.3 ❌

4️⃣ Bit (Signed/Unsigned)

👉 Integers can be:

 Signed → allow negative values

 Unsigned → only positive

⚠️Vulnerability:

int a = -1;

unsigned int b = a;

printf("%u", b); // huge positive number ❌

💥 Result:

 Type conversion bugs

 Security issues

5️⃣ Type Aliasing (typedef)

typedef unsigned int uint32_t;

Common types:

 int8_t → 8-bit signed

 uint8_t → 8-bit unsigned

 int32_t → 32-bit signed

 uint32_t → 32-bit unsigned


📌 Why used?

👉 To ensure fixed size and consistency

⚠️Vulnerability:

👉 If wrong type is used:

 Size mismatch

 Overflow

 Data misinterpretation

💣 Why this is dangerous (Security View)

👉 Attackers exploit type issues to:

 Cause integer overflow

 Bypass checks

 Manipulate memory

🧾 Simple Example

int size = -1;

if (size < 100) {

malloc(size); // ❌ converted to large unsigned value

💥 Result:

 Huge memory allocation

 Crash or exploit

🔑 Final One-Line (Exam Ready)

👉 Language-based vulnerabilities occur due to incorrect handling of data types, leading to


overflow, type conversion errors, and unexpected program behavior.

🧠 Quick Revision Points

 Signed vs unsigned issues


 Integer overflow

 Type conversion bugs

 Precision errors

 Wrong data size

🧠 Arithmetic Boundary Conditions


🔹 Definition (Write this in exam)

👉 Arithmetic boundary conditions occur when arithmetic operations (addition, subtraction,


multiplication) produce values outside the valid range of a data type, leading to overflow or
underflow.

🔍 Basic Idea

👉 Every variable has a fixed size and range

Example:

 unsigned int (4 bytes) → range:

 0 to 2^32 - 1

👉 If result goes:

 Above max → Overflow

 Below min → Underflow

💥 1️⃣ Numeric Overflow

❌ Example:

unsigned int a;

a = 0xE0000000;

a = a + 0x20000020;

👉 Actual result:

0x100000040 (too large ❌)


👉 But variable can't store it → extra bits lost

💣 Result:

 Value becomes incorrect

 Wraps around

🔥 Simple Understanding

👉 Think of a container:

 Max capacity = fixed

 If you add more → overflow

💥 2️⃣ Numeric Underflow

❌ Example:

unsigned int a = 0;

a = a - 1;

👉 Expected:

-1 ❌ (not possible in unsigned)

👉 Actual result:

4294967295 (very large number)

🔥 Simple Understanding

👉 Going below minimum → wraps to maximum

🧠 Modular Arithmetic (VERY IMPORTANT)


🔹 Definition

👉 Modular arithmetic means working with remainders after division

🔍 Example:

100 % 11 = 1

100 / 11 = 9

👉 Because:
100 = 11 × 9 + 1

📌 General Formula (IMPORTANT)

a=b×q+r

where 0 ≤ r < b

 a = number

 b = divisor

 q = quotient

 r = remainder

🔥 Connection to Overflow

👉 Computers use modular arithmetic internally

Example:

 If value exceeds limit → wraps around (modulo behavior)

unsigned int x = MAX;

x = x + 1; // becomes 0

👉 Same as:

(x + 1) % (max_value + 1)

🎯 Real Use of Modular Arithmetic

1️⃣ Hash Tables

index = hash % 100;

👉 Ensures:

 Value always between 0 to 99

2️⃣ Bounded Values

👉 Keeps numbers within range

⚠️Security Impact

👉 Overflow/underflow can:

 Bypass checks
 Cause buffer overflow

 Lead to vulnerabilities

🧾 Simple Real-Life Analogy

👉 Think of a clock (12 hours):

 After 12 → goes back to 1


👉 That’s modular arithmetic

🔑 Final One-Line (Exam Ready)

👉 Arithmetic boundary conditions occur when values exceed limits of data types, causing
overflow/underflow, and computers handle this using modular arithmetic (wrap-around behavior).

🧠 Quick Revision Points

 Overflow → value too large

 Underflow → value too small

 Modular arithmetic → remainder system

 Used in hash tables

 Causes wrap-around behavior

If you want next, I can explain:


👉 Integer Overflow exploitation (VERY IMPORTANT for cybersecurity)

Byte Order Conversion


1. The Two Formats

 Big-Endian: Stores the Most Significant Byte (the left-most, largest value part) in the lowest
memory address. It stores data exactly how humans read it (left to right).

 Little-Endian: Stores the Least Significant Byte (the right-most, smallest value part) in the
lowest memory address. It stores data in reverse.

Example from your 3rd image:

Data: 00001010 (MSB) | 00010111 | 00001110 | 00000110 (LSB)


 Big-Endian Memory: 00001010 goes into Address A (the first slot).

 Little-Endian Memory: 00000110 goes into Address A (the first slot).

2. Network Byte Order Functions (2nd Image)

Different computer processors use different formats (e.g., Intel processors use Little-Endian).
However, network protocols (the internet) universally use Big-Endian. If a Little-Endian computer
sends data over the internet without translating it, the receiving computer will read the bytes
backward, completely corrupting the data.

To prevent this, programmers use built-in C functions to safely translate the bytes before sending or
receiving. The functions are named using a simple shorthand:

 h = host (your local computer's format)

 n = network (the internet's format, which is Big-Endian)

 s = short (16-bit number / 2 bytes)

 l = long (32-bit number / 4 bytes)

Examples:

 htonl(): Host TO Network Long. Converts a 32-bit number from your computer's native
format into the network's format before transmitting it.

 ntohs(): Network TO Host Short. Converts a 16-bit number received from the network back
into your computer's native format.

Type Conversion Vulnerabilities.


In programming, data types are like boxes of specific shapes and sizes. A vulnerability occurs when
the computer is forced to move a number from one type of box into a completely different type of
box, or when it tries to do math with two different boxes. The computer tries to be helpful by silently
"converting" the numbers, but it often does so in a way that breaks security logic.

Here is the breakdown of how these conversions work and why they are dangerous, especially during
comparisons.

1. Signed vs. Unsigned Types

 Signed numbers can be positive or negative (e.g., -5, 10). They use their very first binary bit
to declare their sign (0 for positive, 1 for negative).
 Unsigned numbers can only be positive (e.g., 0, 10, 255). Because they don't need a sign bit,
they can store much larger positive numbers.

The Danger: If you try to compare a Signed -1 to an Unsigned 5, the computer gets confused. It will
secretly convert the -1 into an Unsigned number. In the binary world, a signed -1 translated into an
unsigned number becomes an absolutely massive number (like 4,294,967,295).

2. Sign Extension

When you move a small number (like an 8-bit number) into a larger box (like a 16-bit box), there is
empty space. The computer must pad that space.

 If the original number is positive, it pads the empty space with 0s.

 If the original number is negative, it pads the space with 1s to ensure the number stays
negative.

The Danger: If a hacker passes a negative number into a system, and the system applies sign
extension (filling it with 1s) but then later reads that data as an unsigned positive number, those
padded 1s turn into a giant, unintended positive value.

3. Truncation

Your text describes decimal truncation (like the trunc() function chopping 3.5 down to 3.0).

However, in Code Auditing, the more dangerous version is Integer Truncation. This happens when
you try to stuff a large number into a box that is too small.

 If you have a 32-bit number and force it into a 16-bit variable, the computer literally chops
off the top half of the binary code.

 The Danger: A hacker might send an oversized file size that bypasses a security check, but
when it gets truncated, the chopped-up number looks small and safe to the system.

4. Arithmetic Conversions (The "Upgrade" Rule)

When you write code that does math or compares two different types of variables (like an int and a
float), the compiler follows a strict ranking system to make them match.

 The rule is simple: The lower-ranked type is always upgraded to the higher-ranked type.

 If you mix a float and a double, the float becomes a double.

 If you mix a Signed int and an Unsigned int, the Signed integer is upgraded to Unsigned.
Shellcode -
1. What is Shellcode?

Shellcode is a small, custom piece of raw machine code (executable instructions) that an attacker
injects into a vulnerable program's memory.

Its name comes from its traditional purpose: to open a "shell" (a command-line terminal like /bin/sh
in Linux or [Link] in Windows) so the attacker can type commands directly into the compromised
system.

2. How it works with Buffer Overflows

As we covered earlier, a buffer overflow allows an attacker to write data past the boundaries of a
memory buffer.

In a standard program, right next to that buffer is a critical piece of memory called the Return
Address. This address acts as a signpost telling the CPU exactly where to go to execute the next
instruction.

The exploit works in two steps:

1. Inject: The attacker pushes the shellcode into the memory buffer.

2. Redirect: The attacker intentionally overflows the buffer until they overwrite the Return
Address. They change that address so it points directly to the location where they just
injected their shellcode. When the CPU reads the altered Return Address, it blindly follows
the signpost and executes the attacker's code.

3. The Provided C Code

char *args[] = { "/bin/sh", NULL };

execve("/bin/sh", args, NULL);

This is standard C code used to spawn a terminal in UNIX/Linux systems. However, a CPU cannot read
C code directly. The attacker must compile this specific C code into raw binary (machine code) and
use that binary sequence as their injected shellcode.

4. Staged Shellcode ("Stubs")

Often, the vulnerable memory buffer is too small to hold a large, complex piece of shellcode.

To solve this, attackers inject a Stub. A stub is a microscopic piece of shellcode that does only one
thing: it opens a network connection back to the attacker's computer, downloads the rest of the
larger malicious payload directly into memory, and then runs it.
Here is a Memory Flow Simulator to help you visualize exactly how an attacker manipulates the
Return Address to force the CPU to execute injected Shellcode instead of the normal program.

Show me the visualisation

You might also like