Created
July 20, 2025 22:44
-
-
Save JasonTurley/f142d08800e1b10ab29a50772d056845 to your computer and use it in GitHub Desktop.
Linux kernel module crackme challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * crackme-1: a simple crackme CTF challenge as a kernel module! | |
| */ | |
| #include <linux/kernel.h> | |
| #include <linux/module.h> | |
| #include <linux/proc_fs.h> | |
| #include <linux/version.h> | |
| #include <linux/uaccess.h> | |
| #include <linux/string.h> // for strcmp | |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) | |
| #define HAVE_PROC_OPS | |
| #endif | |
| #define CHALLENGE_NAME "crackme-1" | |
| #define BUF_MAX_LEN 64 | |
| #define PASSWORD "59bcc3ad6775562f845953cf01624225" | |
| static struct proc_dir_entry *proc_file; | |
| static bool authorized = false; | |
| // Function definitions | |
| static ssize_t crackme_read(struct file* filp, char __user *buffer, size_t len, loff_t *off); | |
| static ssize_t crackme_write(struct file* filp, const char __user *buffer, size_t len, loff_t *off); | |
| #ifdef HAVE_PROC_OPS | |
| static const struct proc_ops proc_file_fops = { | |
| .proc_read = crackme_read, | |
| .proc_write = crackme_write, | |
| }; | |
| #else | |
| static const struct file_operations proc_file_fops = { | |
| .read = crackme_read, | |
| .write = crackme_write, | |
| }; | |
| #endif | |
| static int __init crackme_init(void) | |
| { | |
| proc_file = proc_create(CHALLENGE_NAME, 0666, NULL, &proc_file_fops); | |
| if (NULL == proc_file) { | |
| pr_alert("Error: could not initialize /proc/%s\n", CHALLENGE_NAME); | |
| return -ENOMEM; | |
| } | |
| pr_info("Hello! This is a kernel module crackme challenge.\nEnter the correct password to win.\n"); | |
| pr_info("/proc/%s created\n", CHALLENGE_NAME); | |
| return 0; | |
| } | |
| /* Called when the /proc file is read from. Prints a message to dmesg. */ | |
| static ssize_t crackme_read(struct file* filp, char __user *buffer, size_t len, loff_t *offset) | |
| { | |
| const char *msg; | |
| size_t msg_len; | |
| // Prevent multiple reads from the /proc file | |
| if (*offset > 0) | |
| return 0; // EOF | |
| if (authorized) { | |
| msg = "You won! Please like and subscribe\n"; | |
| } else { | |
| msg = "Enter the correct password in order to win!\n"; | |
| } | |
| msg_len = strlen(msg); | |
| // Copy message to user-space | |
| if (copy_to_user(buffer, msg, msg_len)) | |
| return -EINVAL; | |
| *offset = msg_len; // mark read as done | |
| return msg_len; | |
| } | |
| /* Called when the /proc file is written to. Compares user input with the correct password. */ | |
| static ssize_t crackme_write(struct file *file, const char __user *buffer, | |
| size_t len, loff_t *off) | |
| { | |
| char dest[BUF_MAX_LEN]; | |
| size_t length = len; | |
| // Truncate buffer size if its about max length | |
| if (length >= BUF_MAX_LEN) | |
| length = BUF_MAX_LEN - 1; | |
| // Read user input into destination buffer | |
| if (copy_from_user(dest, buffer, length)) { | |
| pr_alert("copy_from_user failed\n"); | |
| return -EINVAL; | |
| } | |
| // compare user input with correct password | |
| if(!strcmp(dest, PASSWORD)) | |
| authorized = true; | |
| return len; | |
| } | |
| static void __exit crackme_exit(void) | |
| { | |
| proc_remove(proc_file); | |
| pr_info("/proc/%s removed\n", CHALLENGE_NAME); | |
| } | |
| module_init(crackme_init); | |
| module_exit(crackme_exit); | |
| MODULE_LICENSE("GPL"); | |
| MODULE_AUTHOR("@_jasonturley"); | |
| MODULE_DESCRIPTION("A simple crackme challenge"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment