01 · INTRODUCTION

⚙️ What Are C and C++?

C was created by Dennis Ritchie at Bell Labs in 1972. It was designed for system programming — specifically, to rewrite the UNIX operating system. Nearly every modern operating system, including Linux, Windows, macOS, and Android, is written largely in C. It's the closest thing to a universal assembly language.

C++ was developed by Bjarne Stroustrup in 1979 as an extension of C. It added object-oriented programming, templates, exceptions, and a huge standard library. C++ powers everything from game engines (Unreal) to browsers (Chrome) to databases (MySQL) to embedded systems.

For ethical hackers and security researchers, C and C++ are essential because they're the languages of exploit development, malware analysis, reverse engineering, and low-level systems work. If you want to understand buffer overflows, write shellcode, or analyze malware, you need C.

💡 Note: C and C++ are compiled languages. You write code in a text file, compile it with gcc or g++, and get a binary executable. This is different from Python or Ruby, which are interpreted.
02 · WHY C & C++ FOR HACKERS

💡 Why Ethical Hackers Learn C/C++

Python and Ruby are great for automation, but when you need raw power, direct memory access, and speed, nothing beats C and C++. Here's why they're essential for serious security work:

💥

Exploit Development

Buffer overflows, ROP chains, and shellcode are written in C/Assembly.

🔬

Malware Analysis

Most malware is written in C/C++ — you need to read and understand it.

🔧

Custom Tools

Write high-performance security tools, rootkits, and implants.

🎯

Reverse Engineering

Understanding C teaches you how compilers generate assembly.

🧠

Memory Management

Learn how memory works — critical for exploitation and debugging.

⚡

Performance

C runs 50-100x faster than Python. Essential for brute-forcing at scale.

🔑 Key Insight: You don't need to write everything in C. But you absolutely need to read C to understand exploits, malware, and low-level security research.
03 · SETUP & COMPILATION

🛠️ Installing Compilers & Writing Code

On Kali Linux, you'll need gcc (C compiler) and g++ (C++ compiler). Both come pre-installed on most systems, but you can install them if missing.

# Install compilers on Kali/Debian sudo apt update sudo apt install build-essential gcc g++ gdb # Check versions gcc --version g++ --version

Compiling a C Program

# Compile and run gcc hello.c -o hello ./hello # Compile with debug symbols (for gdb) gcc -g hello.c -o hello # Disable protections (for exploit dev practice) gcc -fno-stack-protector -z execstack -no-pie hello.c -o hello # Compile C++ g++ hello.cpp -o hello

Your First C Program

#include <stdio.h> int main() { printf("Hello, Ethical Hacker!\n"); return 0; }
04 · C FUNDAMENTALS

📚 C Fundamentals

Every C program has a main function where execution begins. You must #include the libraries you use and declare the return type of every function.

Hello World — Detailed Breakdown

// Preprocessor directive — includes the standard I/O library #include <stdio.h> // main() is the entry point. Returns int (exit code). int main(int argc, char *argv[]) { printf("Hello, Ethical Hacker!\n"); printf("Program name: %s\n", argv[0]); return 0; // 0 = success, non-zero = error }

Variables & Data Types

int port = 22; // Integer (4 bytes typically) char grade = 'A'; // Single character (1 byte) float ratio = 3.14f; // Single-precision float double pi = 3.14159265; // Double-precision float unsigned int count = 100; // No negative values long long big = 1234567890; // Larger integer // Constants const int MAX = 100;

Data Type Sizes

TypeSize (typical)Range
char1 byte-128 to 127
short2 bytes-32,768 to 32,767
int4 bytes-2.1B to 2.1B
long4-8 bytesPlatform dependent
float4 bytes~7 decimal digits
double8 bytes~15 decimal digits
void*8 bytesAny pointer (64-bit)

Input & Output

int port; char host[64]; printf("Enter host: "); scanf("%s", host); printf("Enter port: "); scanf("%d", &port); printf("Target: %s:%d\n", host, port); // Format specifiers // %d = int, %s = string, %c = char, %f = float, %p = pointer, %x = hex
⚠️ Warning: scanf("%s", buf) is dangerous — it doesn't check buffer size and causes buffer overflows. Use fgets() instead, or specify width: scanf("%63s", buf).
05 · DATA TYPES

📦 Data Types & Modifiers

Type Modifiers

signed int a = -10; // Can be negative (default) unsigned int b = 10; // Only positive short int c = 100; // Smaller range long int d = 100000L; // Larger range long long e = 1000000LL;

Type Casting

int a = 10; int b = 3; // Integer division — loses decimal float result1 = a / b; // 3.0 (integer division) float result2 = (float)a / b; // 3.333... (cast to float) printf("%.2f\n", result2);

Enumerations

