C Language Compiled Code refers to the machine-readable version of a program written in the C programming language. When you write C source code in human-readable files (.c and .h), it cannot be executed directly by a computer. A compiler translates this source code through several stages including preprocessing, compilation to assembly, assembling into object code, and linking with libraries to produce a standalone executable file. The resulting compiled code consists of binary instructions that the CPU can interpret and run directly. This makes compiled code fundamentally different from the original C source code, which is intended for humans to read, write, and modify.
Source Code
The code is in C language (.c and .h files)
cat # Command used to display the contents of a file test.c # The C source file whose contents will be printed to the terminal
(host) cat test.c
#include <stdio.h> // Includes the Standard Input/Output library so we can use functions like printf()
int main(){ // The main function: program execution starts here printf(“Hello World!”); // Prints the text “Hello World!” to the standard output (usually the terminal) return 0; // Ends the program and returns 0 to the operating system indicating successful execution }
#include <stdio.h>
int main(){ printf("Hello World!"); return 0; }
Pre-Processor
This step includes the headers and expand the macros, the generated file have the .i, .ii extensions
gcc # GNU C Compiler -E # Tells gcc to run only the preprocessor (expands #include, #define, etc.) test.c # The C source file being processed | # Pipe operator; sends the output of the command on the left to the command on the right head # Displays only the first 10 lines of the output
The assembly code gets converted into object code/machine code, the generated file have the .o, .obj extensions
gcc # GNU C Compiler -c # Compile the source code into an object file (machine code) without linking test.c # The C source file being compiled
(host) gcc -c test.c
cat # Outputs the contents of the file test.o # Object file containing compiled machine code | # Pipe operator; sends output of the left command to the right command xxd # Converts binary data into a hexadecimal (hex) and ASCII representation | # Pipe operator again head # Displays only the first 10 lines of the hex output
The last step is combining the object code/machine code and .lib/.a static library files, the generated file have the .exe, elf, bin extensions
gcc # GNU C Compiler used to compile and link the program test.c # The C source file being compiled -o # Option to specify the name of the output file test.bin # Name of the final executable binary file that will be created
(host) gcc test.c -o test.bin
cat # Outputs the contents of the file test.bin # The compiled executable binary file | # Pipe operator; sends output of one command to another xxd # Converts binary data into hexadecimal and ASCII representation | # Pipe operator again head # Displays the first 10 lines of the output
Computer Programming is the process of designing, creating, testing, and maintaining programs to perform specific tasks or solve particular problems. It involves translating logical solutions into a language computers can understand and execute. Programmers use languages like Python, Java, C++, or JavaScript to write code that instructs computers on how to carry out required operations.
Python
Python is a high-level, interpreted programming language known for its simplicity, readability, and versatility. It was first released in 1991 as Python 0.9.0 by Guido van Rossum. Python is cross-platform, so it can run on various operating systems like Windows, macOS, and Linux without significant code changes.
Python supports object-oriented programming, allowing developers to design software using objects that encapsulate data and behavior. It also supports procedural and functional programming paradigms, making it highly flexible. As an interpreted language, Python executes code line by line, which facilitates rapid development, easier debugging, and interactive testing.
Interpreted (?)
Interpreted refers to a method of program execution where the source code is not directly compiled into machine code beforehand. Instead, the code is executed line by line or in small sections at runtime, often through an interpreter.
Interpretation Process
Source Code: The programmer writes Python code in a human-readable form.
Compilation to Bytecode: Before execution, Python automatically translates the source code into bytecode, which is a low-level, platform-independent representation of the code.
Execution by the Python Virtual Machine (PVM): The PVM reads and executes the bytecode, translating it into machine-level instructions that the computer can understand.
Advantages
Cross-Platform Compatibility: Since the bytecode is platform-independent, the same Python program can run on any system with a compatible Python interpreter.
Ease of Debugging: Errors are caught during runtime, making testing and debugging easier, especially for beginners.
Interactive Development: Python supports interactive execution, allowing developers to test code snippets immediately without compiling the entire program.
Compiled
Compiled refers to a method of program execution where the source code written by the programmer is directly translated into machine code by a compiler before the program is run. Machine code consists of low-level instructions that a computer’s processor can execute directly.
Compilation Process:
Source Code: The programmer writes human-readable code in a programming language such as C, C++, or Rust.
Compilation: The compiler analyzes the source code, checks it for errors, and translates it into machine code specific to the target processor and operating system. This results in an executable file.
Linking: If the program uses external libraries or modules, the compiler links them together with the machine code to create a complete, runnable program.
Execution: The final executable file can be run directly by the computer without needing an interpreter.
Advantages
Faster Execution: Compiled programs generally run faster because the code is already translated into machine language.
Platform-Specific: The resulting executable is usually specific to the operating system and processor architecture it was compiled for.
Error Detection: Compilation detects many errors before the program is run, which can make debugging easier.
No Runtime Translation: Unlike interpreted languages, compiled code does not require an interpreter to execute.
Cross-Platform
Cross-Platform refers to software, applications, or programming languages that can run on multiple operating systems or hardware platforms with minimal modification. This means the same program can function on Windows, macOS, Linux, and sometimes even mobile operating systems like Android or iOS.
High-Level
A High-Level Programming Language is designed to be human-readable and easy to use. Unlike low-level languages, which are close to machine code and hardware operations, high-level languages use natural language elements, symbols, and abstractions that are intuitive for programmers.
Object-Oriented
OOP is a programming paradigm that organizes software design around objects—instances of classes. Objects are self-contained units containing data (attributes) and code (methods) that operate on that data. This approach models real-world entities, making programs easier to design, understand, and maintain.
Concepts
Class: A blueprint or template for creating objects, defining attributes and methods.
Object: A specific instance of a class with unique attribute values but shared structure.
Encapsulation: Keeping an object’s data and methods together while restricting outside access, providing controlled interaction.
Inheritance: Allowing a subclass to inherit properties and methods from a superclass, promoting code reuse.
Polymorphism: Enabling different objects to respond differently to the same method call, allowing flexible and interchangeable code.
Abstraction: Hiding complex implementation details and exposing only necessary parts.
Advantages
Modularity: Programs can be broken into reusable, independent objects.
Maintainability: Changes to one object typically do not affect others.
Reusability: Code is reused through inheritance and composition.
Real-World Modeling: Objects naturally map to real-world entities, making problem-solving intuitive.
Kernel Mode v.s. User Mode
The kernel is the core component of an operating system (OS) that manages system resources and facilitates communication between hardware and software. It acts as a bridge between user-level applications and computer hardware, ensuring safe and efficient use of resources like memory, CPU, and input/output devices.
Kernel-Level Applications (Privileged Mode)
Run in kernel mode, also known as privileged mode, with full access to all hardware and system resources.
Considered trusted because improper behavior can crash the system or compromise security.
Examples: device drivers, memory management routines, core OS functions.
User-Level Applications (Restricted Mode)
Run in user mode, a restricted environment that limits access to hardware and critical resources.
Considered less trusted, so the OS restricts their actions to prevent accidental or malicious damage.
Examples: web browsers, word processors, games.
Interaction via System Calls
User-level applications cannot directly access hardware or kernel resources. They communicate with the kernel through system calls.
A system call is a controlled interface that allows programs to request services like file operations, network communication, or memory allocation.
Kernel’s Role in Handling Requests
The kernel executes requested operations in privileged mode when it receives a system call.
After completing the task, the kernel returns control to the user-level application, maintaining system stability and security.
The kernel is crucial for system stability, security, and efficiency. By separating user mode from kernel mode, operating systems ensure that user applications are restricted while trusted kernel processes manage hardware and resources safely. This separation prevents accidental or malicious misuse of critical system functions and enables multitasking by controlling access to shared resources.
Example
Using the standard C library to output Hello World! to the standard output device
cat # Command used to display the contents of a file test.c # The C source file whose contents will be printed to the terminal
(host) cat test.c
#include <stdio.h> // Includes the Standard Input/Output library so we can use functions like printf()
int main(){ // The main function: program execution starts here printf(“Hello World!”); // Prints the text “Hello World!” to the standard output (usually the terminal) return 0; // Ends the program and returns 0 to the operating system indicating successful execution }
#include <stdio.h>
int main(){ printf("Hello World!"); return 0; }
gcc # GNU C Compiler program used to compile C source code test.c # The C source file being compiled -o # Option that tells the compiler to name the output file test.exe # Name of the compiled executable file that will be created
(host) gcc test.c -o test.exe
Output
Hello World!
Step by step of the process
User-mode: Program Execution
test.exe is loaded into user mode memory.
main() function begins execution in user mode.
User-mode: Calling the C Library
printf("Hello World!") function is called within main() function.
printf() function is part of the C standard library and runs in user mode.
System Call: Switching to Kernel-mode
printf internally calls write() system call to send data to stdout.
The write() system call is invoked, which causes a context switch from user mode to kernel mode.
Kernel-mode: Writing Output
The kernel’s write function is executed with the provided data.
The kernel accesses the terminal or console device buffer.
The string "Hello World!" is written to the hardware output (e.g., screen).
The kernel ensures that the operation is performed safely and that access control is maintained.
Kernel-mode: Return to User-mode
After the write operation completes, the kernel returns the result (number of bytes written or error code) back to user mode.
User-mode: Continuing Execution
printf() function receives the result from the kernel and completes its execution.
The main() function continues executing and returns 0, indicating successful termination.
Program Exit
The program exits cleanly, and control is returned to the operating system.
Some General-Purposes
Automation and Testing
Python is widely used for automating repetitive tasks such as file handling, data entry, and system monitoring. It is popular in software testing with frameworks like PyTest and unittest, allowing developers to write automated tests for applications.
Example: Automating data extraction from spreadsheets or websites.
Web Development, Game Development, and Business Applications
Python powers web development through frameworks like Django and Flask, enabling the creation of scalable and secure web applications. In game development, Python is used with libraries like Pygame to create 2D games and prototypes.
Examples: Inventory management, accounting, CRM systems, and desktop software, all benefiting from Python’s rapid development capabilities.
Data Science, Machine Learning, and Deep Learning
Python is the primary language for data science, offering libraries such as NumPy, Pandas, Matplotlib, and Seaborn for data analysis and visualization. In machine learning, libraries like scikit-learn, TensorFlow, and PyTorch enable developers to build predictive models and AI applications.
Deep learning frameworks in Python are used to create neural networks for tasks like image recognition, natural language processing, and other advanced AI applications.
Why Python?
Easy to learn: Python mimics English; it employs a streamlined syntax focusing on natural language, making learning more straightforward for newcomers.
Flexible and reliable: A language for general-purpose programming, it can be used to develop any application with minimum effort.
Extremely active community: The community has all sorts of Python professionals that provide access to documentation or answer your questions.
Python IDLE
Python’s IDLE is the integrated development environment (IDE) that can be downloaded on different operating systems
Install Python on macOS
Download the latest Python version from here & Install it
Go to Launchpad and look for IDLE (Integrated Development and Learning Environment)
Or, go to Launchpad, then Others, then Terminal, and finally type python3 there
The Application Layer is the seventh and topmost layer of the OSI model, providing the interface for end users to interact with network services. It acts as a bridge between user applications and the underlying network, allowing software to access communication functions without managing data transport or routing. This layer handles high-level protocols and services that enable tasks such as sending emails, browsing the web, transferring files, and accessing remote databases.
By providing these services, the Application Layer ensures seamless and efficient user interaction with the network.
In addition to user interaction, the Application Layer formats, presents, and interprets data in a way applications can understand. It could include functions such as data encoding, encryption, and session management to ensure information is meaningful, secure, and correctly synchronized. For example, a web browser at this layer requests HTML pages from a web server via HTTP and presents the content to the user in a readable format. Similarly, email clients use protocols such as SMTP, POP3, and IMAP to send, receive, and organize messages.
The Application Layer interacts closely with the Presentation and Session Layers to provide complete end-to-end services. While the Presentation Layer handles data translation and formatting, and the Session Layer manages communication sessions, the Application Layer focuses on making network services accessible and usable to end users. This layer encompasses a wide variety of protocols and services, from web and email to file transfer, remote login, and messaging, ensuring that network functionality translates into practical, user-facing applications.
Hypertext Transfer Protocol (HTTP)
Hypertext Transfer Protocol (HTTP) is a TCP/IP-based protocol that enables communication between a client, such as a web browser, and a web server. It defines the rules for requesting and delivering resources like HTML pages, images, videos, and other web content over the internet
HTTP operates as a stateless protocol, meaning each request from a client to a server is independent. However, extensions like cookies and sessions can maintain state across multiple interactions. By standardizing communication between clients and servers, HTTP enables users to access and navigate websites seamlessly, making it the foundation of data exchange on the World Wide Web.
Some HTTP Headers
Host: Target virtual host to use (HOST:PORT)
Server: Target server that handled the request
User-Agent: Software/Browser that is making the request
Some HTTP request methods
GET: Read data
POST: Insert data
HEAD: Return metadata about the target
Some HTTP Response Status Codes
200: Request has succeeded
404: Server cannot find the requested resource
500: Internal server error
If you want to get a file named test.html from qeeqbox.com, your HTTP request will be something like this
GET /test.html HTTP/1.1 Host: www.qeeqboox.com
If the server does have the requested file, the HTTP response will be
HTTP/1.1 200 OK Content-Length: 12 Content-Type: text/plain; charset=utf-8
Hello World!
If the file does not exist, the HTTP response will be
HTTP/1.1 404 Content-Length: 0
Uniform Resource Locator (URL)
A Uniform Resource Locator (URL) is a standardized and unique identifier used to locate and access resources on the internet, such as web pages, files, or services. It provides the necessary information for a client, like a web browser, to retrieve a resource from a specific server.
Protocol: A set of rules that define how content is transferred between the web server and browser
Sub Domain: An extension to a domain name to separate a website section
Root Domain: A website’s main or primary domain
Top Level Domain: An identifier that’s used to categorize the domain
Sub Directory: A directory that exists inside another directory
A process is an instance of a running application on a computer or device. It represents the program in action, including its code, current activities, memory allocation, and system resources it uses while executing. A single application can create multiple processes simultaneously, allowing different parts of the program to run independently or enabling multiple users to use the same application at once.
The operating system manages processes by allocating resources, scheduling execution, and isolating each process to prevent interference. This ensures that applications run efficiently and securely.
Foreground: Requires user to interact with it
Background: Does not require users to interact with it
Services
A service is a type of process that runs continuously in the background without terminating, providing ongoing functionality to the operating system or other applications. Unlike regular processes that start and stop with user interaction, services are designed to operate independently. They typically start automatically when the system boots and run until it shuts down.
Examples include web server services, database services, and print spoolers. These services handle requests, manage resources, or deliver functionality continuously. By operating persistently, services ensure that essential system functions and networked applications remain available and responsive at all times.
Application
An application is a software program designed to perform specific tasks or functions for users or other systems. It provides a user-friendly interface or automated processes that allow individuals or devices to accomplish objectives such as word processing, web browsing, data analysis, gaming, or communication.
Applications can range from simple utilities to complex software suites and rely on underlying system resources, such as the operating system and network services, to function effectively. By translating user inputs into actions and delivering outputs in a usable form, applications bridge the gap between technical systems and practical, everyday tasks.
Web Application
A web application is a software program that runs on a web server and is accessed by users through a web browser or network client over the internet or an internal network. Unlike traditional desktop applications, web applications do not require local installation and can provide interactive functionality such as online shopping, email services, social media platforms, or cloud-based productivity tools.
Web applications rely on web technologies like HTML, CSS, JavaScript, and server-side programming languages to process user input, communicate with databases, and deliver dynamic content. By operating over a network, web applications allow users to access services from anywhere, on various devices, while centralizing maintenance and updates on the server side.
Cyberattacks
Cross-Site Scripting
A threat actor aims to execute malicious actions on the victim’s website (It’s a client-side code injection attack)
Reflected Cross-Site Scripting
A threat actor injects malicious content into web pages or web applications. The content will be reflected in the response and executed in the victim’s browser
Dom-Based Cross-Site Scripting
A threat actor injects malicious content into web pages or web applications. The content is not reflected in the response and is executed in the victim’s browser
Stored Cross-Site Scripting
A threat actor injects malicious content into a vulnerable server. The content is retrieved by users and then execute
Cross-site request forgery
A threat actor may trick an authenticated or trusted victim into transmitting unauthorized actions on their behalf
A threat actor crafts an exploit URL for a fund transfer and sends it to an authenticated user
Denial-of-service (DoS)
A threat actor makes a target device\resource unavailable by overloading it using a device
A threat actor uses one device to overload XYZ LLC’s website (This was common in the old days, but nowadays it often does not work )
Distributed Denial of Service (DDoS)
A threat actor makes a target device\resource unavailable by flooding using multiple devices
A threat actor uses hundreds of infected devices to flood XYZ LLC’s website
PCAP Example
The client requested web content from the server over an insecure protocol called HTTP, the server responded with the web content, the client received the web content and got rendered by the client’s web browser. Insecure protocols can be intercepted, and the data carried in them can be modified
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
The Presentation Layer, which is Layer 6 of the OSI model, translates data between the application layer and the network transmission format. This ensures that data sent from one device can be correctly interpreted by another, even if they use different data representations. For example, it handles conversions between character encodings such as ASCII and EBCDIC, translates between different data structures, and converts multimedia formats such as audio or video streams.
By providing this translation function, the Presentation Layer enables applications on heterogeneous systems to communicate effectively.
In addition to data translation, the Presentation Layer is responsible for data encryption and compression. Encryption transforms data into a secure format to protect it during transmission, while compression reduces data size to improve efficiency and save bandwidth.
These functions ensure that data is interpretable, secure, and optimized for network transport. By handling these tasks independently of the application layer, the Presentation Layer standardizes data handling and promotes interoperability between different software and hardware systems.
Although conceptually important, the Presentation Layer is often not explicitly implemented in modern network protocol stacks. Many of its functions, such as encryption, compression, and data formatting, are integrated into the application layer or handled by specific libraries and frameworks. This is why some protocol stacks omit a distinct Presentation Layer, but the responsibilities it defines remain essential for consistent, secure, and interpretable data exchange.
The optional functions of the Presentation Layer include:
Encryption: Converting plaintext to ciphertext using a secret key
Decryption: Converting ciphertext back to plaintext using the same secret key
Compression: Reducing the number of symbols required to represent data
Decompression: Restoring compressed data to its original form
Formatting: Converting data into a standardized format for easy transmission
GNU ZIP (GZIP)
GNU ZIP (GZIP) is a widely used compression technology designed to reduce file size for efficient storage and transfer over networks, especially the internet. It uses the DEFLATE algorithm, which combines LZ77 compression and Huffman coding to achieve high compression ratios while maintaining reasonable processing speed.
GZIP files are easily recognizable by their magic header 1F 8B, which identifies the format and allows software to interpret and decompress the data correctly. Commonly used in web servers, APIs, and data archival, GZIP helps reduce bandwidth usage and speeds up data transmission, making it a key tool for improving network efficiency and performance.
The client requested web content from the server and indicated that it accepts GZIP content, the server responds with content that is compressed in GZIP, the client receives the GZIP and gets handled in the presentation layer
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
Wireshark decompresses the content (The web browser does that as well in the background, and there will be a tab at the bottom that has the decompressed content)
The Session Layer, Layer 5 of the OSI model, manages communication sessions between networked devices. A session is a logical channel that enables two nodes to exchange data in an organized manner. This layer ensures reliable communication by controlling when conversations start and end, maintaining context for accurate data interpretation.
Beyond opening and closing sessions, the Session Layer provides synchronization and checkpointing mechanisms. It inserts markers in data streams so interrupted sessions can resume from the last checkpoint instead of restarting. This is particularly beneficial for long-running processes such as file transfers, database queries, or video streaming, as it enhances efficiency and reliability by reducing retransmissions.
While many modern protocols integrate session management into the Transport or Application layers, the Session Layer conceptually separates these responsibilities. It also interacts with authentication and security mechanisms to control access, ensuring only authorized applications or users can communicate. By handling these tasks, the Session Layer establishes a framework for reliable, organized, and stateful communication between devices.
Socket
A socket is a software interface that enables processes or applications to communicate with the Transport Layer of a network stack. It serves as an endpoint for sending and receiving data, providing a standardized way for programs to establish connections, transmit information, and interact with network services.
Each socket is uniquely identified by a combination of an IP address and a port number, defining the communication channel between two devices. Using sockets, applications can leverage transport protocols like TCP or UDP to exchange data reliably or quickly, depending on the protocol. This approach allows applications to avoid managing low-level details such as packet transmission, routing, and error handling directly.
Active Socket
The client uses an active socket to initiate a TCP connection. The process involves:
Create a socket
Connect to a server
nc # Netcat, a networking utility used to read/write data over TCP or UDP 192.168.1.1 # Target IP address (usually a local network device like a router or server) 1234 # Target port number to connect to on the remote system
(Client) nc 192.168.1.1 1234
Passive Socket
The server uses a passive socket to wait for incoming TCP connections. The process involves:
Create a socket
Bind IP and Port
Listen to connections
Accept a connection
nc # Netcat, networking utility for reading/writing data over TCP or UDP -l # Listen mode, wait for an incoming connection instead of initiating one 1234 # Local port number to listen on
(Server) nc -l 1234
Authentication
Authentication verifies that a claimed identity is valid by ensuring the person, device, or system is who or what it claims to be. This serves as a critical security measure, preventing unauthorized access to sensitive data, applications, or systems.
Authentication can use various methods, including knowledge-based credentials (such as passwords or PINs), possession-based credentials (such as security tokens or smart cards), and inherent characteristics (such as fingerprints, facial recognition, or iris scans). By accurately verifying identities, authentication protects resources and establishes trust between users, devices, and systems in digital environments.
Authorization
Authorization determines whether a verified user, device, or system has the necessary permissions to access a resource or perform a specific action. After authentication confirms the identity, authorization enforces rules and policies to control what the entity can do, such as reading files, executing commands, or accessing certain network services.
This process is managed through methods such as access control lists, role-based access controls, and policy-based systems. Effective authorization ensures that even authenticated users are restricted to only permitted operations, protecting sensitive data, maintaining system integrity, and preventing unauthorized actions in digital environments.
Cyberattacks
Session Hijacking: A threat actor accesses the user’s account using a stolen or leaked valid (existing) session identifier
Session Fixation: A threat actor may trick a user into using a known session identifier to log in. after logging in, the session identifier is used to gain access to the user’s account.
Session Replay: A threat actor may re-use a stolen or leaked session identifier to access the user’s account
PCAP Example
The client requested web content from the server, the client created a session for handling the connection.
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
The Transport Layer is the fourth layer in the OSI model and ensures reliable and efficient data transmission between network nodes. Unlike lower layers that focus on moving raw data between devices, the Transport Layer manages communication between applications. It breaks large data streams into smaller segments for transmission and reassembles them at the receiving end to ensure completeness and correct order.
This layer handles flow control to prevent a fast sender from overwhelming a slower receiver and provides error detection and correction to maintain data integrity.
Two main protocols operate at this layer: Transmission Control Protocol (TCP) and User Datagram Protocol (UDP). TCP is connection-oriented, establishing a reliable session that guarantees delivery and ensures segments arrive in sequence. UDP, on the other hand, is connectionless and prioritizes speed over reliability by sending data without confirming receipt. This makes UDP suitable for applications such as video streaming or online gaming, where low latency is crucial.
Both protocols use port numbers to direct data to the correct application or process on source and destination devices. Port numbers allow multiple applications on the same device to communicate simultaneously without interference, a process called multiplexing.
By providing segmentation, error detection, flow control, and multiplexing, the Transport Layer enables seamless end-to-end communication between applications across diverse, complex networks.
Transmission Control Protocol (TCP)
Transmission Control Protocol (TCP) is a connection-oriented protocol that ensures reliable data transmission between processes on different devices over a network. Before any data transfer occurs, TCP establishes a connection using a three-way handshake to synchronize both the sender and receiver and ensure they are ready to communicate.
Once the connection is established, TCP divides the data into segments for transmission. It verifies delivery by receiving acknowledgments from the receiving device. If any segment is lost or corrupted during transmission, TCP automatically retransmits it to ensure complete and accurate data delivery.
This reliability makes TCP ideal for applications where data integrity and order are critical, such as web browsing, email, and file transfers.
Pros
Reliable
Error checking and recovery
Cons
Slow
Resource intensive
Uses
File sharing
Downloading
Flags
SYN: Starts a connection (It’s set at the beginning of TCP connection)
ACK: Confirms that data or initiation request has been received
RST: Aborts the connection immediately
FIN: Aborts the connection gracefully
PSH: Pushes the data to the application as soon as possible (No intermediate buffering)
URG: Prioritizes the data (This flag is obsolete)
User Datagram Protocol (UDP)
User Datagram Protocol (UDP) is a connectionless, message-oriented protocol that allows processes to send data over a network without establishing a prior connection or verifying delivery. Unlike TCP, UDP does not provide mechanisms for sequencing, acknowledgment, or retransmission. This means data packets may arrive out of order, be duplicated, or even be lost without notice.
This lightweight approach reduces overhead and latency, making UDP ideal for applications that require fast, real-time communication. Such applications include video streaming, online gaming, voice over IP (VoIP), and broadcasting, where speed and efficiency are prioritized over guaranteed delivery.
Pros
Fast
Simple
Cons
Does not have any error recovery
Uses
Video streaming
Real-time services
Flags
None
*Note, UDP does have error checking but doesn’t have any error-recovery
Logical Ports
Logical ports are virtual connection points within an operating system that facilitate the sending and receiving of data over a network. Each port is identified by a 16-bit number ranging from 0 to 65,535, allowing multiple services to operate simultaneously on the same device without conflict.
Ports numbered below 1024 are known as privileged or well-known ports. Running services on these ports typically requires elevated system privileges, such as administrative rights, to ensure the security and proper management of critical services like web, email, or FTP servers.
The assignment and use of these ports can vary slightly depending on the operating system. Still, in all cases, logical ports provide a structured way to direct network traffic to the correct application or process.
Common Used Ports
File Transfer Protocol (ftp/21)
Secure Shell Protocol (ssh/22)
Teletype Network (telnet/23)
Simple Mail Transfer Protocol (SMTP/25)
Domain Name System Protocol (DNS/53)
Hypertext Transfer Protocol (http/80)
Hypertext Transfer Protocol Secure (https/443)
Microsoft Directory Services (microsoft-ds/445)
Remote Desktop Protocol (ms-wbt-server/3389
Viewer Remote Desktop (vnc/5900)
Enumerate Ports (Locally)
Enumerating ports locally involves identifying which ports are currently in use by services and applications on a computer. This can be done using commands such as netstat or lsof, which display all active and listening ports along with the associated processes.
By running these commands, administrators can monitor network activity, troubleshoot connectivity issues, and verify that services are operating on the intended ports. For example, if you run a custom web server, you might observe it actively listening on port 80, the standard port for HTTP traffic, confirming that the service is properly bound and ready to receive incoming connections.
This local enumeration is essential for network management, security auditing, and ensuring proper service configuration.
Enumerating ports on a remote host involves discovering which network services are reachable from outside the target and identifying the ports they listen on. Common techniques include TCP and UDP scanning (e.g., SYN/half-open or full-connect scans), service and version detection (banner grabbing), and targeted probes to identify specific application behavior. These tasks are often performed using tools like Nmap or Masscan for legitimate inventorying and threat hunting.
This activity, described in the MITRE ATT&CK® Reconnaissance matrix as Network Service Discovery, helps defenders build asset inventories and prioritize patching, while attackers use the same information to plan exploitation. The results typically inform follow-up actions such as vulnerability assessment or access control changes.
PCAP Example
The web server is listening on port 80. The client can connect to this web server using the network adapter IP, but they do not need to specify port 80 in the web browser because it uses the HTTP protocol. If the web server port is 6789, the client can do http://<Network_Adapter_IP>:6789
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
The Network Layer is the third layer in the OSI (Open Systems Interconnection) model, responsible for enabling communication between devices on different networks. Unlike the Data Link Layer, which handles data transfer within a local network, the Network Layer ensures that data can travel across multiple interconnected networks to reach its intended destination. It abstracts the physical and logical complexities of underlying networks, enabling devices to communicate even when separated by routers or switches. The layer packages data into units called packets and adds logical addressing information (typically IP) to facilitate accurate delivery.
One primary function is routing, which determines the most efficient path for data from the source to the destination across one or more networks. Routers operate at this layer, examining destination IP addresses and using routing tables and protocols like OSPF or BGP to forward packets.
The Network Layer also handles fragmentation, breaking down large packets into smaller ones when required by the network’s maximum transmission unit (MTU), and reassembling them at the receiving end to ensure data integrity.
Additionally, the Network Layer plays a crucial role in error handling, congestion control, and logical addressing. It provides unique IP addresses to devices and manages packet traversal across networks, enabling efficient and reliable operation of complex topologies. The layer supports important network services, such as Quality of Service (QoS), which prioritizes certain types of traffic, and security features, such as IP filtering and access control.
Overall, the Network Layer forms the backbone of internetwork communication, ensuring seamless data movement between devices regardless of their physical or geographical location.
Internet Protocol (IP)
The Internet Protocol (IP) is a fundamental set of rules that govern how data is addressed, routed, and transmitted across interconnected networks, enabling communication and information exchange over the internet. IP assigns unique logical addresses, known as IP addresses, to devices, allowing each device to be identified and located within a network.
When data is sent, it is broken into packets, each containing source and destination IP addresses. These addresses guide packets through multiple networks and intermediate devices, such as routers, to reach their intended destinations. IP defines how packets are formatted, addressed, and handled during transmission, ensuring reliable traversal of complex network paths.
By providing a standardized method for addressing and routing, IP forms the backbone of internet communication and underpins virtually all modern networking protocols and services.
Internet Protocol Address V4 (IPv4)
IPv4 is a network address used to identify and locate devices on a network uniquely. It uses a 32-bit addressing system, allowing approximately 4.3 billion unique addresses. These addresses are typically represented in dotted-decimal notation, consisting of four octets separated by periods (e.g., 192.168.1.1).
IPv4 addresses are essential for routing data packets between different devices and networks, ensuring that information is delivered to the correct destination.
Binary
A numbering scheme that expressed in the base-2 numeral system (0 or 1)
11000000.10101000.00000001.00000001
Decimal
A numbering scheme that expressed in the base-10 system (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
192.168.1.1
IPv4 Addresses Classification
Public addresses
Used for external communication (access the Internet)
Private addresses
Used for internal communication (access resources in a local network)
IPv4 Addresses Classes
Class A
1.0.0.1 to 126.255.255.254
Networks: 126
Host per 1 a networks: 16,777,214
Subnet Mask: 255.0.0.0
Private Range
10.0.0.0 to 10.255.255.255
Used for very large networks
Class B
128.1.0.1 to 191.255.255.254
Networks: 16,382
Host per 1 a networks: 65,534
Subnet Mask: 255.255.0.0
Private Range
172.16.0.0 to 172.31.255.255
169.254.0.0 to 169.254.255.255
Automatic Private IP Addressing (APIPA)
A device will assign itself an IP address within that range if Dynamic Host Configuration Protocol (DHCP) does not work or failed
Used for small networks
Class C
192.0.1.1 to 223.255.254.254
Networks: 2,097,150
Host per 1 a networks: 254
Subnet Mask: 255.255.255.0
Private Range
192.168.0.0 to 192.168.255.255
Used for very small-sized network
Class D
224.0.0.0 to 239.255.255.255
Reserved for multicast groups.
Class E
240.0.0.0 to 254.255.255.254
Research/Reserved/Experimental
Note: Class A also has 127.0.0.0 to 127.255.255.255 are reserved for loopback and diagnostic (Those addresses cannot be used)
Subnet
A subnet, or subnetwork, divides a larger network into smaller, more manageable segments to improve performance, security, and organization. Each subnet is a distinct logical network with its own range of IP addresses, allowing devices within the subnet to communicate efficiently while controlling traffic flow between different subnets.
Subnetting reduces network congestion by limiting broadcast traffic to each segment, making it easier for administrators to implement policies, manage resources, and isolate issues. It also enhances security by segmenting sensitive areas, controlling access, and minimizing exposure of critical devices to the entire network. Overall, subnets provide flexibility and scalability, enabling large networks to function smoothly while maintaining structure and control.
255.0.0.0 – /8 – 1 network – 16,777,214 hosts in the network
255.128.0.0 – /9 – 2 subnets – 8,388,606 hosts in each network
255.192.0.0 – /10 – 4 subnets – 4,194,302 hosts in each network
255.224.0.0 – /11 – 8 subnets – 2,097,150 hosts in each network
255.240.0.0 – /12 – 16 subnets – 1,048,574 hosts in each network
255.248.0.0 – /13 – 32 subnets – 524,286 hosts in each network
255.252.0.0 – /14 – 64 subnets – 262,142 hosts in each network
255.254.0.0 – /15 – 128 subnets – 131,070 hosts in each network
255.255.0.0 – /16 – 256 subnets – 65,534 hosts in each network
255.255.128.0 – /17 – 512 subnets – 32,766 hosts in each network
255.255.192.0 – /18 – 1,024 subnets – 16,384 hosts in each network
255.255.224.0 – /19 – 2,048 subnets – 8,190 hosts in each network
255.255.240.0 – /20 – 4,096 subnets – 4,094 hosts in each network
255.255.248.0 – /21 – 8,192 subnets – 2,046 hosts in each network
255.255.252.0 – /22 – 16,384 subnets – 1,022 hosts in each network
255.255.254.0 – /23 – 32,768 subnets – 510 hosts in each network
255.255.255.0 – /24 – 65,536 subnets – 254 hosts in each network
255.255.255.128 – /25 – 131,072 subnets – 126 hosts in each network
255.255.255.192 – /26 – 262,144 subnets – 62 hosts in each network
255.255.255.224 – /27 – 524,288 subnets – 30 hosts in each network
255.255.255.240 – /28 – 1,048,576 subnets – 14 hosts in each network
255.255.255.248 – /29 – 2,097,152 subnets – 6 hosts in each network
255.255.255.252 – /30 – 4,194,304 subnets – 2 hosts in each network
Internet Protocol Address V4 (IPv4) Example
192.168.1.0/25, the first node starts at 0, and the last one is 126
192.168.1.0
0 is the network address (network identifier)
192.168.1.2
A node on the network
192.168.1.126
Last node on the network
192.168.1.127
Broadcast address (All nodes in that subnet respond to it)
Router
A router is a physical or virtual networking device that connects multiple computer networks and forwards data packets between them. Operating at the Network Layer of the OSI model, routers use IP addresses to determine the best path for each packet to reach its destination. They maintain a routing table containing information about network paths and routes, enabling them to make intelligent forwarding decisions based on factors such as network topology, congestion, and cost.
Routers enable communication between different networks, such as connecting a home network to the internet. They also provide important services, such as network traffic management, segmentation, and security, through features like firewalls and access control lists. By directing data efficiently and ensuring it reaches the correct destination, routers are a critical component of modern network infrastructure.
VLAN Interconnection
VLAN interconnection is a networking technique that enables communication and routing between multiple Virtual Local Area Networks (VLANs) that are otherwise logically isolated from each other. While VLANs segment a physical network into separate virtual networks to improve security, reduce broadcast traffic, and organize devices, devices on different VLANs cannot communicate directly without a method for interconnection.
This is achieved through routing, either with a Layer 3 switch that supports inter-VLAN routing or a router configured to handle traffic between VLANs. VLAN interconnection allows organizations to maintain the benefits of network segmentation while enabling controlled data exchange between departments, services, or applications. This ensures both efficiency and security in complex network environments.
VLAN Interconnection (Router on stick – Trunk port)
VLAN interconnection using the “Router on a Stick” method is a networking technique that allows routing between multiple VLANs through a single physical router interface. In this setup, a trunk port on the router carries traffic for all VLANs. Each packet is tagged to indicate its VLAN membership using a protocol such as IEEE 802.1Q.
The router inspects the VLAN tag, determines the destination VLAN, and routes the traffic accordingly. This enables devices on different VLANs to communicate while maintaining logical segmentation.
This approach is cost-effective because it eliminates the need for multiple physical interfaces on the router, making it a popular solution in small-to medium-sized networks where efficient hardware use and simplified configuration are priorities.
Cyberattacks
Man in the Middle (MITM)
A threat actor intercepts and relays messages between 2 targets
A threat utilizing the victim’s MAC – This happens after the ARP poising, and the threat actor can carry the end goal of the cyberattack like a man in the middle (T1557.002 Adversary-in-the-Middle: ARP Cache Poisoning)
DNS Spoofing
When a victim gets directed to a malicious website (This happens after DNS poising)
PCAP Example
The web server here uses 0.0.0.0 IP; this is a placeholder that means listen to all, it accepts incoming connections from all network adapters (If this was 127.0.0.1, it would only be accessible to processes running on the device itself). A client can connect to this web server using the network adapter IP, in this case, the network adapter IP is 10.0.0.2 as shown in the Wireshark image
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
The Data Link Layer is the second layer in the OSI model. It enables reliable data transmission between two directly connected devices on the same network. This layer takes the raw bit-stream from the Physical Layer and organizes it into structured units called frames. These frames include not only the data being sent but also important control information, such as source and destination addresses, error-detection codes, and sequencing details. This ensures that data is properly packaged for accurate delivery and helps detect or correct transmission errors.
In addition to framing, the Data Link Layer manages data flow to prevent network congestion and collisions, especially in shared networks. It uses protocols such as Ethernet for wired networks and Wi-Fi for wireless networks to control access to the medium, coordinate transmissions, and ensure that only one device transmits at a time. The layer also checks for errors using mechanisms such as cyclic redundancy checks (CRC), allowing the receiving device to identify corrupted frames and request retransmission if needed.
The Data Link Layer is divided into two sublayers: the Logical Link Control (LLC) sublayer, which handles communication between higher layers and provides error and flow control; and the Media Access Control (MAC) sublayer, which manages how devices on the same network segment access the shared medium. Together, these functions ensure reliable and efficient communication between nodes on the same network, serving as a critical bridge between the raw transmission capabilities of the Physical Layer and the logical communication handled by higher layers, such as the Network Layer.
Ethernet Protocol
A set of rules governing the communication and exchange of data between two nodes on the same network
Framing: a technique that divides a data stream into smaller parts
Physical addressing: a technique that adds (encapsulates) the source and destination’s MAC address to each frame
Error control: a technique that detects and corrects the error (If possible)
Flow controls: a technique that synchronizes the receiving and sending speed between nodes
Access control: a technique that allows multiple devices to use the same communication channel
Two sub-layers
Logical Link Control
Multiplexing
A technique that combines multiple data streams over a single medium
De-multiplexing
A technique that reverts one input data signal back to multiple data streams
Flow control
A technique that manages how much data it can transmit between the sender and receiver
Error detection
A technique that checks whether the receiver has received correct data or not
Media Access Control and its primary purpose is framing
Bridge
A bridge is a networking device that connects and filters traffic between two separate network segments, usually with two ports. It operates at the Data Link Layer of the OSI model and uses MAC (Media Access Control) addresses to make forwarding decisions.
When a data packet arrives at a port, the bridge examines the destination MAC address to determine whether to forward it to the other port or keep it within the same segment. This helps reduce unnecessary traffic. Bridges maintain a MAC address table, also known as a forwarding table, which maps devices to their respective ports. This enables efficient, intelligent traffic management.
By segmenting networks and controlling data flow, bridges improve overall network performance, reduce collisions, and better organize network resources.
L2 Switch
A Layer 2 (L2) switch is a network device that connects multiple devices within the same local area network (LAN). It operates at the Data Link Layer of the OSI model. Unlike a bridge, which typically has only two ports, an L2 switch has multiple ports, allowing it to handle traffic between many devices simultaneously.
An L2 switch uses MAC (Media Access Control) addresses to determine the destination of incoming data packets and stores this information in a MAC address table (or lookup table). This allows the switch to forward packets only to the appropriate port, reducing unnecessary network congestion and collisions. By intelligently directing traffic, an L2 switch improves overall network efficiency and provides a scalable way to expand a LAN while maintaining high-speed and reliable communication between connected devices.
Physical Segmentation
Physical segmentation involves dividing a network into separate subnets using hardware devices like switches, routers, or bridges. This approach physically isolates different parts of the network, improving traffic management, enhancing security, and reducing congestion and collisions within each subnet.
By creating distinct segments, network administrators can control data flow more effectively, implement specific policies for each segment, and limit the impact of network failures or security breaches to only the affected area. Physical segmentation is commonly used in enterprise networks, data centers, and environments where performance and security are critical, as it provides a clear and effective way to organize and optimize network infrastructure.
Logical Segmentation
Logical segmentation is the process of dividing a network into separate subnets or virtual networks using software-based configurations rather than physical hardware. This is typically achieved through technologies such as VLANs (Virtual Local Area Networks) and subnetting, which allow devices on the same physical network to be grouped into isolated logical networks.
Logical segmentation improves network management by enabling administrators to control traffic flow, apply security policies, and optimize performance without reconfiguring or adding new hardware. It also enhances scalability and flexibility, allowing networks to adapt to changing organizational needs and support multiple departments or applications. By containing broadcast traffic within each logical subnet, logical segmentation reduces congestion and improves overall network efficiency.
Media Access Control Address (MAC Address)
A Media Access Control (MAC) address is a unique 12-digit hexadecimal identifier assigned to a network interface card (NIC) or other network hardware. It serves as a physical address that identifies a device on a local network. The MAC address is hardcoded by the manufacturer and used by network devices, such as switches and bridges, to ensure the accurate delivery of data frames within the network.
The first half of the MAC address typically identifies the manufacturer, allowing for vendor identification, while the second half is a unique identifier for the specific device. MAC addresses are essential for network communication, traffic management, and security functions, including device authentication and network access control. They play a foundational role in both wired and wireless networking environments.
Examples
00:11:22:AA:CC:DD
0011.22AA.CCDD
00-11-22-AA-CC-DD
Cyberattacks
ARP Poisoning
A cyberattack where a threat actor sends malicious ARP over a local area network (LAN) to link a threat actor’s MAC address with a legitimate device IP on the network (In case of man in the middle, the packet is sent to the default gateway and the victim) (T1557 Adversary-in-the-Middle: ARP Cache Poisoning)
Spanning Tree Attack
A threat actor plugs a rouge L2 switch and manipulates other devices’ priority value; all traffic goes to the threat actor device ()
VLAN Hopping
Switch Spoofing
A threat actor plugs a rouge L2 switch to a mis-configured network, the rouge L2 switch forms an unauthorized trunk connection and gains access to the VLAN
Double Tagging
A threat actor modifies the Ethernet frames tags, which allows packets to be sent through any VLAN
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
The Physical Layer is the lowest layer in the OSI (Open Systems Interconnection) model, defining physical connections between devices in a network. It handles raw binary data, or bit-streams, consisting of 1s and 0s without processing or decision-making.
This layer converts bits into signals for transmission over media such as copper cables, fiber-optic networks, or wireless networks. In electrical cables, bit representation is 1 for medium-high voltage and 0 for low voltage; in optical fibers, it is 1 for light pulses and 0 for their absence.
The Physical Layer also defines connector types, cable specifications, signal frequencies, transmission rates (bandwidth), and network topology. It ensures reliable data transmission between devices, forming the foundation for higher layers of the network model. Though it is unaware of the content being transmitted, its proper functioning is critical for overall performance and reliability.
Coaxial Cable
A coaxial cable is an electrical cable designed to transmit radio frequency (RF) signals with minimal loss and interference. It consists of a central copper conductor surrounded by an insulating layer, a metallic shield, and an outer protective jacket. The metallic shield protects the signal from electromagnetic interference, making coaxial cables ideal for applications like cable television, internet connections, and radio communications.
Coaxial cables can transmit high-frequency signals over long distances while maintaining signal integrity, and they are widely used in both residential and commercial networking environments.
Binary
Binary is a base-2 number system using only two values: 1 and 0. It represents all forms of data and instructions in digital systems. Each digit in a binary number, called a bit, is the fundamental unit of information in computing and digital communications.
The simplicity of binary makes it ideal for electronic devices, as circuits can easily distinguish between two states-ON (1) and OFF (0), or high and low voltage. By combining multiple bits, complex data, instructions, and multimedia content can be efficiently encoded, stored, and transmitted, forming the foundation of modern computing and digital communication technologies.
A bit, short for binary digit, is the smallest unit of data in a computer and represents a single binary value: 0 or 1. Bits are the fundamental building blocks of all digital information, forming the basis for how computers store, process, and transmit data. By combining multiple bits, more complex units such as bytes, characters, and instructions can be represented.
Despite their simplicity, bits enable computers to perform a wide range of operations, from basic calculations to running sophisticated software, making them essential to the functioning of all digital systems.
1 On 0 Off
Bytes
A byte is a unit of digital information consisting of 8 bits and is commonly used to represent a single character, such as a letter, number, or symbol. For example, the letter "C" is represented in binary as 01000011, with each bit contributing to the character’s value.
While one byte is sufficient for most standard ASCII characters, more complex characters (such as those from non-Latin alphabets, emojis, or special symbols) may require multiple bytes, as seen in encoding schemes like UTF-8. Bytes serve as a fundamental unit of memory and storage in computers, allowing data to be organized, processed, and transmitted efficiently across digital systems.
00110001 is equal to 1 01110100 01100101 01110011 01110100 is equal to test
Medium types
Cables
The signals are electrical pulses
Fiber
The signals are light pluses
Wireless
The signals are electromagnetic waves
Some Functions
Transmission mode
Simplex: A unidirectional communication where the sender sends data, and the receiver receives data
Half duplex: A bidirectional communication where the sender can send or receive data but only in one direction at a time
Full duplex: A bidirectional communication simultaneously where the sender can send and receive data at a time
Physical typologies
Point-to-point: Two nodes are connected with a dedicated link
Bus: Nodes are connected using a single cable
Ring: Each node is connected (Point-to-point) to another on each side, the last one is connected to the first one (Data travels in a circle)
Mesh: Nodes are connected (Point-to-point) with all the other nodes
Star: Nodes are connected to a central node (Each node communicates indirectly through the central node)
Latency
Latency is the time it takes for data to travel from its source to its destination across a network or system. It is a critical measure of network performance and responsiveness, influenced by factors such as physical distance, the quality of the transmission medium, the number of network hops, and processing time at intermediate devices.
Low latency is essential for real-time applications such as video conferencing, online gaming, and financial trading, where even small delays can significantly degrade performance and user experience. High latency can cause lag, slow data transfers, and reduced efficiency, making it a key consideration in network design, optimization, and
Wired vs. Wireless
Wired
Faster data transfer: Speed is consistent
Has Lower latency: Data travels faster, which means low latency by default
Hard to deploy: Connected devices usually do not move (Desktop)
More secure (Data does not need to be encrypted?): Data can be accessed by devices that physically attached to that network
Wireless
Slow data transfer
Speed is not consistent
Has higher latency
Distance
Data is susceptible to noise (Re-send)
Data is encrypted and needs some time to be decrypted
Easy to deploy
Connected devices can be moved (A smart phone)
Less secure (Data needs to be encrypted?)
Data travels through the air and can be intercepted
Examples
Network interface cards (NIC): Provides a physical connection to a network
Modem: Converts the signal type from one type to another type
Hubs: Connects multiple devices in the network (A node that broadcasts data to all connected devices)
Cables: A wire or a set of wires that connects one device with another
Jamming: A threat actor may send interfering signals to the target (T1464 Network Denial of Service)
Tampering: A threat actor may cut cables, unplug devices, etc..
Tapping: A threat actor may plug a device that monitors the network traffic (T1200 Hardware Additions)
PCAP Example
In the PCAP file, you can get an overview of the data by clicking on the entry, then Frame 1 (In this case, it’s the metadata gathered about the data), which includes detailed info about the data that are transmitted or received, some of the info, like interface id, name, and description, are not part of the data, but they are in Wireshark for analysis and troubleshooting network problems
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
A computer network connects devices like computers, servers, routers, and other hardware to share data, resources, and services. These networks create pathways for information to flow between devices, enabling activities such as sending emails, browsing the web, streaming video, or participating in video calls.
Computer networks can vary in size and complexity. Local Area Networks (LANs) connect devices within small areas like homes, offices, or schools. Wide Area Networks (WANs) cover larger geographic regions, linking offices, data centers, or even countries. The internet is the largest global network, connecting billions of devices worldwide.
Networks are essential for our daily digital lives, supporting personal communication, business operations, online education, healthcare systems, financial transactions, cloud computing, and many other services. They rely on protocols, hardware, and security measures to ensure data is transmitted efficiently, reliably, and safely between devices.
Network Security
Network security refers to methods, technologies, and procedures used to protect computer networks and their resources from unauthorized access, misuse, modification, or disruption. It ensures sensitive information (such as personal data, financial records, or confidential business information) remains safe while maintaining the availability and integrity of network services
Network security covers a wide range of practices including:
Access Control: Restricting who can connect to the network or access specific resources using passwords, authentication systems, or multi-factor authentication (MFA).
Firewalls: Devices or software that monitor and filter incoming and outgoing traffic to block malicious activity.
Intrusion Detection and Prevention: Systems that detect unusual or suspicious activity and respond to potential threats.
Encryption: Protecting data in transit by converting it into a format unreadable by unauthorized users.
Network Monitoring: Continuously observing network traffic and performance to identify potential security breaches or vulnerabilities.
Regular Updates and Patching: Ensuring network devices and software are up to date to protect against known vulnerabilities.
Effective network security not only prevents unauthorized access but also reduces the risk of data breaches, malware infections, and service disruptions, helping maintain trust, reliability, and operational continuity for individuals and organizations alike.
Protocols
In networking, a protocol is a formal set of rules and conventions that govern how devices communicate over a network. Protocols define data formatting, transmission, routing, and reception, ensuring information from one device can be correctly interpreted by another, even if they are from different manufacturers or run different software. They cover aspects like error detection, data compression, addressing, encryption, and session management, making communication reliable and secure.
Examples of common network protocols include:
HTTP/HTTPS: For web traffic
FTP (File Transfer Protocol): Transfers files between a client and server
SSH (Secure Shell Protocol): Enables secure communication between two computers
Telnet: Enables communication between two computers
SMTP (Simple Mail Transfer Protocol): Sends, receives, and relays emails
DNS (Domain Name System): Translates human-readable hostnames into IP addresses
TCP/IP (Transmission Control Protocol/Internet Protocol): For end-to-end communication
IMAP (Internet Message Access Protocol): Retrieves messages from email servers
HTTPS: Securely transports data between a client and web server
Microsoft Directory Services (Microsoft-DS): Used for file sharing over TCP/IP by SMB service
MySQL: Relational database management system
RDP (Remote Desktop Protocol, ms-wbt-server): Interacts with a desktop computer remotely
VNC (Viewer Remote Desktop): Interacts with a desktop computer remotely
By following standardized protocols, networks achieve interoperability, efficiency, and consistency, allowing diverse systems to work together seamlessly.
Open Systems Interconnection (OSI)
The Open Systems Interconnection (OSI) model is a standardized framework for understanding and implementing network communications. It consists of seven distinct layers, each defining specific functions and protocols to ensure successful data exchange between devices on a network. The layers, from bottom to top, are Physical, Data Link, Network, Transport, Session, Presentation, and Application.
The OSI model provides a structured approach to designing and troubleshooting networks by clearly separating different network functions, such as how data is physically transmitted, how devices are addressed and routed, how data integrity is ensured, and how applications access network services. Introduced in the 1980s based on ISO recommendations, the OSI model serves as a universal reference that promotes interoperability between hardware and software from different vendors, making it easier to design, manage, and maintain complex network systems.
Layers
Layer 7
Application
HTTP, HTTPS, FTP, SMTP
Host Layer
Layer 6
Presentation
ASCII, JPEG, GZIP
Host Layer
Layer 5
Session
Socket
Host Layer
Layer 4
Transport
TCP, UDP
Host Layer
Layer 3
Network
IPv4, IPv6, IPSec
Media Layer
Layer 2
Data Link
PPP, IEEE, L2TP, Ethernet
Media Layer
Layer 1
Physical
Cables, Wireless
Media Layer
OSI in Action – Browsing The Internet (Web Client)
Layer 7
Application
HTTP
the client uses a web browser to send http data
Layer 6
Presentation
GZIP
handles the data format and compresses it (If applicable)
Layer 5
Session
Socket
opens a session for communication between source and destination (Web Server)
Layer 4
Transport
TCP
data is segmented, and each segment will have the source and destination port number
Layer 3
Network
IPv4
converts segments into packets; each packet will have the source and destination IP address
Layer 2
Data Link
Ethernet
converts packets into frames; each frame will have the source and destination MAC address
Layer 1
Physical
Coax
converts frames into bit-stream and send the data over the physical medium
OSI in Action – Browsing The Internet (Web Server)
Layer 1
Physical
Coax
converts bit-stream into frames
Layer 2
Data Link
Ethernet
merges all frames into packets
Layer 3
Network
IPv4
converts packets into segments
Layer 4
Transport
TCP
converts segments into data
Layer 5
Session
Socket
data is kept
Layer 6
Presentation
GZIP
decompresses data and reverts the formatting
Layer 7
Application
HTTP
the destination receives the client http data
Python Web Server
Python has a built-in package called http.server that can be used as file server or a customized web server that handles HTTP(s) requests.
How to Run http.server (Default)
In the terminal, go to the directory that has the static content (files, images, etc..) and type python3 -m http.server, this serves the directory content to clients (Some threat actors utilize this method when they breach a network, Python is most likely running on the devices, so it’s used to move data in the breached network). After running the http.server it will show if it was successful or not, and the port that’s used
python3 # Python using version 3 -m # Tell Python to run a module as a script http.server # Start the built-in HTTP file server on port 8000 (default)
(RPi) python3 -m http.server Serving HTTP on :: port 8000 (http://[::]:8000/)
The output will change depending on the directory (folder) from which the server is started
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Directory listing for /</title> </head> <body> <h1>Directory listing for /</h1> <hr> <ul> <li><a href=".bash_history">.bash_history</a></li>
How to Run http.server (Customized)
The course content is built around a customized webserver that responds to HTTP GET requests, handles sessions/compressions, and logs requests. You may need to install a package called netifaces using pip3 install netifaces (In case you do not want to run the server or having issues with it, there is a Wireshark dump that was captured while interacting with the customized webserver, skip these steps)
pip3 # The Python 3 package installer (runs pip for Python 3.x) install # The command telling pip3 to install a package netifaces # The name of the package to install, provides access to network interface information (IP, MAC addresses)
(RPi) pip3 install netifaces
Then copy the following into a file (E.g. server.py)
from http.server import SimpleHTTPRequestHandler # Import the built-in HTTP request handler from socketserver import TCPServer # Import a basic TCP server implementation from io import BytesIO # Import BytesIO to handle bytes in memory (for gzip compression) from gzip import GzipFile # Import GzipFile to compress HTTP response from datetime import datetime # Import datetime to generate timestamps for logging from contextlib import suppress # Import suppress to prevent crashes
with suppress(Exception): # Try importing network interface details from netifaces import gateways, ifaddresses, AF_INET, AF_LINK # Network interface utilities print(“The default network interface is: “, gateways()[‘default’][AF_INET][1]) # Display default network interface name print(“The default network interface mac address is: “, ifaddresses(gateways()[‘default’][AF_INET][1])[AF_LINK]) # Display MAC address of the default network interface
class Server(SimpleHTTPRequestHandler): # Define a custom HTTP server
def do_GET(self): # Handle HTTP GET requests compressed = False # Track whether gzip compression is used content = b'<HTML><h1>Hello World!</h1></HTML>’ # HTTP response body (bytes)
if len(content) > 0: # Only attempt compression if content exists if ‘accept-encoding’ in self.headers: # Check if client sent Accept-Encoding header if ‘gzip’ in self.headers[‘accept-encoding’]: # Client supports gzip bytes_ = BytesIO() # Create an in-memory byte buffer with GzipFile(fileobj=bytes_, mode=’w’, compresslevel=5) as f: # Gzip wrapper f.write(content) # Compress the response body content = bytes_.getvalue() # Replace content with compressed bytes compressed = True # Mark response as compressed
self.send_response(200) # Send HTTP 200 OK status if compressed: self.send_header(‘content-encoding’, ‘gzip’) # Notify client of gzip encoding self.send_header(‘content-length’, len(content)) # Send content length header self.end_headers() # End HTTP headers self.wfile.write(content) # Write response body to client
TCPServer((‘0.0.0.0’, 80), Server).serve_forever() # Start server on all interfaces, port 80
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from io import BytesIO from gzip import GzipFile from datetime import datetime from contextlib import suppress
with suppress(Exception): from netifaces import gateways, ifaddresses, AF_INET, AF_LINK print("The default network interface is: ",gateways()['default'][AF_INET][1]) print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])
class Server(SimpleHTTPRequestHandler): def do_GET(self): compressed = False content = b'<HTML><h1>Hello World!</h1></HTML>' if len(content) > 0: if 'accept-encoding' in self.headers: if 'gzip' in self.headers['accept-encoding']: bytes_ = BytesIO() with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f: f.write(content) f.close() content = bytes_.getvalue() compressed = True self.send_response(200) if compressed: self.send_header('content-encoding', 'gzip') self.send_header('content-length', len(content)) self.end_headers() self.wfile.write(content)
Then run the file as Python script with elevated privileges, the reason why you need to elevate privileges because the customized webserver is using port 80 (Port below 1024 can be open only with elevated privileges, E.g. root)
sudo # Run the command with superuser (root) privileges python3 # Run the Python 3 interpreter server.py # The Python script file to execute (in this case, your HTTP server)
(RPi) sudo python3 server.py The default network interface is: eth0 The default network interface mac address is: [{'addr': 'bc:f2:b8:57:86:02'}]
You can either use a web browser or client to communicate with that server, the content URL in this case is http://127.0.0.1:80
curl # A command-line tool used to send requests and receive responses http://127.0.0.1:80 # Send an HTTP GET request to the local Python http.server running on port 80
(RPi) curl http://127.0.0.1:80
<HTML><h1>Hello World!</h1></HTML>
Packet Analyzer (Wireshark)
A tool or device for capturing and analyzing packets of data traveling in a communication channel. Click on open a capture file, then open the following http.pcapng file
Filter Bar – You can filter the traffic based on specific rules like IP, port, or protocol
Packets List – This shows the traffic as entries and you click on any of the entries for more details, or you can sort them by time, IP, etc..
Packet Details – When you click on an entry, the details of that entry will show up in this section
Packet bytes – You can review any packet bytes in this section, if you click on any byte, it will show the meaning of it in the Packet Details section (This is a very helpful feature)