Introduction
Welcome, we are gonna be walking through the challenges created for hackfridays during the month of October, hosted on CTFroom. I had fun creating this challenges and I hope you had fun playing the same. The challenges were meant to introduce you to kernel exploitation lets learn.
Kernel Adventures 1
The first challenge was sort of straight forward and was accessible here kernel_adventures
The kernel character device /dev/chall contains an ioctl handler that checks for the magic value 0xdeadbeef. When the comparison succeeds the handler directly escalates the caller’s credentials (e.g. by calling commit_creds(prepare_kernel_cred(0))). An unprivileged user can call ioctl() with that magic value and receive root. This is a trivial but common backdoor/debugging mistake.

POC
| |
All that is needed is send the magic value to ioctl and we escalate our privileges automatically.
Kernel Adventures 2
The challenge is accessible here Kernel_adventures
This challenge involves a vulnerable Linux kernel module that exposes a character device /dev/chall with improper access control checks. The vulnerability allows local privilege escalation from an unprivileged user to root.
Vulnerability Analysis
The Bug: Integer Underflow + Bit Check Bypass
The core vulnerability lies in the VULN_SET_ADMIN ioctl handler:
| |
The check level + 1 < 10 suffers from an integer underflow vulnerability. When level is 0xFFFFFFFF (or -1 as signed), level + 1 becomes 0, which is indeed less than 10. This allows an attacker to set is_admin to 0xFFFFFFFF.
The Escalation Mechanism
In the VULN_GET_FLAG handler, there’s an “accidental” privilege escalation:
| |
Since 0xFFFFFFFF & 0x80000000 is non-zero, this condition triggers when is_admin has the highest bit set.
Final Flag Access Check
After potential escalation, the flag is accessible if either:
The process is root (
uid_eq(current_uid(), GLOBAL_ROOT_UID))OR the lowest bit of
is_adminis set (po->is_admin & 1u)
Since 0xFFFFFFFF has both the highest bit (triggers escalation) and lowest bit set, both conditions are satisfied.
Exploitation Strategy
Step-by-Step Attack
Open the device: Gain access to the vulnerable driver
Set admin to -1: Trigger the integer underflow to set
is_admin = 0xFFFFFFFFTrigger GET_FLAG: This both escalates privileges and retrieves the flag
Spawn root shell: Use the gained root privileges
POC
| |
Agent 47
The challenge is accessible here Agent47
This is a reverse engineering challenge where the flag is split into multiple XOR-encrypted parts. The program checks a password and reveals the flag if the correct password is provided.
Analysis
Key Components
XOR Encryption: All flag parts are XOR-encrypted with key
0x5AFlag Structure: The flag appears to follow the format
flag{...}Password Check: Uses a weak function
check_password()that can be easily bypassed
XOR Decryption
The encryption uses a simple XOR cipher:
| |
Encrypted Flag Parts
The flag is split into 8 encrypted parts:
part1[] = { 0x3C, 0x36, 0x3B, 0x3D, 0x21, 0 }part2[] = { 0x3E, 0x6E, 0x6B, 0x3E, 0x62, 0 }part3[] = { 0x39, 0x3E, 0x63, 0x62, 0x3C, 0 }part4[] = { 0x6A, 0x6A, 0x38, 0x68, 0x6A, 0 }part5[] = { 0x6E, 0x3F, 0x63, 0x62, 0x6A, 0 }part6[] = { 0x6A, 0x6A, 0x63, 0x63, 0x62, 0 }part7[] = { 0x3F, 0x39, 0x3C, 0x62, 0x6E, 0 }part8[] = { 0x68, 0x6D, 0x3F, 0x27, 0 }
Solutions
Method 1: Bypass the Password Check
Since check_password() is declared as weak, we can provide our own implementation:
| |
Compile and run:
| |

Method 2: Manual XOR Decryption
We can manually decrypt each part using the XOR key 0x5A:
| |