enum Status { CLOSED, OPEN, FILTERED }; enum Status port_status = OPEN; if (port_status == OPEN) { printf("Port is open!\n"); } // Custom values enum Color { RED = 1, GREEN = 2, BLUE = 4 };
06 · CONTROL FLOW

🔀 Control Flow

If / Else If / Else

int port = 443; if (port == 22) { printf("SSH\n"); } else if (port == 80) { printf("HTTP\n"); } else if (port == 443) { printf("HTTPS\n"); } else { printf("Unknown\n"); }

Switch Statement

switch (port) { case 22: printf("SSH\n"); break; case 80: case 443: printf("Web\n"); break; default: printf("Unknown\n"); }

Loops

// for loop for (int i = 0; i < 10; i++) { printf("%d\n", i); } // while loop int n = 0; while (n < 10) { printf("%d\n", n); n++; } // do-while (runs at least once) do { printf("Runs once at minimum\n"); } while (0); // break & continue for (int i = 0; i < 100; i++) { if (i % 2 == 0) continue; // Skip evens if (i > 20) break; // Stop at 20 printf("%d\n", i); }
07 · FUNCTIONS

🧩 Functions & Scope

Declaring Functions

// Function prototype (declaration) int add(int a, int b); // Function definition int add(int a, int b) { return a + b; } // Function that takes a pointer (modifies original) void increment(int *n) { (*n)++; } int main() { printf("%d\n", add(5, 3)); // 8 int x = 10; increment(&x); printf("%d\n", x); // 11 return 0; }

Static & Global Variables

int global_counter = 0; // Accessible everywhere void counter() { static int count = 0; // Persists across calls count++; printf("Called %d times\n", count); } int main() { counter(); // 1 counter(); // 2 counter(); // 3 return 0; }

Recursion

int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); } printf("%d\n", factorial(5)); // 120
08 · POINTERS & MEMORY

🎯 Pointers & Memory Management

Pointers are the most important and most dangerous feature of C. They store memory addresses and give you direct control over memory — which is why C is used for exploits and malware.

Pointer Basics

int x = 42; int *p = &x; // p holds the address of x printf("x = %d\n", x); // 42 printf("&x = %p\n", &x); // address printf("p = %p\n", p); // same address printf("*p = %d\n", *p); // 42 (dereferencing) *p = 100; // Modify x through pointer printf("x = %d\n", x); // 100

Dynamic Memory Allocation

#include <stdlib.h> // Allocate memory for 10 ints int *arr = (int *)malloc(10 * sizeof(int)); // Check if allocation succeeded if (arr == NULL) { fprintf(stderr, "Memory allocation failed\n"); return 1; } // Use the array for (int i = 0; i < 10; i++) { arr[i] = i * i; } // Free the memory when done free(arr); // Other allocation functions calloc(10, sizeof(int)); // Zero-initialized realloc(arr, 20 * sizeof(int)); // Resize
⚠️ Critical: Always free() memory you malloc(). Always check for NULL. Never use memory after freeing. These bugs are the source of countless exploits.

Pointer Arithmetic

int arr[] = {10, 20, 30, 40}; int *p = arr; printf("%d\n", *p); // 10 printf("%d\n", *(p+1)); // 20 printf("%d\n", *(p+2)); // 30 p++; // Move pointer forward printf("%d\n", *p); // 20
09 · ARRAYS & STRINGS

📊 Arrays & Strings

Arrays

// Declare and initialize int ports[5] = {21, 22, 80, 443, 3306}; // Access and modify printf("%d\n", ports[0]); // 21 ports[1] = 2222; // Iterate for (int i = 0; i < 5; i++) { printf("Port: %d\n", ports[i]); } // 2D array int matrix[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};

Strings — Character Arrays

#include <string.h> // C strings are null-terminated char arrays char name[20] = "Hacker"; char *host = "example.com"; // Common string functions strlen(name); // Length: 6 strcpy(name, "NewName"); // Copy (unsafe!) strncpy(name, "Safe", 19); // Copy with bound strcat(name, "!"); // Concatenate strcmp(name, "Other"); // Compare strstr(name, "ack"); // Find substring // Safe input fgets(name, sizeof(name), stdin);
⚠️ Warning: strcpy() and strcat() don't check buffer sizes — they cause buffer overflows. Use strncpy() and strncat() with explicit bounds. This is one of the most common vulnerability classes.
10 · STRUCTS & UNIONS

🏗️ Structs, Unions & Typedefs

Structs — Custom Data Types

struct Target { char ip[16]; int port; char os[32]; int vulnerable; }; // Using a struct struct Target t1; strcpy(t1.ip, "192.168.1.1"); t1.port = 22; strcpy(t1.os, "Linux"); t1.vulnerable = 1; printf("Target: %s:%d (%s)\n", t1.ip, t1.port, t1.os); // Pointer to struct struct Target *ptr = &t1; printf("Port: %d\n", ptr->port); // Arrow operator

