<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Kernel on kiperZ</title>
    <link>https://kiperz.dev/kernel/</link>
    <description>Recent content in Kernel on kiperZ</description>
    <generator>Hugo -- 0.147.7</generator>
    <language>en</language>
    <lastBuildDate>Fri, 21 Aug 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://kiperz.dev/kernel/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Sofirium</title>
      <link>https://kiperz.dev/kernel/sofirium/</link>
      <pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/sofirium/</guid>
      <description>&lt;p&gt;A character driver that keeps a singly linked list of &amp;ldquo;NFTs&amp;rdquo;. Deleting the collection
frees every node and forgets to clear a single pointer, so the whole list stays walkable
after the free. That is the entire bug. Getting from there to a root shell took me
longer than it should have, because the obvious fake chunk placement poisons the
kmalloc-512 freelist, and the technique I wanted to finish with allocates from
kmalloc-512 itself.&lt;/p&gt;</description>
    </item>
    <item>
      <title>僕と契約して、魔法少女になってよ！ - THJCC CTF 2026</title>
      <link>https://kiperz.dev/kernel/qb---thjcc-ctf-2026/</link>
      <pubDate>Fri, 05 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/qb---thjcc-ctf-2026/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;A single-byte NULL off-by-one in a &lt;code&gt;kmalloc-1024&lt;/code&gt; object is leveraged into a &lt;code&gt;pipe_buffer.page&lt;/code&gt; LSB clear → page-level UAF → cross-cache reclaim into &lt;code&gt;filp_cachep&lt;/code&gt; → &lt;code&gt;struct file-&amp;gt;f_mode&lt;/code&gt; overwrite → page-cache code injection into &lt;code&gt;/bin/busybox&lt;/code&gt; (Dirty-Pipe style) → root code execution. &lt;strong&gt;Fully leakless&lt;/strong&gt;: no kernel address is ever read.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#ebdbb2;background-color:#282828;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Description: Make a contract and become a magical girl!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Target: Linux &lt;strong&gt;6.17.7&lt;/strong&gt;, x86-64. Mitigations on: SMEP, SMAP, KPTI (&lt;code&gt;pti=on&lt;/code&gt;), KASLR, &lt;code&gt;dmesg_restrict=1&lt;/code&gt;, &lt;code&gt;kptr_restrict=1&lt;/code&gt;. The interactive shell runs as &lt;strong&gt;uid 1000&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Messenger - LACTF 2025</title>
      <link>https://kiperz.dev/kernel/messenger/</link>
      <pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/messenger/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;A 3-byte heap OOB write in &lt;code&gt;msgsnd()&lt;/code&gt; is leveraged into a page-level UAF and then into root via a &lt;code&gt;struct cred&lt;/code&gt; overwrite (PageJack).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#ebdbb2;background-color:#282828;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Description: i love sending messages, so i made it possible to add just a few more bytes to them
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;vulnerability&#34;&gt;Vulnerability&lt;/h2&gt;
&lt;p&gt;A custom Linux 6.10.9 kernel ships with the following patch in &lt;code&gt;ipc/msgutil.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#ebdbb2;background-color:#282828;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b8bb26;font-weight:bold&#34;&gt;@@ -93,7 +93,7 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b8bb26;font-weight:bold&#34;&gt;&lt;/span&gt;        return ERR_PTR(-ENOMEM);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    alen = min(len, DATALEN_MSG);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#282828;background-color:#fb4934&#34;&gt;-   if (copy_from_user(msg + 1, src, alen))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#282828;background-color:#fb4934&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#282828;background-color:#b8bb26&#34;&gt;+   if (copy_from_user(msg + 1, src, alen + 3))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#282828;background-color:#b8bb26&#34;&gt;&lt;/span&gt;        goto out_err;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;load_msg()&lt;/code&gt;, invoked by &lt;code&gt;msgsnd()&lt;/code&gt;, copies &lt;code&gt;alen + 3&lt;/code&gt; bytes from userland into a freshly-allocated &lt;code&gt;msg_msg&lt;/code&gt; slab object. Three bytes are written past the end of the slot, into the next object in the same slab. The allocation size (via &lt;code&gt;msgsz&lt;/code&gt;) and the three overflow bytes (bytes &lt;code&gt;[msgsz, msgsz+1, msgsz+2]&lt;/code&gt; of the user buffer) are both attacker-controlled.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Phantom - 0xfunctf 2026</title>
      <link>https://kiperz.dev/kernel/phantom/</link>
      <pubDate>Sat, 14 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/phantom/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Physical page UAF via persistent &lt;code&gt;mmap&lt;/code&gt; → spray to reallocate the page as a PTE → forge a PTE to the physical page of &lt;code&gt;modprobe_path&lt;/code&gt; → overwrite via &lt;code&gt;/proc/self/mem&lt;/code&gt; → trigger &lt;code&gt;modprobe&lt;/code&gt; → root.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenge Files:&lt;/strong&gt; A &lt;code&gt;.tar.gz&lt;/code&gt; archive containing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#ebdbb2;background-color:#282828;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar -ztvf phantom.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- root/root   1306874 2026-02-14 08:00 initramfs.cpio.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- root/root  12430112 2026-02-14 04:11 bzImage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- root/root      8848 2026-02-13 22:24 phantom.ko
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x root/root       251 2026-02-13 06:39 run.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- root/root       145 2026-02-13 22:24 interface.h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This writeup focuses on the physical page UAF, PTE reallocation, and the overwrite of &lt;code&gt;modprobe_path&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hello Rootkitty (Harder)</title>
      <link>https://kiperz.dev/kernel/hello-rootkitty-harder/</link>
      <pubDate>Thu, 30 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/hello-rootkitty-harder/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Same rootkit, harder exploitation. No SMEP/SMAP means we can execute userspace code from kernel context (ret2usr). Overflow the buffer → execute our shellcode → disable CR0 write protection → restore syscall table → iretq back to userspace. Oh, and we can also get root shell as a bonus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;pwn&lt;/code&gt; &lt;code&gt;kernel&lt;/code&gt; &lt;code&gt;rootkit&lt;/code&gt; &lt;code&gt;ret2usr&lt;/code&gt; &lt;code&gt;privilege-escalation&lt;/code&gt; &lt;code&gt;CR0&lt;/code&gt; &lt;code&gt;iretq&lt;/code&gt; &lt;code&gt;SMEP-bypass&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenge Files:&lt;/strong&gt; Kernel module (rootkit), same as before&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This writeup assumes you&amp;rsquo;ve read the previous &amp;ldquo;Hello Rootkitty&amp;rdquo; challenge. I&amp;rsquo;ll focus on the advanced techniques specific to the &amp;ldquo;Harder&amp;rdquo; version without repeating the basics.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hello Rootkitty</title>
      <link>https://kiperz.dev/kernel/hello-rootkitty/</link>
      <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/hello-rootkitty/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Kernel rootkit hides &lt;code&gt;ecsc_flag_*&lt;/code&gt; files but has a buffer overflow in its &lt;code&gt;strcpy()&lt;/code&gt;. Create a super long filename to overflow the buffer → control RIP → call &lt;code&gt;cleanup_module()&lt;/code&gt; to restore original syscalls → profit!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Challenge Files:&lt;/strong&gt; Kernel module (rootkit)&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is my first CTF writeup! At the time I solved this challenge, I was just starting out with heap exploitation. There are probably cleaner/simpler ways to solve this, but this approach worked for me. If you spot improvements, feel free to share!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kexpita</title>
      <link>https://kiperz.dev/kernel/kexpita/</link>
      <pubDate>Sat, 21 Jun 2025 00:00:00 +0000</pubDate>
      <guid>https://kiperz.dev/kernel/kexpita/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Buffer overflow in a kernel module → RIP control → ROP chain to bypass SMEP/SMAP → &lt;code&gt;commit_creds(prepare_kernel_cred(0))&lt;/code&gt; → root shell&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is my first kernel exploitation writeup! This was a school project at EPITA, not a CTF challenge. I was learning kernel security concepts for the first time, so the approach might not be the most optimized. Feedback welcome!&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;challenge-overview&#34;&gt;Challenge Overview&lt;/h2&gt;
&lt;p&gt;This is a class project where we had to exploit a vulnerable kernel module called &lt;strong&gt;kexpita&lt;/strong&gt;. The module is a character device driver with a classic buffer overflow vulnerability.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
