Linux-Rootkit-Kernel-Modules-1

Let me give you a comprehensive guide on kernel module development, just like the exploitation writeup!


Part 1: Understanding Kernel Modules

1.1 What Are Kernel Modules?

Think of the Linux kernel as a smartphone operating system, and kernel modules as apps you can install.

┌─────────────────────────────────────────────┐
│         Userspace Applications              │
│  (bash, firefox, your programs)             │
└─────────────────────────────────────────────┘
                  ↕ System Calls
┌─────────────────────────────────────────────┐
│           Linux Kernel Core                 │
│  • Process Management                       │
│  • Memory Management                        │
│  • File Systems                             │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│        Kernel Modules (Loadable)            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │ USB      │  │ Graphics │  │  Your    │ │
│  │ Driver   │  │ Driver   │  │ Module   │ │
│  └──────────┘  └──────────┘  └──────────┘ │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│              Hardware                        │
│  (CPU, RAM, USB devices, GPU)               │
└─────────────────────────────────────────────┘

Kernel modules are pieces of code that can be:

  • Loaded into the kernel while it's running (no reboot needed)

  • Unloaded when no longer needed

  • Run with full kernel privileges (Ring 0)

1.2 Why Use Modules Instead of Built-in Code?

Without modules:

  • Every driver compiled into kernel

  • Kernel becomes huge (100+ MB)

  • Need to reboot for every change

  • Wasted memory for unused drivers

With modules:

  • Load only what you need

  • Kernel stays small (~10-20 MB)

  • Add/remove features on-the-fly

  • Easy testing and development

Real-world example: When you plug in a USB device, the kernel loads the appropriate module automatically. When you remove it, the module can be unloaded.

1.3 What Can Kernel Modules Do?

  • Device drivers: Control hardware (USB, graphics cards, network cards)

  • Filesystems: Add support for new filesystem types (ext4, NTFS, FAT32)

  • Network protocols: Implement new networking features

  • Security modules: Add security features (SELinux, AppArmor)

  • System monitoring: Watch system events

  • And yes... rootkits! (malicious modules that hide themselves)


Part 2: Your First Kernel Module - "Hello World"

2.1 The Simplest Possible Module

Let's create a module that just prints "Hello, Kernel!" when loaded and "Goodbye, Kernel!" when unloaded.

Create a file called hello.c:

2.2 Understanding Each Part

Header Files:

These are kernel headers, not standard C library headers. You can't use printf(), malloc(), or other libc functions in kernel code!

The __init Macro:

  • static: Function is private to this file

  • __init: Tells kernel this code runs once at load time, then can be freed from memory

  • Returns int: 0 for success, negative error code for failure

The __exit Macro:

  • __exit: This code runs once at unload time

  • Returns void: Exit functions don't return values

Registration Macros:

These macros tell the kernel which functions to call.

Module Metadata:

MODULE_LICENSE() is mandatory. Without it, the module won't load properly!

Common licenses:

  • "GPL" - GNU General Public License

  • "GPL v2" - GPL version 2

  • "Dual MIT/GPL" - Can be used under either license

  • "Proprietary" - Closed source (taints the kernel)

2.3 printk() - The Kernel's printf()

In userspace, you use printf(). In kernel space, you use printk().

Format:

Log Levels:

Examples:

Where does printk() output go?

Not to your terminal! It goes to the kernel log buffer. View it with:


Part 3: Compiling Kernel Modules - The Makefile

3.1 Why We Need a Special Makefile

You can't compile kernel modules with just gcc hello.c -o hello.ko. Kernel modules need:

  • Special compilation flags

  • Kernel headers

  • Symbol resolution

  • Proper linking

The kernel build system handles all this.

3.2 The Basic Makefile

Create a file called Makefile (exact name, capital M) in the same directory as hello.c:

3.3 Understanding the Makefile

Line 1: obj-m += hello.o

  • obj-m: List of modules to build

  • hello.o: Object file (will be compiled from hello.c)

  • The .o becomes .ko (kernel object) automatically

If you had multiple source files:

The 'all' target:

Let's break this down:

  • make -C <directory>: Change to that directory and run make

  • /lib/modules/$(shell uname -r)/build: Kernel build directory

    • $(shell uname -r): Current kernel version (e.g., 5.15.0-generic)

    • This directory contains kernel headers

  • M=$(PWD): Tell kernel build system where our module source is

  • modules: Target to build modules

The 'clean' target:

Same structure, but calls the clean target to remove build files.

3.4 Important Makefile Notes

Use TABS, not spaces!

Makefiles require actual TAB characters for indentation. If you copy-paste and it doesn't work, it's probably spaces instead of tabs.

Check if kernel headers are installed:


Part 4: Building and Loading Your Module

4.1 Compilation

Files created:

The important file: hello.ko - This is your loadable kernel module!

4.2 Checking Module Information

Before loading, you can inspect the module:

4.3 Loading the Module

Method 1: insmod (Insert Module)

This shows:

  • Module name: hello

  • Size: 16384 bytes

  • Used by: 0 other modules

Check kernel log:

Success! Your module is running in kernel space!

4.4 Listing Loaded Modules

4.5 Unloading the Module


Part 5: Common Issues and Troubleshooting

5.1 "Module not found" Error

Cause: Module compiled for different kernel version

Check:

Solution:

5.2 "Operation not permitted"

Possible causes:

  1. Secure Boot enabled - Disable in BIOS or sign your module

  2. Missing MODULE_LICENSE() - Add to your code

  3. Kernel lockdown mode - Check with cat /sys/kernel/security/lockdown

5.3 Module Won't Unload

Cause: Something is using your module

Debug:

Force unload (dangerous!):

5.4 Compilation Errors

Error: "linux/module.h: No such file or directory"

Error: "Makefile:2: *** missing separator. Stop."

  • You have spaces instead of TAB in Makefile

  • Re-type the indentation with TAB key


Part 6: Module Parameters

6.1 What Are Module Parameters?

Parameters let you customize module behavior at load time without recompiling.

Example: A network driver might take parameters for IP address, port, etc.

6.2 Adding Parameters

6.3 Using Parameters

Loading with default values:

Loading with custom values:

Viewing parameters:

Changing parameters (if writable):

6.4 Parameter Types

Permission values:

  • 0000: No one can read/write

  • 0444: Everyone can read, no one can write

  • 0644: Owner read/write, others read-only

  • 0666: Everyone read/write


Part 7: Debugging Kernel Modules

7.1 Using printk() for Debugging

Good debugging practices:

7.2 Controlling Log Verbosity

7.3 Dynamic Debug

For more control, use dynamic debugging:

Enable dynamic debug:

Common causes:

  • NULL pointer dereference: Accessing *ptr when ptr = NULL

  • Invalid memory access: Accessing freed memory or wrong address

  • Stack overflow: Too much recursion or huge local variables

How to avoid:


Part 8: Practical Example - A Counter Module

Let's build something more useful: a module that counts how many times it's been accessed.

8.1 The Code

8.2 Testing the Counter

8.3 What This Demonstrates

  • Creating /proc entries for user interaction

  • Handling read operations

  • Copying data to userspace safely (copy_to_user())

  • Maintaining state (the counter variable)

  • Proper cleanup in exit function


Part 9: Best Practices

9.1 Error Handling

Always check return values:

9.2 Resource Cleanup

Always clean up in reverse order:

9.3 Naming Conventions

Use prefixes to avoid conflicts:

9.4 Static vs. Global

Make things static unless they need to be exported:


Part 10: Common Commands Reference

10.1 Module Management

10.2 Debugging Commands

10.3 Build Commands

Last updated