Typedef — Cleaner Syntax

typedef struct { char ip[16]; int port; } Target; // Now use without "struct" keyword Target t1; t1.port = 80;

Unions — Shared Memory

union Data { int i; float f; char str[4]; }; union Data d; d.i = 0x41424344; // Access same bytes as different types printf("%c%c%c%c\n", d.str[3], d.str[2], d.str[1], d.str[0]);
11 · C++ & OOP

🔷 C++ & Object-Oriented Programming

C++ extends C with object-oriented features: classes, inheritance, polymorphism, templates, and exceptions. It's a superset of C — almost all C code compiles as C++.

C++ Hello World

#include <iostream> int main() { std::cout << "Hello, Hacker!" << std::endl; return 0; }

Classes & Objects

class Target { private: std::string ip; int port; std::vector<int> open_ports; public: // Constructor Target(std::string ip, int port) : ip(ip), port(port) {} // Destructor ~Target() {} // Methods void addPort(int p) { open_ports.push_back(p); } void display() const { std::cout << "Target: " << ip << ":" << port << std::endl; } // Getter std::string getIp() const { return ip; } }; int main() { Target t("192.168.1.1", 22); t.addPort(80); t.addPort(443); t.display(); return 0; }

Inheritance

class WebTarget : public Target { private: std::string domain; public: WebTarget(std::string ip, int port, std::string domain) : Target(ip, port), domain(domain) {} void display() const { Target::display(); std::cout << "Domain: " << domain << std::endl; } };

Polymorphism & Virtual Functions

class Scanner { public: virtual void scan() { std::cout << "Generic scan" << std::endl; } virtual ~Scanner() {} }; class NmapScanner : public Scanner { public: void scan() override { std::cout << "Running Nmap scan" << std::endl; } };
12 · STL & TEMPLATES

📚 Standard Template Library (STL)

The STL is C++'s killer feature — a rich collection of data structures and algorithms ready to use.

Common Containers

#include <vector> #include <map> #include <set> #include <string> // Vector — dynamic array std::vector<int> ports = {22, 80, 443}; ports.push_back(8080); for (int p : ports) { std::cout << p << std::endl; } // Map — key-value pairs (sorted) std::map<std::string, int> services; services["ssh"] = 22; services["http"] = 80; services["https"] = 443; for (auto &pair : services) { std::cout << pair.first << " → " << pair.second << std::endl; } // Set — unique elements std::set<std::string> unique_ips = {"10.0.0.1", "10.0.0.2"};

Templates — Generic Programming

template <typename T> T max(T a, T b) { return (a > b) ? a : b; } std::cout << max(5, 10) << std::endl; // int std::cout << max(3.14, 2.71) << std::endl; // double std::cout << max(std::string("a"), std::string("b"));

Smart Pointers (C++11+)

#include <memory> // Unique pointer — exclusive ownership std::unique_ptr<int> p1 = std::make_unique<int>(42); // Shared pointer — reference counted std::shared_ptr<int> p2 = std::make_shared<int>(100); // No manual delete needed — automatic cleanup
13 · SECURITY & EXPLOITS

💥 Security, Exploits & Vulnerabilities

Understanding C at a low level is essential for exploitation. Here are the classic vulnerability classes you'll encounter.

Buffer Overflow — The Classic

// VULNERABLE CODE — DO NOT USE IN PRODUCTION void vulnerable(char *input) { char buffer[64]; strcpy(buffer, input); // No bounds check! } // If input is longer than 64 bytes, it overwrites // the return address on the stack → code execution // SAFE version void safe(char *input) { char buffer[64]; strncpy(buffer, input, sizeof(buffer) - 1); buffer[sizeof(buffer) - 1] = '\0'; }

Format String Vulnerability

// VULNERABLE printf(user_input); // If user_input contains %x, %s, %n... // SAFE printf("%s", user_input);

Integer Overflow

unsigned int a = 4294967295; // Max uint32 a = a + 1; // Wraps to 0! // Common in size calculations: int size = user_len + 1; // Can overflow char *buf = malloc(size); // Too small allocation

Use-After-Free

char *ptr = malloc(100); free(ptr); // ptr is now dangling strcpy(ptr, "data"); // Use-after-free vulnerability!

Compilation Protections

ProtectionFlagPurpose
Stack Canary-fstack-protectorDetects stack smashing
NX / DEP-z noexecstackPrevents code on stack
PIE / ASLR-pie -fPIERandomizes memory layout
RELRO-Wl,-z,relroProtects GOT
FORTIFY-D_FORTIFY_SOURCE=2Checks buffer sizes
# Compile with all protections enabled (production) gcc -fstack-protector-strong -D_FORTIFY_SOURCE=2 -pie -fPIE -Wl,-z,relro,-z,now secure.c -o secure # Compile with NO protections (for exploit dev practice) gcc -fno-stack-protector -z execstack -no-pie -m32 vulnerable.c -o vulnerable
14 · SECURITY TOOLS

🔧 C/C++ Security Tools

🐛 gdb

GNU Debugger — the essential tool for reverse engineering and exploit development.

🔬 pwndbg / GEF

gdb plugins that supercharge debugging with heap analysis, ROP gadgets, and more.

📦 objdump

Disassemble binaries. See what a compiled program actually does at assembly level.

🔍 ltrace / strace

Trace library and system calls — see exactly what a binary does at runtime.

🎯 checksec

Inspect binary protections (ASLR, NX, canary, PIE, RELRO).

💣 ROPgadget

Find ROP gadgets in binaries for return-oriented programming attacks.

📖 radare2 / rizin

Reverse engineering framework. Disassemble, debug, patch binaries.

🔐 Ghidra

NSA's open-source reverse engineering suite. Decompiles binaries to C.

⚙️ valgrind

Memory error detector. Finds leaks, overflows, and uninitialized reads.

🛡️ AFL / libFuzzer

Fuzzing tools — feed random input to find crashes and vulnerabilities.

Basic gdb Usage

# Start debugger gdb ./program # Inside gdb: (gdb) break main # Set breakpoint (gdb) run # Run program (gdb) next # Step over (gdb) step # Step into (gdb) info registers # Show all registers (gdb) x/20x $rsp # Examine stack memory (gdb) disassemble main # Show assembly (gdb) continue # Resume (gdb) quit # Exit
15 · USE CASES

🎯 Where C/C++ Shines in Security

💥

Exploit Development

Buffer overflows, ROP chains, heap exploitation, shellcode.

🔬

Malware Analysis

Most malware is written in C/C++ — read, understand, and analyze it.

🔧

Rootkits & Implants

Low-level kernel modules and persistent backdoors.

🎯

Reverse Engineering

Understand how compilers generate assembly and how to reverse it.

🔐

Cryptography

Implement crypto primitives, custom encryption, and bypasses.

📡

Network Tools

High-performance packet sniffers, packet crafters, and scanners.

🧪

Fuzzing

Write custom fuzzers and analyze crashes for vulnerabilities.

🛡️

Security Tools

Nmap, Metasploit, Wireshark, John — all use C/C++ internally.

16 · BEST PRACTICES

✅ Best Practices

  1. Always check for NULL — After malloc(), fopen(), etc.
  2. Use bounded string functions — strncpy(), snprintf(), fgets().
  3. Free what you allocate — Avoid memory leaks. Use valgrind to check.
  4. Compile with warnings — gcc -Wall -Wextra -Werror.
  5. Enable security flags — -fstack-protector-strong -D_FORTIFY_SOURCE=2 -pie -fPIE.
  6. Initialize variables — Never use uninitialized memory.
  7. Validate input — Never trust argv, stdin, or network data.
  8. Use const where possible — Documents intent and helps the compiler.
  9. Prefer C++ RAII over manual memory — Smart pointers, vectors, strings.
  10. Test with sanitizers — -fsanitize=address,undefined during development.

Safe Compilation Flags

# Development (with sanitizers) gcc -g -Wall -Wextra -fsanitize=address,undefined program.c -o program # Production (with hardening) gcc -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 \ -fPIE -pie -Wl,-z,relro,-z,now program.c -o program

Valgrind — Memory Check

# Check for memory errors and leaks valgrind --leak-check=full --show-leak-kinds=all ./program
18 · CONCLUSION

🎓 Final Thoughts

C and C++ are the foundational languages of computing. Every operating system, every browser, every database, and virtually every security tool is built on them. For ethical hackers, they are indispensable — the key to understanding how systems actually work at the lowest level.

Python and Bash make you productive. C and C++ make you dangerous. They let you:

The journey follows a clear path:

  1. Learn C syntax — variables, control flow, functions, pointers.
  2. Master memory — malloc, free, stack vs heap, pointers.
  3. Understand the stack — how function calls work, return addresses.
  4. Learn gdb — debug binaries, inspect memory, set breakpoints.
  5. Practice exploitation — pwn.college, ROP Emporium, CTFs.
  6. Read real exploits — study CVEs and public PoCs.
🚀 Next Steps: Install gcc and gdb on Kali. Write a simple C program. Compile it, run it, then disassemble it. Then open gdb and inspect it. Within weeks, you'll understand exploitation at a level most hackers never reach.

Happy hacking — ethically. ⚙️